¿Cómo desconecto completamente un proceso de la Terminal?

304

Utilizo Tilda (terminal desplegable) en Ubuntu como mi "central de comandos", más o menos de la misma manera que otros podrían usar GNOME Do, Quicksilver o Launchy.

Sin embargo, estoy luchando con cómo separar completamente un proceso (por ejemplo, Firefox) del terminal desde el que se inició, es decir, evitar que dicho proceso (no) secundario

  • se termina al cerrar el terminal de origen
  • "contamina" el terminal de origen a través de STDOUT / STDERR

Por ejemplo, para iniciar Vim en una ventana de terminal "adecuada", probé un script simple como el siguiente:

exec gnome-terminal -e "vim $@" &> /dev/null &

Sin embargo, eso todavía causa contaminación (además, pasar un nombre de archivo no parece funcionar).

slhck
fuente
1
Esa también es una buena pregunta. Creo que es justo considerar un lenguaje de programación Bash - aunque de hecho el alcance de esta pregunta es probablemente más en el lado administrador de sistemas ...
Este es un duplicado de esta pregunta stackoverflow.com/questions/285015/…
Dana the Sane
Su caso de uso no describe el desprendimiento completo, per se.
jiggunjer

Respuestas:

344

Ante todo; una vez que haya comenzado un proceso, puede ponerlo en segundo plano deteniéndolo primero (presionar Ctrl- Z) y luego escribiendo bgpara permitir que se reanude en segundo plano. Ahora es un "trabajo", y su stdout/ stderr/ stdinaún está conectado a su terminal.

Puede iniciar un proceso como fondo inmediatamente agregando un "&" al final del mismo:

firefox &

Para ejecutarlo en segundo plano silenciado, use esto:

firefox </dev/null &>/dev/null &

Alguna información adicional:

nohupes un programa que puede usar para ejecutar su aplicación de tal manera que su stdout / stderr se pueda enviar a un archivo y que cerrar el script principal no haga SIGHUP al hijo. Sin embargo, debe haber tenido la previsión de haberlo usado antes de iniciar la aplicación. Debido a la forma en que nohupfunciona, no puede simplemente aplicarlo a un proceso en ejecución .

disownes un bash incorporado que elimina un trabajo de shell de la lista de trabajos del shell. Lo que esto básicamente significa es que ya no puedes usarlo fg, bgpero lo más importante es que cuando cierras tu shell ya no se cuelga ni envía un mensaje SIGHUPa ese niño. A diferencia nohup, disownse usa después de que el proceso se ha iniciado y se ha establecido en segundo plano.

Lo que no puede hacer es cambiar el stdout / stderr / stdin de un proceso después de haberlo lanzado. Al menos no desde la cáscara. Si inicia su proceso y le dice que su stdout es su terminal (que es lo que hace por defecto), entonces ese proceso está configurado para salir a su terminal. Su shell no tiene nada que ver con la configuración FD de los procesos, eso es puramente algo que el proceso en sí mismo administra. El proceso en sí mismo puede decidir si cierra su stdout / stderr / stdin o no, pero no puede usar su shell para forzarlo a hacerlo.

Para administrar la salida de un proceso en segundo plano, tiene muchas opciones de scripts, "nohup" probablemente sea el primero en pensar. Pero para los procesos interactivos que comienzas pero olvidaste silenciar ( firefox < /dev/null &>/dev/null &) no puedes hacer mucho, realmente.

Te recomiendo que obtengas GNU screen. Con la pantalla, puede cerrar su shell en ejecución cuando la salida del proceso se vuelve molesta y abrir una nueva ( ^Ac).


Ah, y por cierto, no uses " $@" donde lo estás usando.

$@significa, $1, $2, $3..., lo que convertiría a su comando en:

gnome-terminal -e "vim $1" "$2" "$3" ...

Probablemente eso no sea lo que quieres porque solo toma un argumento. Use $1para mostrar que su script solo puede manejar un argumento.

Es realmente difícil hacer que varios argumentos funcionen correctamente en el escenario que proporcionó (con el gnome-terminal -e) porque -esolo toma un argumento, que es una cadena de comando de shell. Tendría que codificar sus argumentos en uno. La mejor y más robusta, pero bastante turbia, es así:

gnome-terminal -e "vim $(printf "%q " "$@")"
lhunath
fuente
¡Muchas gracias por esto! Lamentablemente, solo puedo aceptar una respuesta. Terminé con "nohup $ @ &> / dev / null &" y "alias wvim = 'launch.sh gnome-terminal -x vim'"
20
Qué respuesta tan fantásticamente detallada e informativa. +1
Teekin
1
@ Hi-Angel cuando cierra un bash shell interactivo, bash HUP realiza todos los trabajos activos. Cuando ^ Z y bg un proceso sigue siendo un trabajo, ya sea de fondo. Para eliminarlo como un trabajo, úselo disown, luego el proceso seguirá vivo después de que cierre el shell, ya que bash ya no lo HUP.
Lunh
3
¿No usará en $*lugar de $@solucionar el problema de las cadenas separadas ya?
sjas
2
Lo que no puede hacer es cambiar el stdout / stderr / stdin de un proceso después de haberlo lanzado. No es exactamente cierto. Úselo reptyrpara esto.
Stefan Seidel
198
nohup cmd &

nohup separa el proceso por completo (lo demoniza)

dsm
fuente
55
Aunque sucinto es valioso, la integridad es más valiosa. Aunque nohup es un núcleo de GNU, aquí sería apropiada una respuesta solo de bash (o una nota sobre que no hay una). Buena respuesta, no obstante.
Expiación limitada el
23
nohupSolo ignora la SIGHUPseñal. Ejecuta el proceso normalmente. Sin demonización.
nemo
1
@nemo Lo que significa que el proceso no se separa, sino que se desconectaría (y sería un hijo de init) si el caparazón saliera ... ¿verdad?
Noldorin
@Noldorin Sí. Ignorar SIGHUP, que se envía cuando finaliza el shell, dejará el proceso secundario ejecutándose y reubicándose en init.
nemo
@nemo nohup también silencia las entradas / salidas estándar. Haga un seguimiento con disown para separar por completo.
jiggunjer
60

Si está usando bash, intente ; ver bash (1) .disown [jobspec]

Otro enfoque que puedes probar es at now. Si no eres superusuario, tu permiso de uso atpuede estar restringido.

Randy Proctor
fuente
"disown" no parece ser un comando bash interno (no disponible en mi máquina, y uso bash). "nohup", como sugirió Ben, podría ser una forma mucho mejor (y estándar) de hacerlo.
1
Nunca pensé en usar "at", ¡gracias por la idea!
cadrian
1
atdelegar la ejecución a otra persona, ¡me gusta! +1
Ninsuo
1
Como punto de referencia, esto también funciona zsh.
Coderer
1
Además, disownno parece tener el efecto deseado con gnome-terminal- disowned procesos todavía son asesinados al salir del terminal. Me encantaría saber por qué / cómo.
Kyle Strand
38

Al leer estas respuestas, tuve la impresión inicial de que emitir nohup <command> &sería suficiente. Al ejecutar zsh en gnome-terminal, descubrí que nohup <command> &no evitaba que mi shell matara los procesos secundarios al salir. Aunque nohupes útil, especialmente con shells no interactivos, solo garantiza este comportamiento si el proceso secundario no restablece su controlador para la SIGHUPseñal.

En mi caso, nohupdebería haber evitado que las señales de bloqueo lleguen a la aplicación, pero la aplicación secundaria (VMWare Player en este caso) estaba restableciendo su SIGHUPcontrolador. Como resultado, cuando el emulador de terminal se cierra, aún podría matar sus subprocesos. Esto solo se puede resolver, que yo sepa, asegurando que el proceso se elimine de la tabla de trabajos del shell. Si nohupse reemplaza con un caparazón incorporado, como a veces es el caso, esto puede ser suficiente, sin embargo, en el caso de que no sea ...


disownse builtin una concha en bash, zshy ksh93,

<command> &
disown

o

<command> &; disown

si prefieres frases sencillas. Esto tiene el efecto generalmente deseable de eliminar el subproceso de la tabla de trabajos. Esto le permite salir del emulador de terminal sin indicar accidentalmente el proceso secundario. No importa cómo se SIGHUPvea el controlador, esto no debería matar el proceso de su hijo.

Después del rechazo, el proceso sigue siendo un elemento secundario de su emulador de terminal (juegue pstreesi desea ver esto en acción), pero después de que el emulador de terminal se cierre, debería verlo adjunto al proceso de inicio. En otras palabras, todo es como debería ser, y como presumiblemente quiere que sea.

¿Qué hacer si su shell no es compatible disown? Recomiendo encarecidamente cambiar a uno que sí lo haga, pero en ausencia de esa opción, tiene algunas opciones.

  1. screeny tmuxpuede resolver este problema, pero son soluciones mucho más pesadas, y no me gusta tener que ejecutarlas para una tarea tan simple. Son mucho más adecuados para situaciones en las que desea mantener un tty, generalmente en una máquina remota.
  2. Para muchos usuarios, puede ser conveniente ver si su shell admite una capacidad como la de zsh setopt nohup. Esto se puede usar para especificar que SIGHUPno se debe enviar a los trabajos en la tabla de trabajos cuando se cierra el shell. Puede aplicar esto justo antes de salir del shell, o agregarlo a la configuración del shell como ~/.zshrcsi siempre lo quisiera.
  3. Encuentre una manera de editar la tabla de trabajos. No pude encontrar una manera de hacer esto en tcsho csh, lo cual es algo inquietante.
  4. Escriba un pequeño programa en C para bifurcar y exec(). Esta es una solución muy pobre, pero la fuente solo debe consistir en un par de docenas de líneas. Luego puede pasar comandos como argumentos de línea de comandos al programa C, y así evitar una entrada específica del proceso en la tabla de trabajos.
Stephen Rosen
fuente
29
  1. nohup $COMMAND &
  2. $COMMAND & disown
  3. setsid command

He estado usando el número 2 durante mucho tiempo, pero el número 3 funciona igual de bien. Además, disowntiene un nohupindicador de -h, puede rechazar todos los procesos -ay puede rechazar todos los procesos en ejecución con -ar.

El silencio se logra por $COMMAND &>/dev/null.

¡Espero que esto ayude!

Mr. Minty Fresh
fuente
Corto y dulce; ¡Gracias por este útil resumen!
Sheljohn
No puedo creer que todavía recibo notificaciones para esta publicación ...
Sr. Minty Fresh
9

Creo que la pantalla podría resolver tu problema


fuente
9

en tcsh (y quizás también en otros shells), puede usar paréntesis para separar el proceso.

Compara esto:

> jobs # shows nothing
> firefox &
> jobs
[1]  + Running                       firefox

A esto:

> jobs # shows nothing
> (firefox &)
> jobs # still shows nothing
>

Esto elimina Firefox de la lista de trabajos, pero aún está vinculado al terminal; si ha iniciado sesión en este nodo a través de 'ssh', al intentar cerrar la sesión, el proceso ssh se bloqueará.

Nathan Fellman
fuente
9

La respuesta más simple y correcta para bash:

command & disown

No tiene que separar el proceso del terminal, sino del shell.

ManuelSchneid3r
fuente
7

Para desasociar tty shell, ejecute el comando a través de un sub-shell para

(mando)&

Cuando la salida utiliza el terminal cerrado, pero el proceso aún está vivo.

cheque -

(sleep 100) & exit

Abrir otra terminal

ps aux | grep sleep

El proceso aún está vivo.

jitendra
fuente
Esto es exactamente lo que necesitaba. Intenté agregar un acceso directo de consola para texto sublime y funciona perfectamente, esto es lo que terminé con: ("/ opt / Sublime Text 2 / sublime_text" $ @) &
Ron E
5

Hacer un segundo plano y poner en primer plano un trabajo es probablemente una de las primeras cosas que todo administrador de sistemas Unix debe saber.

Así es como se hace con bash:

./script.sh
# suspend process
{ctrl-Z}
# background process
bg
# list all backgrounded jobs
jobs
# bring it back to foreground
fg
djangofan
fuente
4

Puede ejecutar su comando usando el comando nohup, esto separa su proceso y redirige las salidas a un archivo determinado ... pero no estoy seguro de que eso sea exactamente lo que necesita ...

Ben
fuente
Podría jurar que había intentado nohup antes de usar exec, pero aparentemente no correctamente, ya que funciona así: nohup gnome-terminal -e "vim $ @" &> / dev / null &
2

Pruebe el demonio : debe estar disponible a través de su amigable administrador de paquetes y debe ocuparse de todas las formas de desasociarse del terminal.

ShiDoiSi
fuente
2

Simplemente agregue esto en su bashrc / zshrc:

detach() {
  "$@" 1>/dev/null 2>/dev/null &; disown
}

Luego puede ejecutar comandos rechazados como este:

detach gedit ~/.zshrc
B. Branchard
fuente
1

En mi .bashrc, tengo estas funciones precisamente para ese propósito:

function run_disowned() {
    "$@" & disown
}

function dos() {
    # run_disowned and silenced

    run_disowned "$@" 1>/dev/null 2>/dev/null
}

Prefije un comando con dospara ejecutarlo desconectado de la terminal.

La función está escrita para trabajar con bashy zsh.

ratones
fuente
1
Estoy un poco confundido en cuanto a por qué esta respuesta utiliza una función envuelto en otro, cuando su suficiente para sólo tiene que utilizar una función con el cuerpo de la siguiente manera: ( "$@" & disown) &> /dev/null. Tampoco tiene mucho sentido usar 1>y 2>, porque lo estás usando disown, lo que significa que estás usando bash, y en bash puedes hacer fácilmente &>para redirigir tanto stdout como stderr
Sergiy Kolodyazhnyy
Lo tengo como dos funciones porque (1) creo que es más fácil de leer de esta manera, y (2) necesito la run_disownedfuncionalidad en otros lugares en mis archivos de puntos. Tienes razón sobre el &>asunto, por supuesto.
mic_e
0

En Mac OS X, descubrí que necesito usar nohup AND disown para asegurarme de que el proceso secundario no se derribe con el terminal.

aaron
fuente
0

Yo uso el siguiente script para hacer esto. Detiene el proceso de impresión en el terminal, se desconecta nohupy sale con el estado de retorno si el comando finaliza dentro del TIMEOUT.

#!/bin/bash

TIMEOUT=0.1

CMD=( "$@" )
#Could have some shortcuts here, e.g. replace "somefile.c" with "gedit somefile.c"

#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
#print the command for debugging and to see bash variable expansion
printf "%q " "${CMD[@]}"
echo
nohup "${CMD[@]}" >/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: $CMD"
#return the exit status of nohup, whatever it was
exit $NOHUP_STATUS

Ejemplo de uso:

>>> run false
false
Error: false
>>> echo $?
1
>>> run true
true
>>> run sleep 10
sleep 10
>>>
jozxyqk
fuente
0

sudo apt install ucommon-utils

pdetach command

Ahí tienes :)

d4rk4ng31
fuente
-1

Muchas respuestas sugirieron 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 la identificación 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
hacks
fuente
1
Usar una aplicación NodeJS (en comparación con un comando pequeño y robusto como nohup) para controlar los procesos de Unix parece ... realmente exagerado, y para ser honesto, bastante extraño. Usaría monit si necesita la funcionalidad de reinicio.
Sergio
@ Sergio es su elección utilizar la aplicación depricated.
piratea
Se han realizado varios lanzamientos este año (uno hace 4 días), por lo que no veo cómo / por qué puede pensar que monit es una aplicación obsoleta. @ver mmonit.com/monit/changes
Sergio
Estaba hablando de nohup.
piratea el
1
nohupes un simple comando POSIX estándar, así que el mismo comentario: de ninguna manera está en desuso. @ver unix.com/man-page/posix/1p/nohup
Sergio
-1

Si su objetivo es simplemente iniciar una aplicación de línea de comandos sin mantener la ventana del terminal, entonces puede intentar ejecutar la aplicación después de iniciar el terminal con alt-F2.

MattKelly
fuente