Como posso fechar um terminal sem matar o comando executado nele?

271

Por vezes, quero iniciar um processo e esquecer-me disso. Se eu iniciá-lo a partir da linha de comando, assim:

redshift

Eu não consigo fechar o terminal ou isso irá matar o processo. Posso executar um comando de forma que eu possa fechar o terminal sem matar o processo?

    
por Matthew 12.11.2010 / 23:57

11 respostas

273

Um dos 2 seguintes deve funcionar:

$ nohup redshift &

ou

$ redshift &
$ disown

Veja o seguinte para mais informações sobre como isso funciona:

por 13.11.2010 / 00:30
133

Se o seu programa já estiver em execução , você poderá pausá-lo com Ctrl-Z , colocá-lo em segundo plano com bg e, em seguida, disown , assim:

$ sleep 1000
^Z
[1]+  Stopped                 sleep 1000
$ bg
$ disown
$ exit
    
por 13.11.2010 / 06:36
39

Boa resposta já foi postada por @StevenD, mas acho que isso pode esclarecer um pouco mais.

A razão pela qual o processo é eliminado na terminação do terminal é que o processo que você inicia é um processo filho do terminal. Depois de fechar o terminal, isso também matará esses processos filhos. Você pode ver a árvore de processos com pstree , por exemplo, ao executar kate & no Konsole:

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

Para tornar o processo kate desvinculado de konsole quando você terminar konsole , use nohup com o comando, assim:

nohup kate &

Depois de fechar konsole , pstree ficará assim:

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

e kate sobreviverão. :)

Uma alternativa é usar screen / tmux / byobu , que manterá o shell em execução, independentemente do terminal.

    
por 05.12.2012 / 12:31
23

Você pode executar o processo assim no terminal

setsid process

Isso executará o programa em uma nova sessão. Conforme explicado no link

    
por 30.10.2012 / 06:55
7

A única maneira de fazer tudo isso é fechar o stdin e colocar em segundo plano o comando:

command <&- & 

Então ele não será encerrado quando você sair do shell. Redirecionar stdout é uma boa opção para fazer.

A desvantagem é que você não pode fazer isso depois do fato.

    
por 14.03.2014 / 05:55
7

Eu tenho um script para:

  • Executa comandos arbitrários em segundo plano

  • Impede que sejam mortos com a janela do terminal

  • Suprimir sua saída

  • Lida com o status de saída

Eu o uso principalmente para gedit , evince , inkscape etc que todos têm muita saída de terminal irritante. Se o comando terminar antes de TIMEOUT , o status de saída do nohup é retornado em vez de zero.

#!/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

exemplos ...

>>> 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
    
por 15.02.2014 / 05:12
7

Embora todas as sugestões funcionem bem, descobri que minha alternativa é usar o screen , um programa que configura um terminal virtual na tela.

Você pode considerar começar com screen -S session_name . A tela pode ser instalada em praticamente todos os derivados Linux e Unix. Pressionar Ctrl + A e (em minúsculas) C iniciará uma segunda sessão. Isso permitiria alternar entre a sessão inicial pressionando Ctrl + A e 0 ou a sessão mais recente pressionando Ctrl + A e 1 . Você pode ter até dez sessões em um terminal. Eu costumava iniciar uma sessão no trabalho, ir para casa, ssh na minha máquina de trabalho e invocar screen -d -R session_name . Isso irá reconectar você a essa sessão remota.

    
por 19.02.2015 / 00:07
4

Você pode definir um processo (PID) para não receber um sinal HUP ao sair e fechar a sessão do terminal. Use o seguinte comando:

nohup -p PID
    
por 18.02.2016 / 06:30
4

Eu prefiro:

(applicationName &)

por exemplo: linux@linux-desktop:~$ (chromium-browser &)

Certifique-se de usar parênteses ao digitar o comando!

    
por 02.03.2016 / 12:15
3

Indiscutivelmente semelhante à resposta oferecida pela apolinsky , eu uso uma variante em screen . O comando baunilha é assim

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

A sessão pode ser desconectada com Ctrl A Ctrl D e reconectada no caso simples com screen -r . Eu tenho isso embrulhado em um script chamado session que vive no meu PATH pronto para acesso 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 "$@; echo; echo '--------------------'; read -p 'ALL DONE (Enter to exit):'"
    echo "ERROR: 'screen' is not installed on this system" >&2
fi
exit 1

Isso só funciona quando você sabe antecipadamente que deseja desconectar um programa. Ele não prevê que um programa já em execução seja desconectado.

    
por 29.03.2016 / 17:10
2

Similarmente a outras respostas postadas anteriormente, pode-se transferir um processo em execução para usar a "tela" retrospectivamente graças a reptyr e, em seguida, fechar o terminal. As etapas são descritas nesta postagem . Os passos a seguir são:

  1. Suspenda o processo
  2. Retomar o processo em segundo plano
  3. Ignorar o processo
  4. Iniciar uma sessão de tela
  5. Encontre o PID do processo
  6. Use o reptyr para assumir o processo
por 01.05.2018 / 22:15