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

Come posso staccare completamente un processo dal terminale?

Uso Tilda (terminale a discesa) su Ubuntu come “centrale di comando” - più o meno come altri potrebbero usare GNOME Do, Quicksilver o Launchy.

Tuttavia, sto lottando su come staccare completamente un processo (ad esempio Firefox) dal terminale da cui è stato lanciato - cioè evitare che un tale processo (non) infantile

  • sia terminato quando si chiude il terminale di origine
  • “inquina” il terminale di origine tramite STDOUT/STDERR

Per esempio, per avviare Vim in una “vera e propria” finestra di terminale, ho provato un semplice script come il seguente:

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

Tuttavia, questo causa ancora inquinamento (anche il passaggio di un nome di file non sembra funzionare).

Risposte (18)

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

Prima di tutto, una volta avviato un processo, si può fare uno sfondo fermandolo prima (premere Ctrl-Z) e poi digitando bg per farlo riprendere in background. Ora è un “lavoro”, e i suoi stdout/stderr/stdin sono ancora collegati al vostro terminale.

Potete iniziare un processo come sfondo immediatamente aggiungendo un “&” alla fine di esso:

firefox &

Per eseguirlo in background silenziato, usate questo:

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

Alcune informazioni aggiuntive:

nohup è un programma che potete usare per eseguire la vostra applicazione con in modo che il suo stdout/stderr possa invece essere inviato ad un file e in modo tale che la chiusura dello script padre non SIGHUP il figlio. Tuttavia, è necessario aver avuto la lungimiranza di usarlo prima di avviare l'applicazione. A causa del modo in cui funziona nohup, non è possibile applicarlo a un processo in esecuzione.

disown è un bash builtin che rimuove un lavoro shell dalla lista dei lavori shell. Ciò significa fondamentalmente che non si può più usare fg, bg su di esso, ma, cosa più importante, quando si chiude il guscio non si appende o non si invia più un SIGHUP a quel bambino. A differenza di nohup, disown viene usato **dopo che il processo è stato lanciato e messo in background.

Quello che non potete_ fare, è cambiare lo stdout/stderr/stdin di un processo dopo averlo lanciato. Almeno non dal guscio. Se lanciate il vostro processo e gli dite che il suo stdout è il vostro terminale (che è quello che fate di default), allora quel processo è configurato per l'output sul vostro terminale. La vostra shell non ha nulla a che fare con l'impostazione del FD dei processi, che è puramente qualcosa che il processo stesso gestisce. Il processo stesso può decidere se chiudere o meno il suo stdout/stderr/stdin, ma non potete usare la vostra shell per forzarlo a farlo.

Per gestire l'output di un processo in background, avete un sacco di opzioni da script, “nohup” è probabilmente il primo che vi viene in mente. Ma per i processi interattivi si inizia ma si dimentica di mettere a tacere (firefox < /dev/null &>/dev/null &) non si può fare molto, davvero.

Vi consiglio di prendere GNU screen. Con lo schermo potete semplicemente chiudere il vostro guscio in esecuzione quando l'uscita del processo diventa un fastidio e aprirne uno nuovo (^Ac).


Oh, e a proposito, non usate “$@” dove lo state usando.

$@ significa, $1, $2, $3, $1 …, che trasformerebbe il vostro comando in:

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

Probabilmente non è quello che volete perché -e prende solo un solo argomento. Usate gnome-terminal -e per mostrare che il vostro script può gestire un solo argomento.

È davvero difficile far funzionare correttamente più argomenti nello scenario che avete dato (con l’-e) perché &007 prende solo un argomento, che è una stringa di comando di shell. Dovreste codificare i vostri argomenti in uno solo. Il modo migliore e più robusto, ma piuttosto cludgy, è così:

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

nohup stacca completamente il processo (demonizza il processo)

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

Se si usa bash, provare disown [jobspec]; vedere bash(1) .

Un altro approccio che si può provare è at now. Se non sei un superutente, il tuo permesso di usare at può essere limitato.

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

Leggendo queste risposte, ho avuto l'impressione iniziale che l'emissione di nohup <command> & sarebbe stata sufficiente. Eseguendo zsh in gnome-terminale, ho scoperto che nohup <command> & non ha impedito al mio guscio di uccidere i processi dei bambini all'uscita. Sebbene nohup sia utile, specialmente con i shell non interattivi, garantisce questo comportamento solo se il processo bambino non resetta il suo handler per il segnale SIGHUP.

Nel mio caso, nohup avrebbe dovuto impedire che i segnali di sospensione raggiungessero l'applicazione, ma l'applicazione bambino (VMWare Player in questo caso) stava resettando il suo handler SIGHUP. Di conseguenza, quando l'emulatore di terminale esce, potrebbe ancora uccidere i vostri sottoprocessi. Questo può essere risolto, a mia conoscenza, solo assicurando che il processo sia rimosso dalla tabella dei lavori del guscio. Se nohup è sovrastato da un guscio costruito, come talvolta accade, questo può essere sufficiente, tuttavia, nel caso in cui non sia…


disown è un guscio costruito in bash, zsh, e ksh93,

<command> &
disown

o

<command> &; disown

se si preferisce una sola riga. Questo ha l'effetto generalmente desiderabile di rimuovere il sottoprocesso dalla tabella dei lavori. Ciò consente di uscire dall'emulatore di terminale senza segnalare accidentalmente il processo figlio. Non importa quale sia l'aspetto del manipolatore SIGHUP, questo non dovrebbe uccidere il vostro processo figlio.

Dopo la disconoscimento, il processo è ancora figlio del vostro emulatore di terminale (giocate con pstree se volete vederlo in azione), ma dopo che l'emulatore di terminale esce, dovreste vederlo attaccato al processo init. In altre parole, tutto è come dovrebbe essere, e come presumibilmente volete che sia.

Cosa fare se il vostro guscio non supporta disown? Sarei fortemente a favore del passaggio a uno che lo supporta, ma in assenza di questa opzione, avete poche scelte.

  1. screen e tmux possono risolvere questo problema, ma sono soluzioni molto più pesanti, e non mi piace doverle eseguire per un compito così semplice. Sono molto più adatte a situazioni in cui si vuole mantenere un tty, tipicamente su una macchina remota.
  2. setopt nohup e SIGHUP possono risolvere questo problema, ma sono soluzioni molto più pesanti, e non mi piace doverle far funzionare per un compito così semplice. Per molti utenti, può essere desiderabile vedere se il vostro guscio supporta una capacità come zsh ~/.zshrc. Questo può essere usato per specificare che tcsh non deve essere inviato ai lavori nella tabella dei lavori quando lo shell esce. Si può applicare questa funzionalità appena prima di uscire dalla shell, oppure aggiungerla alla configurazione della shell come csh se si vuole sempre che sia attiva.
  3. 3. Trovare un modo per modificare la tabella dei lavori. Non sono riuscito a trovare un modo per farlo in exec() o &007, il che è un po’ inquietante.
  4. Trovare un modo per modificare la tabella dei lavori. Scrivete un piccolo programma in C per forchetta e &007. Questa è una soluzione molto povera, ma la fonte dovrebbe consistere solo di un paio di dozzine di linee. Si possono poi passare comandi come argomenti di linea di comando al programma C, e quindi evitare una voce specifica del processo nella tabella dei lavori.
30
30
30
2015-08-25 14:39:31 +0000
  1. nohup $COMMAND &
  2. $COMMAND & disown
  3. setsid command

Ho usato il numero 2 per molto tempo, ma il numero 3 funziona altrettanto bene. Inoltre, disown ha un flag nohup di -h, può disconoscere tutti i processi con -a, e può disconoscere tutti i processi in esecuzione con -ar.

Il silenziamento è realizzato da $COMMAND &>/dev/null.

Spero che questo aiuti!

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

Risposta più semplice e corretta per il bash:

command & disown

Non è necessario staccare il processo dal terminale, ma dal guscio.

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

in tcsh (e forse anche in altri gusci), si possono usare le parentesi per staccare il processo.

Confronta questo:

> jobs # shows nothing
> firefox &
> jobs
[1] + Running firefox
``` ```
> jobs # shows nothing
> (firefox &)
> jobs # still shows nothing
>

A questo:

&001

Questo rimuove firefox dall'elenco dei lavori, ma è ancora legato al terminale; se avete effettuato l'accesso a questo nodo tramite ‘ssh’, cercando di effettuare il logout, il processo ssh si bloccherà comunque.

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

Per dissociare il comando tty shell eseguire il comando attraverso il sottoguscio per es.

(comando)& &

Quando il terminale usato in uscita è chiuso ma il processo è ancora vivo.

check -

(sleep 100) & exit

Open other terminal

ps aux | grep sleep

Process is still alive.

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

Il background e il primo piano di un lavoro è probabilmente una delle primissime cose che ogni sys-admin Unix dovrebbe sapere.

Ecco come si fa con il 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

Puoi eseguire il tuo comando usando il comando nohup, questo stacca il tuo processo e reindirizza gli output ad un dato file… ma non sono sicuro che sia esattamente quello che ti serve…

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

Basta aggiungere questo nel vostro bashrc/zshrc:

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

Poi potete eseguire comandi rinnegati come questo:

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

Provate daemon – dovrebbe essere disponibile presso il vostro amichevole gestore di pacchetti e occuparsi in modo completo di ogni modo di dissociarsi dal terminale.

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

Nel mio .bashrc, ho queste funzioni proprio per questo scopo:

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

function dos() {
    # run_disowned and silenced

    run_disowned "$@" 1>/dev/null 2>/dev/null
}
``` &001 


Prefisso un comando con `dos` per eseguirlo staccato dal terminale. 


La funzione è scritta per funzionare con `bash` e `zsh`.
0
0
0
2010-06-19 16:46:44 +0000

Ho trovato su Mac OS X che devo usare sia il nohup che il disconoscimento per garantire che il processo del bambino non venga abbattuto con il terminale.

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

Per fare questo utilizzo il seguente script. Interrompe la stampa del processo al terminale, si stacca con nohup, ed esce con lo stato di ritorno se il comando termina entro 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
``` ```
>>> run false
false
Error: false
>>> echo $?
1
>>> run true
true
>>> run sleep 10
sleep 10
>>>

Esempio d'uso:

&001

0
0
0
2019-06-21 07:14:46 +0000

sudo apt install ucommon-utils

pdetach command

Ci siamo :)

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

Molte risposte suggerite utilizzando nohup. Preferisco suggerire l'uso di pm2 . L'uso di pm2 rispetto a nohup ha molti vantaggi, come il mantenimento dell'applicazione, la manutenzione dei file di log per l'applicazione e molte altre caratteristiche. Per maggiori dettagli controllare questo .

Per installare pm2 è necessario scaricare npm. Per il sistema basato su Debian

sudo apt-get install npm

e per Redhat

sudo yum install npm

Oppure si può seguire queste istruzioni . Dopo aver installato npm usatela per installare pm2

npm install pm2@latest -g
``` ```
$ pm2 start app.js # Start, Daemonize and auto-restart application (Node)
$ pm2 start app.py # Start, Daemonize and auto-restart application (Python)

Una volta terminata l'installazione potete avviare la vostra applicazione da

$ 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
``` ```
$ pm2 stop <app_name|id|'all'|json_conf>
$ pm2 restart <app_name|id|'all'|json_conf>
$ pm2 delete <app_name|id|'all'|json_conf>

Per il monitoraggio dei processi usate i seguenti comandi:

$HOME/.pm2/logs #contain all applications logs
``` &001 


Gestite i processi usando il nome dell'applicazione o l'id del processo oppure gestite tutti i processi insieme: 


&001 &001 
I file di log si trovano in 


&001
-1
-1
-1
2017-04-05 13:47:37 +0000

Se il vostro obiettivo è quello di lanciare semplicemente un'applicazione a riga di comando senza tenere la finestra del terminale, allora potreste provare ad eseguire l'applicazione dopo aver lanciato il terminale con alt-F2.