Cómo evitar que se detenga un proceso en segundo plano después de cerrar el cliente SSH en Linux

291

Estoy trabajando en una máquina Linux a través de SSH (Putty). Necesito dejar un proceso en ejecución durante la noche, así que pensé que podría hacerlo iniciando el proceso en segundo plano (con un signo y al final del comando) y redirigiendo stdout a un archivo.

Para mi sorpresa, eso no funciona. Tan pronto como cierro la ventana de Putty, el proceso se detiene.

¿Cómo puedo evitar que eso suceda?

Liberarse
fuente

Respuestas:

301

Mira el programa " nohup ".

JesperE
fuente
44
¿Cómo lo para después?
Derek Dahmer
99
Inicie sesión y haga "kill <pid>". Use "pidof" si no conoce el pid.
JesperE el
32
Puede usar nohup command > /dev/null 2>&1 &para ejecutar en segundo plano sin crear ningún resultado stdout o stderr (sin nohup.outarchivo)
KCD
¿Qué sucede si necesito proporcionar alguna información? Por ejemplo, tengo un script de larga ejecución que necesito ejecutar en segundo plano, pero primero me pide mi contraseña FTP. nohupNo ayuda en este caso. ¿Hay alguna manera de jugar con Ctrl+Z/ bg?
Sergey
1
Como soy flojo y malo memorizando secuencias crípticas de personajes, escribí esto , basado en lo que dijo @KCD, y lo he estado usando mucho.
Anomalía
167

Recomendaría usar GNU Screen . Le permite desconectarse del servidor mientras todos sus procesos continúan ejecutándose. No sé cómo viví sin él antes de saber que existía.

gpojd
fuente
77
Esta es una de las mejores piezas de software que he usado. Seriamente. Lo tengo ejecutándose en una caja BSD en la que me conecto desde TODAS PARTES, y simplemente puedo volver a conectarlo a mi pantalla y tener todos mis terminales donde estoy haciendo todo tipo de cosas.
Adam Jaskiewicz
1
Puedo dar fe de esto. La pantalla es una gran aplicación. La capacidad de volver a adjuntar es sorprendente y ahorra mucho trabajo potencialmente perdido.
willasaywhat
Incluso lo uso en máquinas locales y adjunto múltiples xterms a la misma sesión de pantalla (pantalla -x). De esa manera puedo abrir muchas ventanas dentro de mi sesión de pantalla y cambiar libremente mis diferentes xterms de ventana a ventana.
Adam Jaskiewicz
17
Depende de si necesita volver a conectarse a la aplicación de fondo o no. Si lo hace, entonces, sí, la pantalla es la única forma de volar. Sin embargo, si se trata de disparar y olvidar, entonces nohup se ajusta a la factura tan bien, si no mejor.
Dave Sherohman el
1
+1 para pantalla. O, como alternativa, tmux (me gusta más que la pantalla) o incluso byobu, que es una buena interfaz para screen o tmux. Simplemente puede escribir screen para obtener un shell para usar y volver más tarde en cualquier momento, o ejecutar su comando con pantalla, como "comando de pantalla": la sesión de pantalla existirá mientras exista el "comando" del proceso, y si es algo muy largo, puede regresar y mirar su salida estándar en cualquier momento.
gerlos
81

Cuando se cierra la sesión, el proceso recibe la señal SIGHUP que aparentemente no está captando. Puede usar el nohupcomando al iniciar el proceso o el comando incorporado bash disown -hdespués de iniciar el proceso para evitar que esto suceda:

> help disown
disown: disown [-h] [-ar] [jobspec ...]
     By default, removes each JOBSPEC argument from the table of active jobs.
    If the -h option is given, the job is not removed from the table, but is
    marked so that SIGHUP is not sent to the job if the shell receives a
    SIGHUP.  The -a option, when JOBSPEC is not supplied, means to remove all
    jobs from the job table; the -r option means to remove only running jobs.
Robert Gamble
fuente
44
La ventaja aquí es que Disown funciona para procesos que ya se han iniciado.
Christian K.
1
¿'Jobspec' significa el pid?
Stewart
1
No se preocupe, encontré esta respuesta aquí stackoverflow.com/questions/625409/…
Stewart
42

daemonize? nohup? ¿PANTALLA? (tmux ftw, la pantalla es basura ;-)

Simplemente haga lo que todas las demás aplicaciones han hecho desde el principio: doble tenedor.

# ((exec sleep 30)&)
# grep PPid /proc/`pgrep sleep`/status
PPid:   1
# jobs
# disown
bash: disown: current: no such job

¡Explosión! Hecho :-) He usado esto innumerables veces en todo tipo de aplicaciones y en muchas máquinas antiguas. Puede combinarse con redireccionamientos y otras cosas para abrir un canal privado entre usted y el proceso.

Crear como coproc.sh:

#!/bin/bash

IFS=

run_in_coproc () {
    echo "coproc[$1] -> main"
    read -r; echo $REPLY
}

# dynamic-coprocess-generator. nice.
_coproc () {
    local i o e n=${1//[^A-Za-z0-9_]}; shift
    exec {i}<> <(:) {o}<> >(:) {e}<> >(:)
. /dev/stdin <<COPROC "${@}"
    (("\$@")&) <&$i >&$o 2>&$e
    $n=( $o $i $e )
COPROC
}

# pi-rads-of-awesome?
for x in {0..5}; do
    _coproc COPROC$x run_in_coproc $x
    declare -p COPROC$x
done

for x in COPROC{0..5}; do
. /dev/stdin <<RUN
    read -r -u \${$x[0]}; echo \$REPLY
    echo "$x <- main" >&\${$x[1]}
    read -r -u \${$x[0]}; echo \$REPLY
RUN
done

y entonces

# ./coproc.sh 
declare -a COPROC0='([0]="21" [1]="16" [2]="23")'
declare -a COPROC1='([0]="24" [1]="19" [2]="26")'
declare -a COPROC2='([0]="27" [1]="22" [2]="29")'
declare -a COPROC3='([0]="30" [1]="25" [2]="32")'
declare -a COPROC4='([0]="33" [1]="28" [2]="35")'
declare -a COPROC5='([0]="36" [1]="31" [2]="38")'
coproc[0] -> main
COPROC0 <- main
coproc[1] -> main
COPROC1 <- main
coproc[2] -> main
COPROC2 <- main
coproc[3] -> main
COPROC3 <- main
coproc[4] -> main
COPROC4 <- main
coproc[5] -> main
COPROC5 <- main

Y ahí tienes, engendras lo que sea. el <(:) abre una tubería anónima a través de la sustitución del proceso, que muere, pero la tubería se queda porque tienes un identificador. Por lo general, hago un en sleep 1lugar de :porque es ligeramente picante, y obtengo un error de "archivo ocupado"; nunca sucede si se ejecuta un comando real (por ejemplo, command true)

"abastecimiento heredoc":

. /dev/stdin <<EOF
[...]
EOF

Esto funciona en cada shell que he probado, incluido busybox / etc (initramfs). Nunca lo había visto antes, lo descubrí de forma independiente mientras pinchaba, ¿quién sabía que la fuente podía aceptar argumentos? Pero a menudo sirve como una forma de evaluación mucho más manejable, si existe tal cosa.

anthonyrisinger
fuente
2
por qué el voto negativo ... y qué pasa si la pregunta es antigua; obviamente es relevante considerando que hay otras 11 respuestas que apestan. Esta solución es, sin sistema, la forma idiomática y aceptada de demonizar durante los últimos 30 años, no aplicaciones sin sentido, por ejemplo. Nohup y col.
anthonyrisinger
77
no importa cuán buena sea su respuesta, a veces a alguien en SO no le gustará y votará negativamente. Es mejor no preocuparse demasiado por eso.
Alex D
1
@ tbc0 ... pruebassh myhost "((exec sleep 500)&) >/dev/null"
anthonyrisinger
1
@anthonyrisinger ok, eso funciona. Creo que esto es más limpio: ssh myhost 'sleep 500 >&- 2>&- <&- &' TMTOWTDI;)
tbc0
1
Esto es genial. La única solución que realmente funciona en busybox. merece más votos a favor
Hamy
34
nohup blah &

Sustituya su nombre de proceso por bla!

Brian Knoblauch
fuente
2
es posible que desee agregar la redirección de salida estándar y error estándar.
David Nehme
99
nohup redirige stdout y stderr a nohup.out (o nohup.out y nohup.err según la versión), por lo que, a menos que esté ejecutando varios comandos, no es necesario.
Chas. Owens
17

Personalmente, me gusta el comando 'lote'.

$ batch
> mycommand -x arg1 -y arg2 -z arg3
> ^D

Esto lo guarda en segundo plano y luego le envía los resultados por correo. Es parte del cron.

Will Hartung
fuente
11

Como otros han señalado, para ejecutar un proceso en segundo plano para que pueda desconectarse de su sesión SSH, debe hacer que el proceso en segundo plano se disocie correctamente de su terminal de control, que es la pseudo-tty que utiliza la sesión SSH.

Puede encontrar información sobre procesos de demonización en libros como "Programa de red avanzada de Stevens, Vol. 1, 3ª Ed." O "Programación avanzada de Unix de Rochkind".

Recientemente (en los últimos años) tuve que lidiar con un programa recalcitrante que no se demonizó adecuadamente. Terminé lidiando con eso creando un programa de demonización genérico, similar a nohup pero con más controles disponibles.

Usage: daemonize [-abchptxV][-d dir][-e err][-i in][-o out][-s sigs][-k fds][-m umask] -- command [args...]
  -V          print version and exit
  -a          output files in append mode (O_APPEND)
  -b          both output and error go to output file
  -c          create output files (O_CREAT)
  -d dir      change to given directory
  -e file     error file (standard error - /dev/null)
  -h          print help and exit
  -i file     input file (standard input - /dev/null)
  -k fd-list  keep file descriptors listed open
  -m umask    set umask (octal)
  -o file     output file (standard output - /dev/null)
  -s sig-list ignore signal numbers
  -t          truncate output files (O_TRUNC)
  -p          print daemon PID on original stdout
  -x          output files must be new (O_EXCL)

El doble guión es opcional en sistemas que no utilizan la función GNU getopt (); es necesario (o debe especificar POSIXLY_CORRECT en el entorno) en Linux, etc. Dado que el doble guión funciona en todas partes, es mejor usarlo.

Todavía puede ponerse en contacto conmigo (nombre punto apellido en gmail punto com) si desea la fuente daemonize.

Sin embargo, el código ahora está (finalmente) disponible en GitHub en mi repositorio SOQ (Stack Overflow Questions) como archivo daemonize-1.10.tgzen el subdirectorio de paquetes .

Jonathan Leffler
fuente
13
¿Por qué no pones la fuente en github o bitbucket?
Rob
55
¿Por qué la ausencia de la fuente de github garantiza un voto negativo?
Jonathan Leffler
77
@JonathanLeffler En mi humilde opinión, enumerar todas las opciones interesantes de un programa que no está disponible públicamente en ninguna forma (ni siquiera comercialmente) raya en perder el tiempo del lector.
DepressedDaniel
7

En un sistema basado en Debian (en la máquina remota) Instale:

sudo apt-get install tmux

Uso:

tmux

ejecuta los comandos que quieras

Para cambiar el nombre de la sesión:

Ctrl + B luego $

escoger un nombre

Para salir de la sesión:

Ctrl + B y luego D

(Esto deja la sesión tmux). Luego, puede cerrar sesión en SSH.

Cuando necesite regresar / verificarlo nuevamente, inicie SSH e ingrese

tmux adjuntar nombre_sesión

Te llevará de vuelta a tu sesión tmux.

Max
fuente
este es el camino a seguir
kilgoretrout
6

Para la mayoría de los procesos, puede pseudo-demonizar usando este viejo truco de línea de comandos de Linux:

# ((mycommand &)&)

Por ejemplo:

# ((sleep 30 &)&)
# exit

Luego, inicie una nueva ventana de terminal y:

# ps aux | grep sleep

Mostrará que sleep 30todavía se está ejecutando.

Lo que ha hecho es iniciar el proceso como hijo de un niño, y cuando sale, el nohup comando que normalmente desencadenaría el proceso de salida no cae en cascada hacia el nieto, dejándolo como un proceso huérfano, todavía ejecutándose .

Yo prefiero este enfoque "establecer y olvidarse de él", no hay necesidad de hacer frente a nohup, screen, tmux, I / O redirección, o cualquiera de esas cosas.

RAM
fuente
5

Si usa la pantalla para ejecutar un proceso como root, tenga cuidado con la posibilidad de ataques de elevación de privilegios. Si su propia cuenta se ve comprometida de alguna manera, habrá una forma directa de hacerse cargo de todo el servidor.

Si este proceso necesita ejecutarse regularmente y tiene suficiente acceso en el servidor, una mejor opción sería usar cron para ejecutar el trabajo. También puede usar init.d (el super demonio) para comenzar su proceso en segundo plano, y puede terminar tan pronto como se haga.

Dana la sana
fuente
5

nohupes muy bueno si desea registrar sus datos en un archivo. Pero cuando pasa a segundo plano, no puede darle una contraseña si sus scripts lo solicitan. Creo que debes intentarlo screen. es una utilidad que puede instalar en su distribución de Linux usando yum, por ejemplo, en CentOS y yum install screenluego acceder a su servidor a través de masilla u otro software, en su tipo de shell screen. Se abrirá la pantalla [0] en masilla. Haz tu trabajo. Puede crear más pantalla [1], pantalla [2], etc. en la misma sesión de masilla.

Comandos básicos que necesitas saber:

Para iniciar la pantalla

pantalla


Para c pantalla siguiente reate

ctrl + a + c


Para pasar a la pantalla n que creó

Ctrl + a + n


A d etach

Ctrl + a + d


Durante el trabajo cierra tu masilla. Y la próxima vez que inicies sesión con el tipo de masilla

pantalla -r

Para volver a conectarse a su pantalla, y puede ver su proceso aún ejecutándose en la pantalla. Y para salir de la pantalla, escriba #exit.

Para más detalles ver man screen.

Adeel Ahmad
fuente
Asumir que esa yumes la herramienta correcta, cuando no conoces la distribución, no es bueno. debe dejar en claro en qué distribuciones screense pueden instalar yum.
tymik
5

Nohup permite que un proceso del cliente no se elimine si se elimina un proceso principal, para discutir cuando cierre la sesión. Aún mejor aún use:

nohup /bin/sh -c "echo \$\$ > $pidfile; exec $FOO_BIN $FOO_CONFIG  " > /dev/null

Nohup hace que el proceso que usted inicia sea inmune a la terminación, que su sesión SSH y sus procesos secundarios se anulan al cerrar sesión. El comando que le proporcioné le proporciona una forma de almacenar el pid de la aplicación en un archivo pid para que pueda eliminarlo correctamente más tarde y permita que el proceso se ejecute después de haber cerrado la sesión.

jcodeninja
fuente
2

Si también está dispuesto a ejecutar aplicaciones X, use xpra junto con "screen".

Alexey Shurygin
fuente
2

También iría para el programa de pantalla (sé que otra respuesta fue la pantalla, pero esta es una finalización)

no solo el hecho de que &, ctrl + z bg disown, nohup, etc. puede darte una desagradable sorpresa de que cuando cierres sesión, el trabajo seguirá siendo asesinado (no sé por qué, pero me pasó a mí, y no me molestó debido a que cambié para usar la pantalla, pero supongo que la solución anthonyrisinger como doble bifurcación resolvería eso), también la pantalla tiene una gran ventaja sobre la conexión a tierra:

screen will background your process without losing interactive control to it

y por cierto, esta es una pregunta que nunca haría en primer lugar :) ... uso la pantalla desde el principio para hacer cualquier cosa en cualquier Unix ... yo (casi) NUNCA trabajo en un shell de Unix / Linux sin iniciar la pantalla primero ... y debería parar ahora, o comenzaré una presentación interminable de lo que es una buena pantalla y qué puede hacer por usted ... búsquela usted mismo, vale la pena;)

El hechicero
fuente
PD anthonyrisinger, eres bueno, te doy eso pero ... ¿30 años? Apuesto a que es una solución cuando &, bg, nohup o screen aún no estaba allí, y sin ofender aprecio su conocimiento, pero es demasiado complicado usarlo :)
THESorcerer
2
(aparte: ver Tmux ) aunque esto me precede mucho [1987], &(ejecución asíncrona) fue introducido por Thompson shell en 1971 , para la primera versión de UNIX ... así que literalmente "siempre ha sido" ;-) por desgracia, Fui demasiado conservador, en realidad han pasado 41 años.
anthonyrisinger
2

También está el comando daemon del paquete libslack de código abierto.

daemon es bastante configurable y se preocupa por todas las tediosas cosas del demonio, como el reinicio automático, el registro o el manejo de archivos pid.

janv
fuente
2

Agregue esta cadena a su comando:> & - 2> & - <& - &. > & - significa stdout cercano. 2> & - significa stderr cercano. <& - significa stdin cercano. & significa ejecutar en segundo plano. Esto también funciona para iniciar un trabajo mediante programación mediante ssh:

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

La respuesta aceptada sugiere usar nohup . Prefiero sugerir el uso de pm2 . Usar pm2 sobre nohup tiene muchas ventajas, como mantener viva la aplicación, mantener archivos de registro para la aplicación y muchas otras características más. Para más detalles mira esto .

Para instalar pm2 necesitas descargar npm . Para el sistema basado en Debian

sudo apt-get install npm

y para Redhat

sudo yum install npm

O puedes seguir estas instrucciones . Después de instalar npm, úselo para instalar pm2

npm install pm2@latest -g

Una vez hecho esto, puede iniciar su aplicación

$ pm2 start app.js              # Start, Daemonize and auto-restart application (Node)
$ pm2 start app.py              # Start, Daemonize and auto-restart application (Python)

Para la supervisión del proceso, utilice los siguientes comandos:

$ pm2 list                      # List all processes started with PM2
$ pm2 monit                     # Display memory and cpu usage of each app
$ pm2 show [app-name]           # Show all informations about application

Administre los procesos utilizando el nombre de la aplicación o el id del proceso o administre todos los procesos juntos

$ pm2 stop     <app_name|id|'all'|json_conf>
$ pm2 restart  <app_name|id|'all'|json_conf>
$ pm2 delete   <app_name|id|'all'|json_conf>

Los archivos de registro se pueden encontrar en

$HOME/.pm2/logs #contain all applications logs

Los archivos ejecutables binarios también se pueden ejecutar con pm2. Tienes que hacer un cambio en el archivo jason. Cambie el "exec_interpreter" : "node", a "exec_interpreter" : "none".(vea la sección de atributos ).

#include <stdio.h>
#include <unistd.h>  //No standard C library
int main(void)
{
    printf("Hello World\n");
    sleep (100);
    printf("Hello World\n");

    return 0;
}

Compilando el código anterior

gcc -o hello hello.c  

y ejecutarlo con np2 en segundo plano

pm2 start ./hello
hacks
fuente
¿Se puede usar esto para ejecutar ejecutables binarios?
GetFree
@Liberarse; Si. Usted puede.
piratea
Agregue un ejemplo por favor. La respuesta tal como está ahora parece que es buena solo para archivos de script.
GetFree
@Liberarse; Se agregó el ejemplo. Avísame si tienes algún problema.
piratea
1

En systemd / Linux, systemd-run es una buena herramienta para iniciar procesos independientes de la sesión. Personas con odio van a odiar

Eugene Shatsky
fuente