ssh si blocca quando il comando viene richiamato direttamente, ma esce in modo pulito quando viene eseguito in modo interattivo
Domanda
Devo avviare un server sul computer remoto e recuperare il numero di porta su cui si sta installando il processo del server.Quando richiamato, il server ascolterà su una porta casuale e restituirà il numero di porta su stderr.
Desidero automatizzare il processo di accesso al computer remoto, avvio del processo e recupero del numero di porta.Ho scritto uno script Python chiamato "invokejob.py
" che risiede sulla macchina remota per fungere da wrapper che richiama il lavoro e quindi restituisce il numero di porta, assomiglia a questo:
import re, subprocess
executable = ... # Name of executable
regex = ... # Regex to extract the port number from the output
p = subprocess.Popen(executable,
bufsize=1, # line buffered
stderr=subprocess.PIPE
)
s = p.stderr.readline()
port = re.match(regex).groups()[0]
print port
Se accedo in modo interattivo, questo script funziona:
$ ssh remotehost.example.com
Last login: Thu Aug 28 17:31:18 2008 from localhost
$ ./invokejob.py
63409
$ exit
logout
Connection to remotehost.example.com closed.
(Nota:disconnessione riuscita, non si è bloccato).
Tuttavia, se provo a invocarlo dalla riga di comando, si blocca:
$ ssh remotehost.example.com invokejob.py
Qualcuno sa perché si blocca nel secondo caso e cosa posso fare per evitarlo?
Tieni presente che devo recuperare l'output del programma, quindi non posso semplicemente utilizzare il flag ssh "-f" o reindirizzare l'output standard.
Soluzione
s = p.stderr.readline()
Sospetto che sia la riga sopra.Quando invochi un comando direttamente tramite ssh, non ottieni il tuo pty completo (supponendo Linux), e quindi nessuno stderr da cui leggere.
Quando accedi in modo interattivo, stdin, stdout e stderr sono impostati per te e quindi il tuo script funziona.
Altri suggerimenti
@Ben Collins
Penso che tu abbia ragione riguardo al fatto che stderr sia un problema.Sono abbastanza sicuro che si stia bloccando sulla chiamata readline().
Alla fine ho rinunciato e ho deciso di utilizzare il modulo pxssh di aspettativa per automatizzare la mia interazione con una sessione ssh.
@Misha M
Sfortunatamente, il trucco del punto e virgola non funziona qui:si blocca durante l'esecuzione del mio programma.
cosa succede se fai quanto segue:
ssh <remote host> '<your command> ;<your regexp using awk or something>'
Per esempio
ssh <remote host> '<your program>; ps aux | awk \'/root/ {print $2}\''
Questo si collegherà a , eseguirà e quindi stamperà ogni PSID per qualsiasi utente root o qualsiasi processo con root nella sua descrizione.
Ho utilizzato questo metodo per eseguire tutti i tipi di comandi su macchine remote.Il problema è racchiudere i comandi che si desidera eseguire tra virgolette singole (') e separare ciascun comando con un punto e virgola (;).