it-swarm-es.tech

¿Cómo puedo ejecutar un comando que sobrevivirá al cierre de la terminal?

A veces quiero comenzar un proceso y olvidarlo. Si lo inicio desde la línea de comando, así:

redshift

No puedo cerrar la terminal, o matará el proceso. ¿Puedo ejecutar un comando de tal manera que pueda cerrar el terminal sin matar el proceso?

339
Matthew

Uno de los siguientes 2 debería funcionar:

$ Nohup redshift &

o

$ redshift &
$ disown

Consulte lo siguiente para obtener un poco más de información sobre cómo funciona esto:

342
Steven D

Si su programa es ya se está ejecutando puede pausarlo con Ctrl-Z, llévalo al fondo con bg y luego disown, de esta manera:

$ sleep 1000
^Z
[1]+  Stopped                 sleep 1000
$ bg
$ disown
$ exit
147
Stefan

@StevenD ya ha publicado una buena respuesta, pero creo que esto podría aclararlo un poco más.

La razón por la que el proceso se interrumpe al terminar el terminal es porque el proceso que inicia es un proceso secundario del terminal. Una vez que cierre la terminal, esto también eliminará estos procesos secundarios. Puede ver el árbol de procesos con pstree, por ejemplo, cuando ejecuta kate & en Konsole:

init-+
     ├─konsole─┬─bash─┬─kate───2*[{kate}]
     │         │      └─pstree
     │         └─2*[{konsole}]

Para hacer que el proceso kate se separe de konsole cuando termina konsole, use Nohup con el comando, de esta manera:

Nohup kate &

Después de cerrar konsole, pstree se verá así:

init-+
     |-kate---2*[{kate}]

y kate sobrevivirá. :)

Una alternativa es usar screen/tmux/byobu, que mantendrá el Shell en ejecución, independientemente del terminal.

50
gertvdijk

Puedes ejecutar el proceso así en la terminal

setsid process

Esto ejecutará el programa en una nueva sesión. Como se explica http://hanoo.org/index.php?article=run-program-in-new-session-linux

31
hanoo

Aunque todas las sugerencias funcionan bien, he encontrado que mi alternativa es usar screen, un programa que configura un terminal virtual en su pantalla.

Puede considerar comenzarlo con screen -S session_name. Screen se puede instalar en prácticamente todos los derivados de Linux y Unix. Golpear Ctrl+A y (minúscula) C comenzará una segunda sesión. Esto le permitirá alternar entre la sesión inicial presionando Ctrl+A y  o la sesión más nueva presionando Ctrl+A y 1. Puede tener hasta diez sesiones en una terminal. Solía ​​comenzar una sesión en el trabajo, ir a casa, ingresar a mi máquina de trabajo y luego invocar screen -d -R session_name. Esto lo reconectará a esa sesión remota.

10
apolinsky

Yo prefiero:

(Nombre de la aplicación y)

por ejemplo: [email protected]:~$ (chromium-browser &)

¡Asegúrese de usar paréntesis cuando escriba el comando!

8
daGo

Tengo un script para:

  • Ejecute comandos arbitrarios en segundo plano

  • Evita que sean asesinados con la ventana de terminal

  • Suprimir su salida

  • Maneja el estado de salida

Lo uso principalmente para gedit, evince, inkscape etc. que tienen mucha salida de terminal molesta. Si el comando finaliza antes de TIMEOUT, se devuelve el estado de salida de Nohup en lugar de cero.

#!/bin/bash

TIMEOUT=0.1

#use Nohup to run the command, suppressing its output and allowing the terminal to be closed
#also send Nohup's output to /dev/null, supressing Nohup.out
#run Nohup in the background so this script doesn't block
Nohup "${@}" >/dev/null 2>&1 &
Nohup_PID=$!

#kill this script after a short time, exiting with success status - command is still running
#this is needed as there is no timeout argument for `wait` below
MY_PID=$$
trap "exit 0" SIGINT SIGTERM
sleep $TIMEOUT && kill $MY_PID 2>/dev/null & #ignore "No such process" error if this exits normally

#if the command finishes before the above timeout, everything may be just fine or there could have been an error
wait $Nohup_PID
Nohup_STATUS=$?
#print an error if there was any. most commonly, there was a typo in the command
[ $Nohup_STATUS != 0 ] && echo "Error ${@}"
#return the exit status of Nohup, whatever it was
exit $Nohup_STATUS

ejemplos ...

>>> run true && echo success || echo fail
success
>>> run false && echo success || echo fail
Error false
fail
>>> run sleep 1000 && echo success || echo fail
success
>>> run notfound && echo success || echo fail
Error notfound
fail
7
jozxyqk

La forma exclusiva de Shell de hacer todo esto es cerrar stdin y poner en segundo plano el comando:

command <&- & 

Entonces no se cerrará cuando salga de Shell. Redirigir stdout es una buena opción opcional para hacer.

La desventaja es que no puedes hacer esto después del hecho.

7
w00t

Puede configurar un proceso (PID) para que no reciba una señal HUP al cerrar sesión y cerrar la sesión del terminal. Use el siguiente comando:

Nohup -p PID
4
tony

Posiblemente similar a respuesta ofrecida por apolinsky , uso una variante en screen. El comando Vanilla es así

screen bash -c 'long_running_command_here; echo; read -p "ALL DONE:"'

La sesión se puede desconectar con Ctrl ACtrl D y reconectado en el caso simple con screen -r. Tengo esto envuelto en un script llamado session que vive en mi PATH listo para un acceso conveniente:

#!/bin/bash
#
if screen -ls | awk '$1 ~ /^[1-9][0-9]*\.'"$1"'/' >/dev/null
then
    echo "WARNING: session is already running (reattach with 'screen -r $1')" >&2
else
    exec screen -S "$1" bash -c "[email protected]; echo; echo '--------------------'; read -p 'ALL DONE (Enter to exit):'"
    echo "ERROR: 'screen' is not installed on this system" >&2
fi
exit 1

Esto solo funciona cuando sabe de antemano que desea desconectar un programa. No proporciona un programa que ya se está ejecutando para desconectarse.

3
roaima

De manera similar a otras respuestas publicadas antes, uno puede transferir un proceso en ejecución para usar "pantalla" retrospectivamente gracias a reptyr y luego cerrar el terminal. Los pasos se describen en este post . Los pasos a seguir son:

  1. Suspender el proceso
  2. Reanudar el proceso en segundo plano
  3. Desconoce el proceso
  4. Lanzar una sesión de pantalla
  5. Encuentra el PID del proceso
  6. Use reptyr para hacerse cargo del proceso
2
user308879