Eseguire comandi remoti, staccandosi completamente dalla connessione ssh


48

Ho 2 computer localpce remoteserver.

Ho bisogno localpcdi eseguire alcuni comandi su remoteserver. Una delle cose che deve fare è avviare uno script di backup che viene eseguito per un numero di ore. Vorrei che il comando localpc"sparasse" e che poi funzionasse in modo completamente indipendente remoteserver, come se localpcnon ci fosse mai stato in primo luogo.

Questo è quello che ho fatto finora:

remoteserver contiene ha lo script:

/root/backup.sh

localpc è programmato per eseguire questo:

ssh root@remoteserver 'nohup /root/backup.sh' &

Lo sto facendo nel modo giusto? C'è un modo migliore per farlo? Incontrerò qualche problema nel farlo in questo modo?


stackoverflow.com/questions/19996089/… e stackoverflow.com/questions/29142/… forniscono una serie di approcci utili per questo problema che non utilizza screen / tmux ecc ...
Paul

Risposte:


47

Probabilmente si dovrebbe utilizzare screensulla macchina remota, di avere un vero e proprio comando distaccato:

ssh root@remoteserver screen -d -m ./script

Mi piace questa idea. Al termine dello script, lo schermo continuerà a funzionare ... e dovrei in qualche modo riconnetterlo alla prossima volta che volevo eseguirlo, giusto?
LVLAaron,

@AaronJAnderson: no, dato che il comando non è una shell, quando termina anche quella sessione dello schermo termina.
enzotib,

52

Chiudi, ma non esattamente.

Indipendentemente da qualsiasi terminale

ssh root@remoteserver '/root/backup.sh </dev/null >/var/log/root-backup.log 2>&1 &'

È necessario chiudere tutti i descrittori di file collegati al socket ssh, poiché la sessione ssh non si chiuderà fintanto che in alcuni processi remoti il ​​socket è aperto. Se non sei interessato all'output dello script (presumibilmente perché lo script stesso si occupa di scrivere in un file di registro), reindirizzalo a /dev/null(ma nota che ciò nasconderà errori come l'impossibilità di avviare lo script).

L'uso nohupnon ha alcun effetto utile qui. nohuporganizza per il programma che non riceve un segnale HUP se il terminale di controllo del programma scompare, ma qui non c'è un terminale, quindi nulla invierà un SIGHUP al processo di punto in bianco. Inoltre, nohupreindirizza l'output standard e l'errore standard (ma non l'input standard) su un file, ma solo se sono collegati a un terminale, che, di nuovo, non lo sono.

Staccare da un terminale

 aaron@localpc$ ssh root@remoteserver
 root@remoteserver# nohup /root/backup.sh </dev/null &
 nohup: appending output to `nohup.out'
 [1] 12345
 root@remoteserver# exit
 aaron@localpc$ 

Utilizzare nohupper staccare lo script dal suo terminale di controllo in modo che non riceva un SIGHUP quando il terminale scompare. nohupreindirizza anche l'output standard dello script e l'errore standard su un file chiamato nohup.outse sono collegati al terminale; devi occuparti tu stesso degli input standard.

Mantenere un terminale remoto

Se si desidera mantenere il comando in esecuzione in un terminale remoto ma non averlo collegato alla sessione SSH, eseguirlo in un multiplexer terminale come Screen o Tmux .

ssh root@remoteserver 'screen -S backup -d -m /root/backup.sh'

Successivamente è possibile riconnettersi al terminale su cui è in esecuzione lo script invocando screen -S backup -rdcome root su quella macchina.

Automatizzare un comando remoto

Per una protezione leggermente migliore, non aprire gli accessi root remoti diretti troppo ampiamente. Creare una coppia di chiavi per scopi speciali e dargli un comando forzato /root/.ssh/authorized_keys. Il contenuto del file della chiave pubblica è AAAA…== wibble@example.com; aggiungere un elenco di opzioni separato da virgole, incluso il command="…"quale specifica che la chiave può essere utilizzata solo per eseguire questo comando specifico. Assicurati di mantenere le opzioni e la chiave tutte su una riga.

command="/root/backup.sh </dev/null >/dev/null 2>/dev/null &",no-port-forwarding,no-agent-forwarding,no-x11-forwarding,no-pty,no-user-rc AAAA…== wibble@example.com

Ho provato il primo comando che hai elencato. Non fa sfondo sulla casella che ha eseguito il comando. Il cursore si trova lì e attende il completamento ... forse è un bug?
LVLAaron,

Potrebbe essere necessario reindirizzare stdin a / dev / null sul sistema remoto. Questo potrebbe essere il motivo per cui ssh non sta uscendo.
KeithB,

Vorrei aggiungere l' -fopzione per ottenere ssh in 'background' (cioè terminare, chiudere le connessioni) sul lato locale. Questo funzionerà insieme al &. nohupè facoltativo in questo caso, ma potresti considerare di utilizzare setsidinvece.
Alexios,

@KeithB Il reindirizzamento di stdin è parte di esso, ma devo anche reindirizzare stdout e stderr: nohup non lo farà qui perché non sono terminali, e in realtà nohup non è utile qui.
Gilles 'SO- smetti di essere malvagio'

1
@erikbwork Nota che non ho assolutamente idea di queste cose, ma a seguito della discussione e dei commenti: Gilles non usa l'opzione -t nei suoi comandi, quindi non verrà stabilito alcun pseudo terminale, né sul client né sul server lato. Pertanto, nessun HUP verrà inviato.
Binarus

12

La ricetta standard per eseguire un comando remoto da un accesso remoto come SSH è la seguente:

nohup command </dev/null >command.log 2>&1 &

Se commandè uno script di shell che si occupa della registrazione su un file stesso, è possibile passare command.loga /dev/null. Una volta iniziato, disconnettiti subito.

Hai bisogno di tutto su quella linea.

nohup dice alla shell di non disturbare il processo se la sessione di login è disconnessa.

</dev/null gli dice di non aspettare mai l'input

>command.log gli dice di inviare qualsiasi messaggio a questo file di registro denominato

2>&1gli dice di inviare qualsiasi messaggio stderr allo stesso file di registro. In alcuni casi è meglio avere due file, il secondo per raccogliere i messaggi di errore e il primo per raccogliere i normali messaggi di attività. Ciò può semplificare la verifica del corretto funzionamento di tutto.

& gli dice di staccare questo processo ed eseguirlo in background come processo daemon.


10

Questa discussione è stata molto utile, ma la mia soluzione doveva essere un po 'diversa.

Non mi piace la soluzione dello schermo perché lascia un processo dello schermo in esecuzione che non mi serve. I reindirizzamenti e le nohup utilizzati in questo modo:

ssh root@remoteserver '/root/backup.sh </dev/null >/var/log/root-backup.log 2>&1 &'

NON funzionavano per me se usato con il comando ssh.

Ho creato uno script wrapper sul computer remoto che esegue lo script effettivo. Lo script wrapper imposta il reindirizzamento e nohup. Qualcosa come questo:

backupwrapper.sh:
nohup backup.sh > /dev/null 2>&1 &

Quindi sul mio computer client corro (non notate alcun reindirizzamento):

# ssh remotemachine "backupwrapper.sh"
#

Il comando ssh ritorna immediatamente, la connessione viene terminata e lo script viene lasciato in esecuzione.


6

Come dice Nils , è un rischio per la sicurezza consentire a root di accedere tramite ssh. E sconsiglio di eseguire qualsiasi lavoro sostanziale su una macchina senza un registro. Se qualcosa va storto, ti consigliamo di avere alcuni messaggi di risoluzione dei problemi. Ci sono altre risposte che ti mostrano come farlo. Ma ecco come ti consiglio di realizzare esattamente ciò che hai chiesto. È tutto integrato in sh (1). Non c'è bisogno dello schermo GNU (anche se penso che sia una soluzione intelligente). Aggiunge questa stringa al comando: >&- 2>&- <&- &. >&-significa vicino stdout. 2>&-significa stretto stderr. <&-significa stretto stdin. &significa correre in background, ad es

$ ssh myhost 'sleep 30 >&- 2>&- <&- &'
# ssh returns right away, and your sleep job is running remotely
$

0

Dovresti attivare il comando remoto in background remoteserver. Il modo in cui lo fai farà da sfondo al comando ssh localpc.

A parte questo, è una cattiva idea consentire root-ssh.

Quindi imposta su remoteserver: Una riga sudoers che verrà eseguita /root/backup.shcome root dall'utente backup.

È possibile creare quell'utente senza password "valida".

Inserisci il comando sudo /root/backup.sh &come comando in ~backup/.ssh/authorized_keys- insieme alla chiave pubblica di localpc(chiunque attivi quello script).


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.