¿Cómo pongo un proceso que ya se está ejecutando en nohup?
Pregunta
Tengo un proceso que ya lleva mucho tiempo ejecutándose y no quiero finalizarlo.
¿Cómo lo pongo en nohup (es decir, cómo hago para que continúe ejecutándose incluso si cierro la terminal?)
Solución
Uso del Control de trabajos de bash para enviar el proceso al fondo:
- Ctrl + Z para detener (pausar) el programa y volver al shell.
-
bg
para ejecutarlo en segundo plano. -
disown -h [job-spec]
donde [especificación-trabajo] es el número de trabajo (como%1
para el primer trabajo en ejecución; encuentre su número con el comandojobs
) para que el trabajo no se elimine cuando el terminal se cierre .
Otros consejos
Supongamos que, por alguna razón, Ctrl + Z tampoco funciona, vaya a otra terminal, busque la identificación del proceso (usando ps
) y ejecute:
kill -SIGSTOP PID
kill -SIGCONT PID
SIGSTOP
suspenderá el proceso y SIGCONT
reanudará el proceso, en segundo plano. Entonces, cerrar ambos terminales no detendrá su proceso.
El comando para separar un trabajo en ejecución del shell (= lo convierte en nohup) es disown
y un comando de shell básico.
Desde bash-manpage (man bash):
repudiar [-ar] [-h] [especificación de trabajo ...]
Sin opciones, cada especificación de trabajo se elimina de la tabla de trabajos activos.Si se da la opción -h, cada JobSpec no se elimina de la tabla, sino que se marca para que el suspiro no se envíe al trabajo si el shell recibe un suspiro.Si no se especifica ningún jobspec presente, y no se proporciona ni la opción -a ni la opción -r, se utiliza el trabajo actual.Si no se proporciona ninguna especificación de trabajo, la opción -a significa eliminar o marcar todos los puestos de trabajo;la opción -r sin un argumento de especificación de trabajo restringe la operación a trabajos en ejecución.El regreso value es 0 a menos que una especificación de trabajo no especifique un trabajo válido.
Eso significa que un simple
disown -a
eliminará todos los trabajos de la tabla de trabajos y los desactivará
Estas son buenas respuestas anteriores, solo quería agregar una aclaración:
No puede disown
un pid o proceso, usted <=> un trabajo, y esa es una distinción importante.
Un trabajo es algo que es una noción de un proceso que se adjunta a un shell, por lo tanto, debe arrojar el trabajo en segundo plano (no suspenderlo) y luego rechazarlo.
Problema:
% jobs
[1] running java
[2] suspended vi
% disown %1
Ver http://www.quantprinciple.com/ invest / index.php / docs / tipsandtricks / unix / jobcontrol / para una discusión más detallada de Unix Job Control.
Desafortunadamente disown
es específico de bash y no está disponible en todos los shells.
Ciertos sabores de Unix (por ejemplo, AIX y Solaris) tienen una opción en el comando nohup
que se puede aplicar a un proceso en ejecución:
nohup -p pid
La respuesta de Node es realmente excelente, pero dejó abierta la pregunta de cómo redirigir stdout y stderr.Encontré una solución en Unix y Linux, pero tampoco está completo.Me gustaría fusionar estas dos soluciones.Aquí lo tienes:
Para mi prueba, hice un pequeño script bash llamado loop.sh, que imprime el pid de sí mismo con un minuto de suspensión en un bucle infinito.
$./loop.sh
Ahora obtenga el PID de este proceso de alguna manera.Generalmente ps -C loop.sh
es bastante bueno, pero en mi caso está impreso.
Ahora podemos cambiar a otra terminal (o presionar ^Z y en la misma terminal).Ahora gdb
debe adjuntarse a este proceso.
$ gdb -p <PID>
Esto detiene el script (si se está ejecutando).Su estado puede comprobarse mediante ps -f <PID>
, donde el STAT
El campo es 'T+' (o en el caso de ^Z 'T'), lo que 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
Close(1) devuelve cero en caso de éxito.
(gdb) call open("loop.out", 01102, 0600)
$6 = 1
Open(1) devuelve el nuevo descriptor de archivo si tiene éxito.
Esta apertura es igual a open(path, O_TRUNC|O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)
.En lugar de O_RDWR
O_WRONLY
podría aplicarse, pero /usr/sbin/lsof
dice 'u' para todos los controladores de archivos estándar* (FD
columna), que es O_RDWR
.
Revisé los valores en el archivo de encabezado /usr/include/bits/fcntl.h.
El archivo de salida se puede abrir con O_APPEND
, como nohup
haría, pero esto no es sugerido por man open(2)
, debido a posibles problemas de NFS.
Si obtenemos -1 como valor de retorno, entonces call perror("")
imprime el mensaje de error.Si necesitamos el errno, use p errno
Comando gdb.
Ahora podemos comprobar el archivo recién redirigido. /usr/sbin/lsof -p <PID>
huellas dactilares:
loop.sh <PID> truey 1u REG 0,26 0 15008411 /home/truey/loop.out
Si queremos, podemos redirigir stderr a otro archivo, si queremos usar call close(2)
y call open(...)
nuevamente usando un nombre de archivo diferente.
Ahora el adjunto bash
tiene que ser liberado y podemos salir gdb
:
(gdb) detach
Detaching from program: /bin/bash, process <PID>
(gdb) q
Si el guión fue detenido por gdb
desde otro terminal continúa ejecutándose.Podemos volver a la terminal de loop.sh.Ahora no escribe nada en la pantalla, sino que se ejecuta y escribe en el archivo.Tenemos que dejarlo en un segundo plano.Así que presiona ^Z
.
^Z
[1]+ Stopped ./loop.sh
(Ahora estamos en el mismo estado que si ^Z
fue presionado al principio.)
Ahora podemos comprobar el estado del trabajo:
$ 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
Por lo tanto, el proceso debería ejecutarse en segundo plano y desconectarse del terminal.El número en el jobs
La salida del comando entre corchetes identifica el trabajo dentro. bash
.Podemos usar en el siguiente incorporado bash
comandos que aplican un signo '%' antes del número de trabajo:
$ 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
Y ahora podemos salir de la fiesta de llamadas.El proceso continúa ejecutándose en segundo plano.Si salimos, su PPID se convierte en 1 (proceso init(1)) y el terminal de control se vuelve desconocido.
$ 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)
COMENTARIO
El material de gdb se puede automatizar creando un archivo (p. ej.loop.gdb) que contiene los comandos y ejecutar gdb -q -x loop.gdb -p <PID>
.Mi loop.gdb se ve así:
call close(1)
call open("loop.out", 01102, 0600)
# call close(2)
# call open("loop.err", 01102, 0600)
detach
quit
O se puede utilizar el siguiente delineador en su lugar:
gdb -q -ex 'call close(1)' -ex 'call open("loop.out", 01102, 0600)' -ex detach -ex quit -p <PID>
Espero que esta sea una descripción bastante completa de la solución.
Para enviar el proceso en ejecución a nohup ( http://en.wikipedia.org/wiki/Nohup)
nohup -p pid
, no funcionó para mí
Luego probé los siguientes comandos y funcionó muy bien
-
Ejecuta SOMECOMMAND, diga
/usr/bin/python /vol/scripts/python_scripts/retention_all_properties.py 1
. Ctrl + Z para detener (pausar) el programa y volver al shell.
-
bg
para ejecutarlo en segundo plano. -
disown -h
para que el proceso no se cancele cuando el terminal se cierre. -
Escriba
exit
para salir del shell porque ahora está listo para comenzar, ya que la operación se ejecutará en segundo plano en su propio proceso, por lo que no está vinculada a un shell.
Este proceso es el equivalente a ejecutar nohup SOMECOMMAND
.
En mi sistema AIX, probé
nohup -p processid>
Esto funcionó bien.Continuó ejecutando mi proceso incluso después de cerrar las ventanas de la terminal.Tenemos ksh como shell predeterminado, por lo que bg
y disown
Los comandos no funcionaron.
- ctrl + z : esto pausará el trabajo (¡no se cancelará!)
-
bg
- esto pondrá el trabajo en segundo plano y volverá al proceso de ejecución -
disown -a
- esto cortará todos los archivos adjuntos con el trabajo (por lo que puede cerrar el terminal y aún se ejecutará)
Estos simples pasos le permitirán cerrar la terminal mientras mantiene el proceso en ejecución.
No se colocará en nohup
(según tengo entendido su pregunta, no la necesita aquí).
Esto funcionó para mí en Ubuntu Linux mientras estaba en tcshell.
Ctrl Z para pausarlo
-
bg
para ejecutar en segundo plano -
jobs
para obtener su número de trabajo -
nohup %n
donde n es el número de trabajo