dev-app/src/lib/ssh/ssh.ts
2024-12-04 20:10:54 +08:00

104 lines
3.0 KiB
TypeScript

// ssh -L 8080:localhost:80 -L 9090:localhost:90 user@remote-server
import { ChildProcess, spawn } from 'child_process';
type Options = {
name: string;
values: SSHValue[];
};
export type SSHValue = {
localPort: number;
remoteHost: string; // localhost
remotePort: number;
remote?: string; //sky config配置
status?: 'active' | 'inactive';
};
export const demos: SSHValue[] = [
{
localPort: 3000,
remoteHost: 'localhost',
remotePort: 3000,
remote: 'diana',
},
{
localPort: 5244,
remoteHost: 'localhost',
remotePort: 5244,
remote: 'diana',
},
];
export class SSHServer {
name = 'diana';
values: SSHValue[] = [];
childProcess: ChildProcess | null = null;
isRunning = false;
constructor(opts?: Options) {
this.name = opts?.name || this.name;
this.values = opts?.values || demos;
}
start(options?: Options) {
try {
const remote = options?.name || this.name;
const demos = options?.values || this.values;
const _port = demos.filter((item) => item.status === 'active');
if (_port.length === 0) {
this.isRunning = false;
return;
}
const params = _port
.map((item) => {
return ['-L', `${item.localPort}:${item.remoteHost}:${item.remotePort}`];
})
.flat();
const childProcess = spawn(
'ssh',
[
'-N', // 不执行远程命令
// '-f', // 后台运行
'-o',
'ServerAliveInterval=60', // 每60秒发送一次心跳包
'-o',
'ServerAliveCountMax=3', // 尝试3次心跳失败后断开连接
'-T',
...params,
remote,
],
{
// stdio: 'ignore',
stdio: 'inherit',
killSignal: 'SIGINT',
},
);
this.childProcess = childProcess;
childProcess.stdout?.on('data', (data) => {
console.log('childProcess', data.toString());
});
childProcess.on('error', (err: any) => {
if (err.code === 'EADDRINUSE') {
console.error('端口被占用:', err);
return;
}
console.error('Failed to start SSH process:', err);
});
childProcess.on('exit', (code, signal) => {
console.log('SSH process exited:', code, signal);
this.isRunning = false;
});
this.isRunning = true;
console.log('当前ssh -L 服务启动', this.name);
// 监听的端口是
// console.log('监听的端口是:', _port.map((item) => `[${item.localPort},${item.remotePort}]`).join(','));
console.log('监听的端口是:', _port.map((item) => item.localPort).join(','));
} catch (error) {
console.error('启动失败:', error);
}
}
stop() {
if (this.childProcess) {
console.log('正在停止 ssh -L 服务:', this.name);
this.childProcess.kill(); // 发送默认信号 SIGTERM
this.childProcess = undefined;
} else {
console.log('没有正在运行的 ssh -L 服务.');
}
}
}