shell - segundo - ¿Cómo pongo un proceso ya en ejecución en nohup?
ver procesos en linux (10)
- Ctrl + Z : esto detendrá el trabajo (¡no se cancelará!)
-
bg
- esto pondrá el trabajo en segundo plano y volverá al proceso en ejecución -
disown -a
: esto cortará todos los archivos adjuntos con el trabajo (para que pueda cerrar el terminal y aún se ejecute)
Estos sencillos pasos le permitirán cerrar el terminal mientras mantiene el proceso en ejecución.
No se colocará en nohup
(según mi comprensión de su pregunta, no la necesita aquí).
Tengo un proceso que ya se está ejecutando durante mucho tiempo y no quiero finalizarlo.
¿Cómo lo pongo bajo nohup (es decir, cómo hago que continúe ejecutándose incluso si cierro el terminal?)
El comando para separar un trabajo en ejecución del shell (= hace que nohup) está disown
y es un comando de shell básico.
Desde bash-manpage (man bash):
disown [-ar] [-h] [jobspec ...]
Sin opciones, cada especificación de trabajo se elimina de la tabla de trabajos activos. Si se da la opción -h, cada especificación de trabajo no se elimina de la tabla, pero se marca para que SIGHUP no se envíe al trabajo si el shell recibe un SIGHUP. Si no hay ninguna especificación de trabajo, y no se proporciona la opción -a ni la opción -r, se utiliza el trabajo actual. Si no se proporciona una especificación de trabajo, la opción -a significa eliminar o marcar todos los trabajos; La opción -r sin un argumento de especificación de trabajo restringe la operación a trabajos en ejecución. El valor de retorno 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 hará nohup
En mi sistema AIX, lo intenté
nohup -p processid>
Esto funcionó bien. Continuó ejecutando mi proceso incluso después de cerrar las ventanas de terminal. Tenemos ksh como shell predeterminado, por lo que los comandos bg
y disown
no funcionaron.
Estas son buenas respuestas arriba, solo quería agregar una aclaración:
No puedes disown
un pid o un proceso, no puedes disown
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 lanzar el trabajo en segundo plano (no suspenderlo) y luego rechazarlo.
Problema:
% jobs
[1] running java
[2] suspended vi
% disown %1
Consulte http://www.quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/jobcontrol/ para obtener una descripción más detallada de Unix Job Control.
Esto me funcionó en Ubuntu Linux mientras estaba en tcshell.
Ctrl Z para pausarlo
bg
para ejecutar en segundo planojobs
dejobs
para obtener su número de trabajonohup %n
donde n es el número de trabajo
La respuesta de Node es realmente genial, pero dejó abierta la pregunta de cómo se puede redireccionar stdout y stderr. Encontré una solución en Unix y Linux , pero tampoco está completa. Me gustaría fusionar estas dos soluciones. Aquí está:
Para mi prueba hice un pequeño script de bash llamado loop.sh, que imprime el pid de sí mismo con un minuto de sueño en un bucle infinito.
$./loop.sh
Ahora consigue el PID de este proceso de alguna manera. Por lo general, ps -C loop.sh
es suficientemente bueno, pero está impreso en mi caso.
Ahora podemos cambiar a otro terminal (o presionar ^ Z y en el mismo terminal). Ahora gdb
debe adjuntar a este proceso.
$ gdb -p <PID>
Esto detiene el script (si se está ejecutando). Su estado se puede verificar con ps -f <PID>
, donde el campo STAT
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
Cerrar (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.
Este abierto es igual a open(path, O_TRUNC|O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)
. En lugar de O_RDWR
O_WRONLY
podría aplicar, pero /usr/sbin/lsof
dice ''u'' para todos los manejadores de archivos std * (columna FD
), que es O_RDWR
.
Verifiqué los valores en el archivo de cabecera /usr/include/bits/fcntl.h.
El archivo de salida podría abrirse con O_APPEND
, como haría nohup
, pero man open(2)
no lo sugiere, debido a posibles problemas de NFS.
Si obtenemos -1 como valor de retorno, la call perror("")
imprime el mensaje de error. Si necesitamos el errno, use p errno
gdb comand.
Ahora podemos comprobar el archivo recién redirigido. /usr/sbin/lsof -p <PID>
imprime:
loop.sh <PID> truey 1u REG 0,26 0 15008411 /home/truey/loop.out
Si queremos, podemos redireccionar stderr a otro archivo, si queremos usar call close(2)
y call open(...)
nuevamente usando un nombre de archivo diferente.
Ahora se debe lanzar el bash
adjunto y podemos salir de gdb
:
(gdb) detach
Detaching from program: /bin/bash, process <PID>
(gdb) q
Si gdb
detuvo la secuencia de comandos desde otra terminal, continuará 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 ponerlo en segundo plano. Así que presione ^Z
^Z
[1]+ Stopped ./loop.sh
(Ahora estamos en el mismo estado que si se presionara ^Z
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 debe ejecutarse en segundo plano y desconectarse del terminal. El número en la salida del comando de jobs
entre corchetes identifica el trabajo dentro de bash
. Podemos usar en los siguientes comandos bash
integrados 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 que nos llama. El proceso continúa ejecutándose en segundo plano. Si abandonamos 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
Las cosas gdb se pueden automatizar creando un archivo (por ejemplo, loop.gdb) que contiene los comandos y ejecutando 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 uno puede usar el siguiente forro 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.
Lamentablemente, el rechazo es específico de bash y no está disponible en todos los shells.
Ciertos tipos de Unix (por ejemplo, AIX y Solaris) tienen una opción en el propio comando nohup
que se puede aplicar a un proceso en ejecución:
nohup -p pid
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.
Ejecute algo de SOMECOMMAND, digamos
/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 interrumpa cuando el terminal se cierra.Escriba
exit
para salir de la shell porque ya está listo, ya que la operación se ejecutará en segundo plano en su propio proceso, por lo que no está vinculada a una shell.
Este proceso es el equivalente a ejecutar nohup SOMECOMMAND
.
Supongamos que, por alguna razón, Ctrl + Z tampoco funciona, vaya a otra terminal, encuentre la identificación del proceso (usando ps
) y ejecute:
kill -20 PID
kill -18 PID
kill -20
( SIGTSTP
) suspenderá el proceso y kill -18
( SIGCONT
) reanudará el proceso, en segundo plano. Entonces, cerrar ambos terminales no detendrá su proceso.
Usando el control de trabajo 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 de trabajo] es el número de trabajo (como%1
para el primer trabajo en ejecución; busque su número con el comando dejobs
) para que el trabajo no finalice cuando se cierre el terminal.