// 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 服务.'); } } }