2009-03-23 11:59:25 +0000 2009-03-23 11:59:25 +0000
311
311

¿Cómo puedo separar un proceso de la terminal, completamente?

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

Sin embargo, estoy luchando con cómo separar completamente un proceso (ej. Firefox) de la terminal desde la que ha sido lanzado - es decir. evitar que dicho proceso (no) hijo

  • se termine al cerrar la terminal de origen
  • “contamina” la terminal de origen a través de STDOUT/STDERR

Por ejemplo, para iniciar Vim en una ventana de terminal “adecuada”, he probado un simple script como el siguiente:

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

Sin embargo, eso sigue causando contaminación (además, pasar un nombre de archivo no parece funcionar).

Respuestas (18)

355
355
355
2009-03-23 13:18:35 +0000

En primer lugar; una vez que has iniciado un proceso, puedes ponerlo en segundo plano deteniéndolo primero (presiona Ctrl-Z) y luego escribiendo bg para que se reanude en segundo plano. Ahora es un “trabajo”, y su stdout/stderr/stdin sigue conectado a su terminal.

Puede iniciar un proceso como fondo inmediatamente añadiendo un “&” al final del mismo:

firefox &

Para ejecutarlo en el fondo silenciado, use esto:

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

Alguna información adicional:

nohup es un programa con el que puedes usar para ejecutar tu aplicación con de tal manera que su stdout/stderr pueda ser enviado a un archivo en su lugar y de tal manera que al cerrar el script padre no se SIGNIFIQUE el hijo. Sin embargo, tienes que haber tenido la previsión de usarlo antes de iniciar la aplicación. Debido a la forma en que nohup funciona, no puedes simplemente aplicarlo a un proceso en ejecución.

disown es un bash builtin que elimina un trabajo de la shell de la lista de trabajos de la shell. Lo que esto significa básicamente es que ya no puedes usar fg, bg en él, pero lo más importante, cuando cierras tu shell ya no se colgará o enviará un SIGHUP a ese niño. A diferencia de nohup, disown se usa después de que el proceso se ha lanzado y se ha puesto en segundo plano.

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

Para manejar la salida de un proceso en segundo plano, tiene muchas opciones de scripts, siendo “nohup” probablemente la primera que se le ocurre. Pero para los procesos interactivos que empiezas pero olvidaste silenciar (firefox < /dev/null &>/dev/null &) no puedes hacer mucho, realmente.

Te recomiendo que consigas GNU screen. Con la pantalla puedes simplemente cerrar tu shell en ejecución cuando la salida del proceso se convierte en una molestia y abrir uno nuevo (^Ac).


Oh, y por cierto, no uses “$@” donde lo estás usando.

$@ significa, $1, $2, $3 …, lo que convertiría tu comando en:

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

Eso probablemente no es lo que quieres porque -sólo toma un argumento. Usa $1 para mostrar que tu script sólo puede manejar un argumento.

Es realmente difícil hacer que varios argumentos funcionen correctamente en el escenario que diste (con el gnome-terminal -e) porque -e toma sólo un argumento, que es una cadena de comandos de shell. Tendrías que codificar tus argumentos en uno solo. La mejor y más robusta, pero más bien torpe, manera es así:

gnome-terminal -e "vim $(printf "%q " "$@")"
202
202
202
2009-03-23 12:17:32 +0000
nohup cmd &

nohup desprende el proceso completamente (lo demoniza)

62
62
62
2009-03-23 12:05:02 +0000

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

Otro enfoque que puede intentar es at now. Si no eres superusuario, tu permiso para usar at puede estar restringido.

41
41
41
2014-01-22 17:08:16 +0000

Al leer estas respuestas, tuve la impresión inicial de que la emisión de nohup <command> & sería suficiente. Corriendo zsh en gnome-terminal, encontré que nohup <command> & no evitó que mi proyectil matara los procesos infantiles a la salida. Aunque nohup es útil, especialmente con shells no interactivos, sólo garantiza este comportamiento si el proceso hijo no reinicia su manejador para la señal SIGHUP.

En mi caso, nohup debería haber evitado que las señales de cuelgue lleguen a la aplicación, pero la aplicación hija (VMWare Player en este caso) estaba reiniciando su manejador SIGHUP. Como resultado, cuando el emulador de terminal salga, todavía podría matar sus subprocesos. Esto sólo puede resolverse, que yo sepa, asegurándose de que el proceso sea eliminado de la tabla de trabajos del shell. Si nohup es anulado con un shell builtin, como es a veces el caso, esto puede ser suficiente, sin embargo, en el caso de que no lo sea…

  • *

disown es un shell builtin en bash, zsh, y ksh93,

<command> &
disown

o

<command> &; disown

si prefiere una línea. Esto tiene el efecto generalmente deseable de eliminar el subproceso de la tabla de trabajos. Esto le permite salir del emulador de terminales sin señalar accidentalmente el proceso hijo en absoluto. No importa cómo se vea el manejador SIGHUP, esto no debería matar a tu proceso hijo.

Después de la desconexión, el proceso sigue siendo un hijo de tu emulador de terminal (juega con pstree si quieres ver esto en acción), pero después de que el emulador de terminal salga, deberías verlo unido al proceso init. En otras palabras, todo es como debería ser, y como presumiblemente quieres que sea.

¿Qué hacer si tu shell no soporta disown? Yo abogaría fuertemente por cambiar a uno que sí lo haga, pero en ausencia de esa opción, tienes algunas opciones.

  1. screen y tmux pueden 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 adecuadas para situaciones en las que se quiere mantener un tty, típicamente en una máquina remota.
  2. Para muchos usuarios, puede ser deseable ver si su shell soporta una capacidad como la de zsh setopt nohup. Esto puede ser usado para especificar que SIGHUP no debe ser enviado a los trabajos en la tabla de trabajos cuando el shell sale. Puede aplicar esto justo antes de salir del shell, o agregarlo a la configuración del shell como ~/.zshrc si siempre lo quiere encendido.
  3. Encuentra una manera de editar la tabla de trabajos. No pude encontrar una manera de hacer esto en tcsh o csh, lo cual es algo perturbador.
  4. Escribe un pequeño programa de C para que se bifurque y exec(). Esta es una solución muy pobre, pero la fuente sólo debería consistir en un par de docenas de líneas. Entonces 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.
30
30
30
2015-08-25 14:39:31 +0000
  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, disown tiene una bandera de nohup, puede desautorizar todos los procesos con -h, y puede desautorizar todos los procesos en ejecución con -a.

El silenciamiento se logra con -ar.

¡Espero que esto ayude!

9
9
9
2017-05-05 11:55:05 +0000

La respuesta más simple y la única correcta para el golpe:

command & disown

No tienes que separar el proceso de la terminal, sino del caparazón.

9
9
9
2009-03-23 14:55:15 +0000

en tcsh (y tal vez en otros shells también), puedes usar paréntesis para separar el proceso.

Compara esto:

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

Con esto:

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

Esto elimina a firefox de la lista de trabajos, pero sigue ligado a la terminal; si te conectaste a este nodo a través de ‘ssh’, tratar de cerrar la sesión seguirá colgando el proceso ssh.

7
7
7
2012-08-07 05:18:25 +0000

Para disociar el shell tty ejecute el comando a través del sub-shell para por ejemplo

(comando)&

Cuando salga use la terminal cerrada pero el proceso aún está vivo.

compruebe -

(sleep 100) & exit

Abra la otra terminal

ps aux | grep sleep

El proceso aún está vivo.

5
5
5
2013-05-22 23:00:56 +0000

El fondo y el primer plano de un trabajo es probablemente una de las primeras cosas que todo administrador de sistemas Unix debería saber.

Así es como se hace con el bash:

./script.sh
# suspend process
{ctrl-Z}
# background process
bg
# list all backgrounded jobs
jobs
# bring it back to foreground
fg
4
4
4
2009-03-23 12:03:50 +0000

Puedes ejecutar tu comando usando el comando nohup, este desprende tu proceso y redirige las salidas a un archivo determinado… pero no estoy seguro de que sea exactamente lo que necesitas..

2
2
2
2018-02-05 16:14:17 +0000

Sólo añade esto en tu bashrc/zshrc:

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

Entonces puedes ejecutar los comandos de repudio así:

detach gedit ~/.zshrc
2
2
2
2009-03-23 12:10:49 +0000

Pruebe daemon – debería estar disponible en su amigable gestor de paquetes y encargarse de todas las formas de disociarse de la terminal.

1
1
1
2015-06-14 17:53:47 +0000

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
}

Prefijo un comando con dos para ejecutarlo separado de la terminal.

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

0
0
0
2010-06-19 16:46:44 +0000

He descubierto en Mac OS X que necesito usar tanto nohup como disown para asegurarme de que el proceso del niño no se rompa con el terminal.

0
0
0
2014-09-21 04:42:43 +0000

Utilizo el siguiente guión para hacer esto. Detiene el proceso de impresión en la terminal, se separa con nohup, y sale con el estado de retorno si el comando termina 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
>>>
0
0
0
2019-06-21 07:14:46 +0000

sudo apt install ucommon-utils

pdetach command

Ahí lo tienes :)

-1
-1
-1
2017-02-15 04:16:48 +0000

Muchas respuestas sugirieron usar nohup. Preferiría sugerir el uso de pm2 . Usar pm2 en lugar de nohup tiene muchas ventajas, como mantener la aplicación viva, mantener los archivos de registro de la aplicación y muchas otras características. Para más detalles compruébalo .

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 con

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

Para monitorizar procesos use 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

Gestione los procesos usando el nombre de la aplicación o el ID del proceso o gestione 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
-1
-1
-1
2017-04-05 13:47:37 +0000

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