Ho un processo che è già in esecuzione da molto tempo e non voglio interromperlo.
Come posso metterlo sotto nohup (ovvero, come faccio a farlo continuare anche se chiudo il terminale?)
Ho un processo che è già in esecuzione da molto tempo e non voglio interromperlo.
Come posso metterlo sotto nohup (ovvero, come faccio a farlo continuare anche se chiudo il terminale?)
Risposte:
Usando il Job Control di bash per inviare il processo in background:
bg
per eseguirlo in background.disown -h [job-spec]
dove [job-spec] è il numero del lavoro (come %1
per il primo lavoro in esecuzione; trova il tuo numero con il jobs
comando) in modo che il lavoro non venga interrotto alla chiusura del terminale.disown -h
forse è la risposta più esatta: "fare in modo che il disconnessione si comporti più come un nohup (cioè i lavori rimarranno nell'albero del processo della shell corrente fino a quando non si esce dalla shell) Ciò consente di vedere tutti i lavori avviati da questa shell ". (da [ quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/… )
disown
, disown rende un processo un demone, il che significa che l'input / output standard viene reindirizzato a / dev / null. Quindi, se hai intenzione di rinnegare un lavoro, è meglio avviarlo accedendo a un file, ad esempiomy_job_command | tee my_job.log
disown
dissocia qualsiasi tubo dal processo. Per ricollegare i tubi, utilizzare gdb
come descritto in questa discussione . Più specificamente, questo post .
Supponiamo che anche per qualche motivo Ctrl+ Znon ps
funzioni , vai su un altro terminale, trova l'id di processo (usando ) ed esegui:
kill -SIGSTOP PID
kill -SIGCONT PID
SIGSTOP
sospenderà il processo e SIGCONT
riprenderà il processo, in background. Quindi ora chiudere entrambi i terminali non interromperà il processo.
disown %1
il primo terminale prima di chiuderlo.
kwin
dopo un crash senza pensare alle conseguenze). Quindi se avessi fermato Kwin, tutto sarebbe congelato e non avrei avuto possibilità di correre bg
!
Il comando per separare un lavoro in esecuzione dalla shell (= lo rende nohup) è disown
un comando shell di base.
Da bash-manpage (man bash):
disown [-ar] [-h] [jobspec ...]
Senza opzioni, ogni jobspec viene rimosso dalla tabella dei lavori attivi. Se viene fornita l'opzione -h, ogni jobspec non viene rimosso dalla tabella, ma è contrassegnato in modo che SIGHUP non venga inviato al lavoro se la shell riceve un SIGHUP. Se non è presente jobspec e non viene fornita né l'opzione -a né -r, viene utilizzato il lavoro corrente. Se non viene fornito jobspec, l'opzione -a significa rimuovere o contrassegnare tutti i lavori; l'opzione -r senza argomento jobspec limita l'operazione ai lavori in esecuzione. Il valore restituito è 0 a meno che un jobspec non specifichi un lavoro valido.
Ciò significa che è semplice
disown -a
rimuoverà tutti i lavori dalla tabella dei lavori e li renderà nohup
disown -a
rimuove tutti i lavori. Un semplice disown
rimuove solo il lavoro corrente. Come dice la pagina man nella risposta.
Queste sono buone risposte sopra, volevo solo aggiungere un chiarimento:
Non puoi fare disown
un pid o un processo, sei disown
un lavoro, e questa è una distinzione importante.
Un lavoro è qualcosa che è una nozione di un processo che è collegato a una shell, quindi è necessario gettare il lavoro in background (non sospenderlo) e quindi rinnegarlo.
Problema:
% jobs
[1] running java
[2] suspended vi
% disown %1
Vedi http://www.quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/jobcontrol/ per una discussione più dettagliata di Unix Job Control.
Sfortunatamente disown
è specifico per bash e non è disponibile in tutte le shell.
Alcune versioni di Unix (ad es. AIX e Solaris) hanno un'opzione sul nohup
comando stesso che può essere applicata a un processo in esecuzione:
nohup -p pid
AIX
e Solaris
. "Le versioni AIX e Solaris di nohup hanno un'opzione -p che modifica un processo in esecuzione per ignorare i futuri segnali SIGHUP. A differenza del sopra descritto difetto di bash, nohup -p accetta gli ID di processo.". Fonte
La risposta di Node è davvero eccezionale, ma ha lasciato aperta la domanda su come ottenere reindirizzamento di stdout e stderr. Ho trovato una soluzione su Unix e Linux , ma non è completa. Vorrei unire queste due soluzioni. Ecco qui:
Per il mio test ho realizzato un piccolo script bash chiamato loop.sh, che stampa il pid di se stesso con un minuto di sonno in un ciclo infinito.
$./loop.sh
Ora ottieni il PID di questo processo in qualche modo. Di solito ps -C loop.sh
è abbastanza buono, ma è stampato nel mio caso.
Ora possiamo passare a un altro terminale (o premere ^ Z e nello stesso terminale). Ora gdb
dovrebbe essere collegato a questo processo.
$ gdb -p <PID>
Questo interrompe lo script (se in esecuzione). Il suo stato può essere verificato da ps -f <PID>
, dove il STAT
campo è 'T +' (o nel caso di ^ Z 'T'), che significa (man ps (1))
T Stopped, either by a job control signal or because it is being traced
+ is in the foreground process group
(gdb) call close(1)
$1 = 0
Chiudi (1) restituisce zero in caso di successo.
(gdb) call open("loop.out", 01102, 0600)
$6 = 1
Apri (1) restituisce il nuovo descrittore di file in caso di successo.
Questa apertura è uguale a open(path, O_TRUNC|O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)
. Invece di O_RDWR
O_WRONLY
potrebbe essere applicato, ma /usr/sbin/lsof
dice 'u' per tutti i gestori di file std * ( FD
colonna), che è O_RDWR
.
Ho controllato i valori nel file di intestazione /usr/include/bits/fcntl.h.
Il file di output potrebbe essere aperto O_APPEND
, come nohup
farebbe, ma questo non è suggerito da man open(2)
, a causa di possibili problemi di NFS.
Se otteniamo -1 come valore di ritorno, call perror("")
stampa il messaggio di errore. Se abbiamo bisogno dell'errno, usa il p errno
comando gdb.
Ora possiamo controllare il file appena reindirizzato. /usr/sbin/lsof -p <PID>
stampe:
loop.sh <PID> truey 1u REG 0,26 0 15008411 /home/truey/loop.out
Se vogliamo, possiamo reindirizzare stderr a un altro file, se vogliamo usare call close(2)
e call open(...)
usare nuovamente un altro nome file.
Ora l'allegato bash
deve essere rilasciato e possiamo uscire gdb
:
(gdb) detach
Detaching from program: /bin/bash, process <PID>
(gdb) q
Se lo script è stato interrotto da gdb
un altro terminale, continua a essere eseguito. Possiamo tornare al terminale di loop.sh. Ora non scrive nulla sullo schermo, ma esegue e scrive nel file. Dobbiamo metterlo in secondo piano. Quindi premere ^Z
.
^Z
[1]+ Stopped ./loop.sh
(Ora siamo nello stesso stato come se ^Z
fosse stato premuto all'inizio.)
Ora possiamo verificare lo stato del lavoro:
$ ps -f 24522
UID PID PPID C STIME TTY STAT TIME CMD
<UID> <PID><PPID> 0 11:16 pts/36 S 0:00 /bin/bash ./loop.sh
$ jobs
[1]+ Stopped ./loop.sh
Quindi il processo dovrebbe essere in esecuzione in background e staccato dal terminale. Il numero jobs
nell'output del comando tra parentesi quadre identifica il lavoro all'interno bash
. Possiamo usare i seguenti bash
comandi integrati che applicano un segno '%' prima del numero del lavoro:
$ bg %1
[1]+ ./loop.sh &
$ disown -h %1
$ ps -f <PID>
UID PID PPID C STIME TTY STAT TIME CMD
<UID> <PID><PPID> 0 11:16 pts/36 S 0:00 /bin/bash ./loop.sh
E ora possiamo uscire dalla bash chiamante. Il processo continua in esecuzione in background. Se abbandoniamo il suo PPID diventiamo 1 (processo init (1)) e il terminale di controllo diventa sconosciuto.
$ ps -f <PID>
UID PID PPID C STIME TTY STAT TIME CMD
<UID> <PID> 1 0 11:16 ? S 0:00 /bin/bash ./loop.sh
$ /usr/bin/lsof -p <PID>
...
loop.sh <PID> truey 0u CHR 136,36 38 /dev/pts/36 (deleted)
loop.sh <PID> truey 1u REG 0,26 1127 15008411 /home/truey/loop.out
loop.sh <PID> truey 2u CHR 136,36 38 /dev/pts/36 (deleted)
COMMENTO
Le cose di gdb possono essere automatizzate creando un file (ad esempio loop.gdb) contenente i comandi ed esegui gdb -q -x loop.gdb -p <PID>
. Il mio loop.gdb è simile al seguente:
call close(1)
call open("loop.out", 01102, 0600)
# call close(2)
# call open("loop.err", 01102, 0600)
detach
quit
Oppure si può usare invece il seguente liner:
gdb -q -ex 'call close(1)' -ex 'call open("loop.out", 01102, 0600)' -ex detach -ex quit -p <PID>
Spero che questa sia una descrizione abbastanza completa della soluzione.
lsof
(il nome dell'handle del file è pipe
, non simile /dev/pts/1
) o tramite ls -l /proc/<PID>/fd/<fd>
(questo mostra il collegamento simbolico dell'handle). Inoltre, i sottoprocessi non possono ancora avere reindirizzati output, che devono essere reindirizzati a un file.
Per inviare il processo in esecuzione a nohup ( http://en.wikipedia.org/wiki/Nohup )
nohup -p pid
, non ha funzionato per me
Quindi ho provato i seguenti comandi e ha funzionato molto bene
Esegui qualche SOMECOMMAND, diciamo /usr/bin/python /vol/scripts/python_scripts/retention_all_properties.py 1
.
Ctrl+ Zper interrompere (mettere in pausa) il programma e tornare alla shell.
bg
per eseguirlo in background.
disown -h
in modo che il processo non venga interrotto alla chiusura del terminale.
Digita exit
per uscire dalla shell perché ora sei a posto perché l'operazione verrà eseguita in background nel suo stesso processo, quindi non è legata a una shell.
Questo processo è l'equivalente della corsa nohup SOMECOMMAND
.
bg
- questo metterà il lavoro in background e tornerà in esecuzionedisown -a
- questo taglierà tutti gli allegati con il lavoro (quindi puoi chiudere il terminale e continuerà a funzionare)Questi semplici passaggi ti permetteranno di chiudere il terminale mantenendo il processo in esecuzione.
Non indosserà nohup
(in base alla mia comprensione della tua domanda, non ne hai bisogno qui).
Questo ha funzionato per me su Ubuntu Linux mentre era in tcshell.
CtrlZ per metterlo in pausa
bg
per eseguire in background
jobs
per ottenere il suo numero di lavoro
nohup %n
dove n è il numero del lavoro
nohup: failed to run command '%1': No such file or directory
yourExecutable &
e le uscite continuano a comparire sullo schermo eCtrl+C
non sembrano fermare nulla, digita alla ciecadisown;
e premiEnter
anche se lo schermo scorre con le uscite e non riesci a vedere cosa stai scrivendo. Il processo verrà ignorato e sarai in grado di chiudere il terminale senza che il processo muoia.