2014-09-11 2 views
1

간단한 CLI에서 작업하고 있는데, 그 중 하나는 ssh를 원격 서버에 실행하는 것입니다. ,Node.js readline with interactive child_process spawning

#!/usr/bin/env node 

var spawn = require('child_process').spawn; 
var readline = require('readline'); 

var iface =readline.createInterface({ 
    input: process.stdin, 
    output: process.stdout 
}); 
iface.setPrompt("host> "); 

iface.on("line", function(line) { 
    if (line.trim() == "") { 
    return iface.prompt(); 
    } 
    var host = line.split()[0]; 
    iface.pause(); // PAUSING STDIN! 
    var proc = spawn('ssh', [ host, '-l', 'root', '-o', 'ConnectTimeout=4' ], { stdio: [0,1,2] }); 
    proc.on("exit", function(code, signal) { 
    iface.prompt(); 
    }); 
}); 
iface.prompt(); 

내가이 줄을 제거하는 경우에만, 일부 기호가 원격 서버에 의해 사로 잡았됩니다 STDIN에서 읽을 자식 프로세스 수 있도록 iface.pause()를 사용 이 무슨 뜻인지의 예입니다 다른 것들 - 로컬 readline. 그러나이 pause()은 실제로 stdin을 고정 시키므로 ssh가 연결을 기다리는 시간이 너무 길거나 암호를 묻는 경우 stdin이 일시 중지 되었기 때문에 어떤 문자도 보낼 수 없습니다. 나는 정말로 ssh가 어떻게 연결 (일시 중지 된 상태)을 처리했는지 알지 못한다. 그러나 정상적으로 연결되었지만 어떻게 든 작동한다. 문제는 "대화 형 자식 프로세스가 작동하는 동안 그것을 일시 중지하지 않고 readline에서 stdin을 분리하고 자식 프로세스가 완료된 후 다시 연결하는 방법"입니다.

답변

0

이 문제에 대한 한 가지 해결책은 ssh 클라이언트 연결을 수행하는 데 하위 프로세스를 사용하지 않는 것일 수 있습니다. ssh2이라는 노드를위한 pure-JavaScript ssh 클라이언트가 있습니다. 많은 자식 프로세스를 생성하는 것보다 가벼울뿐만 아니라 작업하기가 훨씬 쉽습니다.

+0

@mscdex 여기에서 반갑습니다. 이미'ssh2' 모듈을 사용해 보았습니다. 그리고 한 번에 여러 서버에서 작업을 병렬로 실행하는 데 정말 좋습니다. 그러나 나를 위해'ssh2'를 통해 대화식 쉘을 구현하는 것은 정말 골칫거리입니다. 탭 자동 완성 및 기타 원시 tty 동작을 중단시키지 않고 창 크기 조정을 처리하기 위해 수행해야하는 작업의 수는 원시 ssh를 사용하는 것이 더 간단하다고 생각하게 만듭니다. –

3

산란 과정 직전에 setRawMode(false)을 추가하여 문제를 해결했습니다. 필자가 이해하는 한, 이는 노드 릴리즈에서 기능 키의 키 누르기를 처리하는 모든 변환을 표준으로합니다. 해결 된 코드 버전은 다음과 같습니다.

var spawn = require('child_process').spawn; 
var readline = require('readline'); 

var iface =readline.createInterface({ 
    input: process.stdin, 
    output: process.stdout 
}); 
iface.setPrompt("host> "); 

iface.on("line", function(line) { 
    if (line.trim() == "") { 
    return iface.prompt(); 
    } 
    var host = line.split()[0]; 
    iface.pause(); // PAUSING STDIN! 
    process.stdin.setRawMode(false); // Releasing stdin 
    var proc = spawn('ssh', [ host, '-l', 'root', '-o', 'ConnectTimeout=4' ], { stdio: [0,1,2] }); 
    proc.on("exit", function(code, signal) { 
    // Don't forget to switch pseudo terminal on again 
    process.stdin.setRawMode(true); 
    iface.prompt(); 
    }); 
}); 
+0

'childprocess'에서 stdin에 직접 쓰려고 했습니까? 나는'proce.stdin.on ('data', iface.input.write.bind (iface.input))'도 사용할 수 있습니다. – stringparser

+0

감사합니다. 이것은 매우 도움이되었습니다! –