Como impedir que um processo em segundo plano seja interrompido após o fechamento do cliente SSH no Linux


291

Estou trabalhando em uma máquina Linux através do SSH (Putty). Eu preciso deixar um processo em execução durante a noite, para poder fazer isso iniciando o processo em segundo plano (com um e comercial no final do comando) e redirecionando o stdout para um arquivo.

Para minha surpresa, isso não funciona. Assim que fecho a janela Putty, o processo é interrompido.

Como posso impedir que isso aconteça ??

Respostas:


301

Confira o programa " nohup ".


4
Como você para depois?
Derek Dahmer

9
Entre e faça "kill <pid>". Use "pidof" se você não conhece o pid.
precisa

32
Você pode usar nohup command > /dev/null 2>&1 &para ser executado em segundo plano, sem criar qualquer stdout ou stderr saída (não nohup.outarquivo)
KCD

E se eu precisar fornecer alguma entrada? Por exemplo, eu tenho um script de longa duração que preciso executar em segundo plano, mas ele primeiro pede minha senha de FTP. nohupnão ajuda neste caso. Existe uma maneira de mexer com Ctrl+Z/ bg?
Sergey

1
Como sou preguiçoso e péssimo em memorizar sequências enigmáticas de personagens, escrevi isso com base no que o @KCD disse e o uso muito.
Anomaly

167

Eu recomendaria o uso do GNU Screen . Ele permite que você se desconecte do servidor enquanto todos os seus processos continuam em execução. Não sei como vivi sem ela antes de saber que existia.


7
Este é um dos melhores softwares que já usei. Seriamente. Eu o tenho rodando em uma caixa BSD na qual ssh de TODA PARTE LUGAR, e posso simplesmente reconectá-lo à minha tela e ter todos os meus terminais onde estou fazendo todo tipo de coisa.
11118 Adam Adamkiewicz

1
Eu posso atestar este. Tela é uma ótima aplicação. A capacidade de reconectar é incrível e economiza muito trabalho potencialmente perdido.
willasaywhat

Eu até o uso em máquinas locais e conecto vários xterms à mesma sessão de tela (tela -x). Dessa forma, posso abrir muitas janelas na minha sessão de tela e alternar livremente meus vários xterms de janela para janela.
Adam Jaskiewicz

17
Depende se você precisa se reconectar ao aplicativo em segundo plano ou não. Se o fizer, sim, a tela é a única maneira de voar. Se for demitir e esquecer, nohup se encaixa perfeitamente, se não melhor.
Dave Sherohman 13/11/2008

1
+1 para tela. Ou, como alternativa, o tmux (eu gosto mais deste que a tela) ou até o byobu, que é uma ótima interface para a tela ou o tmux. Você pode digitar screen para obter um shell para usar e retornar mais tarde a qualquer momento, ou executar seu comando com a tela, como "comando de tela": a sessão de tela existirá enquanto o processo "comando" existir, e se for algo por muito tempo, você pode voltar e ver a saída padrão a qualquer momento.
gerlos

81

Quando a sessão é fechada, o processo recebe o sinal SIGHUP que aparentemente não está captando. Você pode usar o nohupcomando ao iniciar o processo ou o comando interno do bash disown -hapós iniciar o processo para impedir que isso aconteça:

> help disown
disown: disown [-h] [-ar] [jobspec ...]
     By default, removes each JOBSPEC argument from the table of active jobs.
    If the -h option is given, the job is not removed from the table, but is
    marked so that SIGHUP is not sent to the job if the shell receives a
    SIGHUP.  The -a option, when JOBSPEC is not supplied, means to remove all
    jobs from the job table; the -r option means to remove only running jobs.

4
A vantagem aqui é que a renúncia funciona para processos que já foram iniciados.
Christian K.

1
'Jobspec' significa pid?
Stewart

1
Não se preocupe, achou esta resposta aqui stackoverflow.com/questions/625409/...
Stewart

42

daemonize? nohup? TELA? (tmux ftw, a tela é lixo ;-)

Faça o que todos os outros aplicativos fizeram desde o início - garfo duplo.

# ((exec sleep 30)&)
# grep PPid /proc/`pgrep sleep`/status
PPid:   1
# jobs
# disown
bash: disown: current: no such job

Bang! Concluído :-) Eu usei isso inúmeras vezes em todos os tipos de aplicativos e em muitas máquinas antigas. Você pode combinar com redirecionamentos e outros enfeites para abrir um canal privado entre você e o processo.

Crie como coproc.sh:

#!/bin/bash

IFS=

run_in_coproc () {
    echo "coproc[$1] -> main"
    read -r; echo $REPLY
}

# dynamic-coprocess-generator. nice.
_coproc () {
    local i o e n=${1//[^A-Za-z0-9_]}; shift
    exec {i}<> <(:) {o}<> >(:) {e}<> >(:)
. /dev/stdin <<COPROC "${@}"
    (("\$@")&) <&$i >&$o 2>&$e
    $n=( $o $i $e )
COPROC
}

# pi-rads-of-awesome?
for x in {0..5}; do
    _coproc COPROC$x run_in_coproc $x
    declare -p COPROC$x
done

for x in COPROC{0..5}; do
. /dev/stdin <<RUN
    read -r -u \${$x[0]}; echo \$REPLY
    echo "$x <- main" >&\${$x[1]}
    read -r -u \${$x[0]}; echo \$REPLY
RUN
done

e depois

# ./coproc.sh 
declare -a COPROC0='([0]="21" [1]="16" [2]="23")'
declare -a COPROC1='([0]="24" [1]="19" [2]="26")'
declare -a COPROC2='([0]="27" [1]="22" [2]="29")'
declare -a COPROC3='([0]="30" [1]="25" [2]="32")'
declare -a COPROC4='([0]="33" [1]="28" [2]="35")'
declare -a COPROC5='([0]="36" [1]="31" [2]="38")'
coproc[0] -> main
COPROC0 <- main
coproc[1] -> main
COPROC1 <- main
coproc[2] -> main
COPROC2 <- main
coproc[3] -> main
COPROC3 <- main
coproc[4] -> main
COPROC4 <- main
coproc[5] -> main
COPROC5 <- main

E lá vai você, desovar o que for. o <(:) abre um canal anônimo por meio da substituição do processo, que morre, mas o canal permanece porque você tem um identificador para ele. Eu costumo fazer um em sleep 1vez de, :porque é um pouco atrevido, e eu recebia um erro "arquivo ocupado" - nunca acontece se um comando real for executado (por exemplo, command true)

"fornecimento de heredoc":

. /dev/stdin <<EOF
[...]
EOF

Isso funciona em todos os shell que eu já tentei, incluindo o busybox / etc (initramfs). Eu nunca tinha visto isso antes, eu o descobri independentemente enquanto cutucava, quem sabia que a fonte podia aceitar argumentos? Mas geralmente serve como uma forma de avaliação muito mais gerenciável, se houver algo assim.


2
por que o voto negativo ... e daí se a pergunta for antiga; é obviamente relevante, considerando que há 11 outras respostas que são péssimas. essas soluções são, sem sistema, a maneira idiomática e aceita de daemonize nos últimos 30 anos, não aplicativos inúteis, por exemplo. nohup et al.
precisa

7
não importa quão boa seja a sua resposta, às vezes alguém no SO não vai gostar e vai votar em votação. É melhor não se preocupar muito com isso.
Alex D

1
@ tbc0 ... try ssh myhost "((exec sleep 500)&) >/dev/null"
anthonyrisinger

1
@anthonyrisinger ok, isso funciona. Eu acho que isso é mais limpo: ssh myhost 'sleep 500 >&- 2>&- <&- &' TMTOWTDI;)
tbc0 11/11

1
Isso é ótimo. a única solução que realmente funciona no busybox. merece mais votos positivos
Hamy

34
nohup blah &

Substitua o nome do processo por blá!


2
convém adicionar redirecionamento padrão e erro padrão.
David Nehme 12/11/08

9
nohup redireciona stdout e stderr para nohup.out (ou nohup.out e nohup.err, dependendo da versão), portanto, a menos que você esteja executando vários comandos, não é necessário.
Chas. Owens

17

Pessoalmente, gosto do comando 'batch'.

$ batch
> mycommand -x arg1 -y arg2 -z arg3
> ^D

Isso o coloca em segundo plano e envia os resultados para você. É uma parte do cron.


11

Como outros observaram, para executar um processo em segundo plano para que você possa se desconectar da sua sessão SSH, é necessário que o processo em segundo plano se desassocie adequadamente de seu terminal de controle - que é a pseudo-tty que a sessão SSH usa.

Você pode encontrar informações sobre processos de daemon em livros como o "Advanced Network Program, Stevens, Vol. 1, 3rd Edn" ou "Advanced Unix Programming" de Rochkind.

Recentemente (nos últimos dois anos) tive que lidar com um programa recalcitrante que não se daemonizou adequadamente. Acabei lidando com isso criando um programa de daemonização genérico - semelhante ao nohup, mas com mais controles disponíveis.

Usage: daemonize [-abchptxV][-d dir][-e err][-i in][-o out][-s sigs][-k fds][-m umask] -- command [args...]
  -V          print version and exit
  -a          output files in append mode (O_APPEND)
  -b          both output and error go to output file
  -c          create output files (O_CREAT)
  -d dir      change to given directory
  -e file     error file (standard error - /dev/null)
  -h          print help and exit
  -i file     input file (standard input - /dev/null)
  -k fd-list  keep file descriptors listed open
  -m umask    set umask (octal)
  -o file     output file (standard output - /dev/null)
  -s sig-list ignore signal numbers
  -t          truncate output files (O_TRUNC)
  -p          print daemon PID on original stdout
  -x          output files must be new (O_EXCL)

O traço duplo é opcional em sistemas que não usam a função GNU getopt (); é necessário (ou você deve especificar POSIXLY_CORRECT no ambiente) no Linux etc. Como o traço duplo funciona em qualquer lugar, é melhor usá-lo.

Você ainda pode entrar em contato comigo (ponto de nome sobrenome no gmail ponto com) se desejar a fonte daemonize.

No entanto, o código está agora (finalmente) disponível no GitHub no meu repositório SOQ (Stack Overflow Questions) como arquivo daemonize-1.10.tgzno subdiretório packages .


13
Por que você não coloca a fonte no github ou no bitbucket?
Rob

5
Por que a ausência da fonte do github justifica um voto negativo?
23611 Jonathan Leffler

7
@ JonathanLeffler IMHO listando todas as opções interessantes de um programa que não está disponível publicamente de nenhuma forma (nem mesmo comercialmente) para desperdiçar o tempo do leitor.
DepressedDaniel

7

Em um sistema baseado no Debian (na máquina remota) Instale:

sudo apt-get install tmux

Uso:

tmux

executar comandos que você deseja

Para renomear a sessão:

Ctrl + B e depois $

nome do conjunto

Para sair da sessão:

Ctrl + B e D

(isso sai da sessão do tmux). Em seguida, você pode sair do SSH.

Quando precisar voltar / verificar novamente, inicie o SSH e digite

tmux attach session_name

O levará de volta à sua sessão do tmux.


este é o caminho a percorrer
kilgoretrout

6

Para a maioria dos processos, você pode pseudo-daemonizar usando este antigo truque de linha de comando do Linux:

# ((mycommand &)&)

Por exemplo:

# ((sleep 30 &)&)
# exit

Em seguida, inicie uma nova janela do terminal e:

# ps aux | grep sleep

Mostrará que sleep 30ainda está em execução.

O que você fez foi iniciar o processo como filho de uma criança e, quando você sai, o nohupcomando que normalmente acionaria o processo para sair não cai em cascata no neto, deixando-o como um processo órfão, ainda em execução .

Eu prefiro este "defini-lo e esquecê-lo" abordagem, não há necessidade de lidar com nohup, screen, tmux, I / o redirecionamento, ou qualquer dessas coisas.


5

Se você usar a tela para executar um processo como root, tenha cuidado com a possibilidade de ataques de elevação de privilégio. Se sua conta for comprometida de alguma forma, haverá uma maneira direta de assumir o controle de todo o servidor.

Se esse processo precisar ser executado regularmente e você tiver acesso suficiente no servidor, uma opção melhor seria usar o cron para executar o trabalho. Você também pode usar o init.d (o super daemon) para iniciar seu processo em segundo plano, e ele pode terminar assim que terminar.


5

nohupé muito bom se você deseja registrar seus detalhes em um arquivo. Mas quando se trata de segundo plano, você não pode fornecer uma senha se seus scripts solicitarem. Eu acho que você deve tentar screen. é um utilitário que você pode instalar na sua distribuição linux usando yum, por exemplo, no CentOS yum install screene acessar seu servidor via massa ou outro software, no seu tipo de shellscreen . Ele abrirá a tela [0] em massa. Você trabalha. Você pode criar mais telas [1], telas [2] etc. na mesma sessão de massa.

Comandos básicos que você precisa conhecer:

Para iniciar a tela

tela


Para c próxima tela reate

ctrl + a + c


Para mover para n tela ext você criou

ctrl + a + n


To d etach

ctrl + a + d


Durante o trabalho, feche sua massa. E na próxima vez que você fizer login via tipo de massa

tela -r

Para reconectar-se à sua tela, e você pode ver seu processo ainda em execução na tela. E para sair da tela, digite #exit.

Para mais detalhes veja man screen.


Assumir que essa yumé a ferramenta certa, quando você não conhece a distribuição, não é bom. você deve deixar claro em quais distros screenpodem ser instaladas yum.
Tymik 26/05

5

O Nohup permite que um processo do cliente não seja morto se um processo pai for morto, para discussão quando você efetuar logout. Ainda melhor ainda:

nohup /bin/sh -c "echo \$\$ > $pidfile; exec $FOO_BIN $FOO_CONFIG  " > /dev/null

Nohup torna o processo que você inicia imune à finalização, que sua sessão SSH e seus processos filhos são eliminados após o logout. O comando que forneci fornece uma maneira de armazenar o pid do aplicativo em um arquivo pid, para que você possa matá-lo corretamente mais tarde e permitir que o processo seja executado após o logout.




2

eu também iria para o programa de tela (eu sei que a resposta some1 else foi tela, mas esta é uma conclusão)

não apenas o fato de que &, ctrl + z bg rejeita, nohup, etc. pode lhe dar uma surpresa desagradável de que, quando o trabalho de logoff ainda será morto (não sei por que, mas aconteceu comigo, e não incomodou com isso, porque eu mudei para usar a tela, mas acho que a solução anthonyrisinger, como a bifurcação dupla resolveria isso), também a tela tem uma grande vantagem sobre apenas o back-grounding:

screen will background your process without losing interactive control to it

e btw, esta é uma pergunta que eu nunca faria em primeiro lugar :) ... eu uso a tela desde o início para fazer qualquer coisa em qualquer unix ... eu (quase) NUNCA trabalho em um shell unix / linux sem a tela inicial primeiro ... e eu devo parar agora, ou vou começar uma apresentação interminável do que é uma boa tela e o que pode fazer por você ... procure por si mesmo, vale a pena;)


PS anthonyrisinger, você é bom, eu te dou isso, mas ... 30 anos? eu aposto que é uma solução quando o &, bg, nohup ou tela não estava lá ainda, e sem ofensa eu aprecio o seu conhecimento, mas que é muito complicado para usá-lo :)
THESorcerer

2
(à parte: veja Tmux ), embora isso tenha me antecedido amplamente [1987], &(execução assíncrona) foi introduzida pelo shell Thompson em 1971 , para a primeira versão do UNIX ... então literalmente "sempre foi" ;-) infelizmente, Eu era muito conservador - já faz 41 anos.
Anthonyrisinger #

2

Há também o daemon comando do pacote libslack de código aberto.

daemon é bastante configurável e se preocupa com todas as coisas tediosas do daemon, como reinicialização automática, log ou manipulação de arquivos de pid.


2

Anexe esta string ao seu comando:> & - 2> & - <& - &. > & - significa fechar stdout. 2> & - significa stderr próximo. <& - significa fechar stdin. & significa executar em segundo plano. Isso funciona para iniciar programaticamente um trabalho via ssh também:

$ ssh myhost 'sleep 30 >&- 2>&- <&- &'
# ssh returns right away, and your sleep job is running remotely
$


1

Resposta aceita sugerir o uso de nohup . Prefiro sugerir o uso do pm2 . O uso do pm2 sobre nohup tem muitas vantagens, como manter o aplicativo ativo, manter arquivos de log para aplicativos e muito mais outros recursos. Para mais detalhes verifique isso .

Para instalar o pm2, você precisa fazer o download do npm . Para sistema baseado em Debian

sudo apt-get install npm

e para Redhat

sudo yum install npm

Ou você pode seguir estas instruções . Após instalar o npm, use-o para instalar o pm2

npm install pm2@latest -g

Feito isso, você pode iniciar seu aplicativo

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

Para monitoramento de processo, use os seguintes 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

Gerencie processos usando o nome do aplicativo ou a identificação do processo ou gerencie todos os processos 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>

Arquivos de log podem ser encontrados em

$HOME/.pm2/logs #contain all applications logs

Arquivos executáveis ​​binários também podem ser executados usando o pm2. Você precisa fazer uma alteração no arquivo jason. Altere o "exec_interpreter" : "node", para "exec_interpreter" : "none".(consulte a seção de atributos ).

#include <stdio.h>
#include <unistd.h>  //No standard C library
int main(void)
{
    printf("Hello World\n");
    sleep (100);
    printf("Hello World\n");

    return 0;
}

Compilando código acima

gcc -o hello hello.c  

e execute-o com o np2 em segundo plano

pm2 start ./hello

Isso pode ser usado para executar executáveis ​​binários?
GetFree

@Liberta-te; Sim. Você pode.
haccks

Adicione um exemplo, por favor. A resposta como está agora parece ser boa apenas para arquivos de script.
GetFree

@Liberta-te; Adicionado o exemplo. Deixe-me saber se você tiver algum problema.
haccks

1

No systemd / Linux, systemd-run é uma boa ferramenta para iniciar processos independentes de sessão. Aborrecedores que vão odiar

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.