Respostas:
Usando o Job Control do bash para enviar o processo para o segundo plano:
bg
para executá-lo em segundo plano.disown -h [job-spec]
onde [job-spec] é o número do trabalho (como %1
no primeiro trabalho em execução; encontre o seu número com o jobs
comando) para que o trabalho não seja eliminado quando o terminal for fechado.disown -h
talvez seja a resposta mais exata: "fazer com que o renomado se comporte mais como nohup (ou seja, os trabalhos permanecerão na árvore de processos do shell atual até você sair do shell)" Isso permite que você veja todos os trabalhos que esse shell iniciou ". (de [ quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/… )
disown
, disown torna um processo um daemon, o que significa que a entrada / saída padrão é redirecionada para / dev / null. Então, se você pretende renegar um trabalho, é melhor começar com login em um arquivo, por exemplomy_job_command | tee my_job.log
disown
desassocia quaisquer tubos do processo. Para recolocar os tubos, use gdb
como descrito neste tópico . Mais especificamente, este post .
Suponha que, por algum motivo, o Ctrl+ Ztambém não esteja funcionando, vá para outro terminal, encontre o ID do processo (usando ps
) e execute:
kill -SIGSTOP PID
kill -SIGCONT PID
SIGSTOP
suspenderá o processo e SIGCONT
retomará o processo em segundo plano. Portanto, agora, fechar os dois terminais não interromperá o processo.
disown %1
o primeiro terminal antes de fechá-lo.
kwin
após uma falha sem pensar nas consequências). Então, se eu parasse o kwin, tudo teria congelado e eu não tinha possibilidade de correr bg
!
O comando para separar um trabalho em execução do shell (= torna nohup) é disown
e um comando shell básico.
De bash-manpage (man bash):
renegar [-ar] [-h] [jobspec ...]
Sem opções, cada especificação de trabalho é removida da tabela de tarefas ativas. Se a opção -h for fornecida, cada jobpec não será removido da tabela, mas será marcado para que SIGHUP não seja enviado para o job se o shell receber um SIGHUP. Se nenhuma especificação de trabalho estiver presente e nem a opção -a nem a -r forem fornecidas, a tarefa atual será usada. Se nenhuma especificação de trabalho for fornecida, a opção -a significa remover ou marcar todas as tarefas; a opção -r sem um argumento jobspec restringe a operação à execução de jobs. O valor de retorno é 0, a menos que um jobpec não especifique um trabalho válido.
Isso significa que um simples
disown -a
removerá todos os trabalhos da tabela de trabalhos e os tornará nohup
disown -a
remove todos os trabalhos. Um simples disown
remove apenas o trabalho atual. Como a página de manual na resposta diz.
Estas são boas respostas acima, eu só queria adicionar um esclarecimento:
Você não pode dar disown
um pid ou processo, disown
um emprego, e essa é uma distinção importante.
Um trabalho é algo que é uma noção de um processo anexado a um shell; portanto, você deve lançar o trabalho em segundo plano (não suspendê-lo) e depois rejeitá-lo.
Questão:
% jobs
[1] running java
[2] suspended vi
% disown %1
Veja http://www.quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/jobcontrol/ para uma discussão mais detalhada sobre o Unix Job Control.
Infelizmente, disown
é específico do bash e não está disponível em todas as conchas.
Certos tipos de Unix (por exemplo, AIX e Solaris) têm uma opção no nohup
próprio comando que pode ser aplicada a um processo em execução:
nohup -p pid
AIX
e Solaris
. "As versões AIX e Solaris do nohup têm uma opção -p que modifica um processo em execução para ignorar futuros sinais SIGHUP. Diferentemente do built-in desown acima descrito, o nohup -p aceita IDs de processo.". Fonte
A resposta do nó é realmente ótima, mas deixou em aberto a questão de como o stdout e o stderr podem ser redirecionados. Encontrei uma solução em Unix e Linux , mas também não está completa. Gostaria de mesclar essas duas soluções. Aqui está:
Para o meu teste, criei um pequeno script bash chamado loop.sh, que imprime o pid de si mesmo com um minuto de sono em um loop infinito.
$./loop.sh
Agora obtenha o PID desse processo de alguma forma. Geralmente ps -C loop.sh
é bom o suficiente, mas é impresso no meu caso.
Agora podemos mudar para outro terminal (ou pressionar ^ Z e no mesmo terminal). Agora gdb
deve ser anexado a esse processo.
$ gdb -p <PID>
Isso interrompe o script (se estiver em execução). Seu estado pode ser verificado por ps -f <PID>
, onde o STAT
campo é 'T +' (ou no caso de ^ Z 'T'), o que significa (man ps (1))
T Stopped, either by a job control signal or because it is being traced
+ is in the foreground process group
(gdb) call close(1)
$1 = 0
Fechar (1) retorna zero em caso de sucesso.
(gdb) call open("loop.out", 01102, 0600)
$6 = 1
Aberto (1) retorna o novo descritor de arquivo, se for bem-sucedido.
Esta abertura é igual a open(path, O_TRUNC|O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)
. Em vez de O_RDWR
O_WRONLY
poderia ser aplicado, mas /usr/sbin/lsof
diz 'u' para todos os manipuladores de arquivos std * ( FD
coluna), o que é O_RDWR
.
Eu verifiquei os valores no arquivo de cabeçalho /usr/include/bits/fcntl.h.
O arquivo de saída pode ser aberto com O_APPEND
, como nohup
faria, mas isso não é sugerido por man open(2)
causa de possíveis problemas no NFS.
Se obtivermos -1 como valor de retorno, call perror("")
imprima a mensagem de erro. Se precisarmos do errno, use o p errno
comando gdb.
Agora podemos verificar o arquivo recém-redirecionado. /usr/sbin/lsof -p <PID>
impressões:
loop.sh <PID> truey 1u REG 0,26 0 15008411 /home/truey/loop.out
Se quisermos, podemos redirecionar o stderr para outro arquivo, se quisermos usar call close(2)
e call open(...)
novamente usando um nome de arquivo diferente.
Agora o anexo bash
precisa ser liberado e podemos sair gdb
:
(gdb) detach
Detaching from program: /bin/bash, process <PID>
(gdb) q
Se o script foi parado por gdb
outro terminal, ele continua sendo executado. Podemos voltar ao terminal loop.sh. Agora, ele não grava nada na tela, mas executa e grava no arquivo. Temos que colocá-lo em segundo plano. Então pressione ^Z
.
^Z
[1]+ Stopped ./loop.sh
(Agora estamos no mesmo estado em que ^Z
foi pressionado no início.)
Agora podemos verificar o estado do trabalho:
$ ps -f 24522
UID PID PPID C STIME TTY STAT TIME CMD
<UID> <PID><PPID> 0 11:16 pts/36 S 0:00 /bin/bash ./loop.sh
$ jobs
[1]+ Stopped ./loop.sh
Portanto, o processo deve estar em execução em segundo plano e desconectado do terminal. O número na jobs
saída do comando entre colchetes identifica o trabalho dentro bash
. Podemos usar os seguintes bash
comandos internos, aplicando um sinal '%' antes do número do trabalho:
$ bg %1
[1]+ ./loop.sh &
$ disown -h %1
$ ps -f <PID>
UID PID PPID C STIME TTY STAT TIME CMD
<UID> <PID><PPID> 0 11:16 pts/36 S 0:00 /bin/bash ./loop.sh
E agora podemos sair da festança de chamadas. O processo continua em execução em segundo plano. Se sairmos do seu PPID, tornar-se 1 (processo init (1)) e o terminal de controle se tornar desconhecido.
$ ps -f <PID>
UID PID PPID C STIME TTY STAT TIME CMD
<UID> <PID> 1 0 11:16 ? S 0:00 /bin/bash ./loop.sh
$ /usr/bin/lsof -p <PID>
...
loop.sh <PID> truey 0u CHR 136,36 38 /dev/pts/36 (deleted)
loop.sh <PID> truey 1u REG 0,26 1127 15008411 /home/truey/loop.out
loop.sh <PID> truey 2u CHR 136,36 38 /dev/pts/36 (deleted)
COMENTE
O material gdb pode ser automatizado, criando um arquivo (por exemplo, loop.gdb) contendo os comandos e executado gdb -q -x loop.gdb -p <PID>
. Meu loop.gdb fica assim:
call close(1)
call open("loop.out", 01102, 0600)
# call close(2)
# call open("loop.err", 01102, 0600)
detach
quit
Ou pode-se usar o seguinte liner:
gdb -q -ex 'call close(1)' -ex 'call open("loop.out", 01102, 0600)' -ex detach -ex quit -p <PID>
Espero que esta seja uma descrição bastante completa da solução.
lsof
(o nome do identificador de arquivo pipe
não é igual a /dev/pts/1
) ou por ls -l /proc/<PID>/fd/<fd>
(isso mostra o link simbólico do identificador). Além disso, os subprocessos ainda não podem ter saídas redirecionadas, que devem ser redirecionadas para um arquivo.
Para enviar o processo em execução para o nohup ( http://en.wikipedia.org/wiki/Nohup )
nohup -p pid
, não funcionou para mim
Então eu tentei os seguintes comandos e funcionou muito bem
Execute alguns SOMECOMMAND, digamos /usr/bin/python /vol/scripts/python_scripts/retention_all_properties.py 1
.
Ctrl+ Zpara parar (pausar) o programa e voltar ao shell.
bg
para executá-lo em segundo plano.
disown -h
para que o processo não seja interrompido quando o terminal fechar.
Digite exit
para sair do shell, porque agora você pode prosseguir, pois a operação será executada em segundo plano em seu próprio processo, para que não esteja vinculada a um shell.
Esse processo é equivalente à execução nohup SOMECOMMAND
.
bg
- isso colocará o trabalho em segundo plano e retornará ao processo em execuçãodisown -a
- isso cortará todo o anexo com o trabalho (para que você possa fechar o terminal e ele ainda funcione)Essas etapas simples permitirão fechar o terminal enquanto mantém o processo em execução.
Ele não será colocado nohup
(com base no meu entendimento da sua pergunta, você não precisa dela aqui).
Isso funcionou para mim no Ubuntu linux enquanto estava no tcshell.
CtrlZ pausar
bg
executar em segundo plano
jobs
para obter o número do trabalho
nohup %n
onde n é o número do trabalho
nohup: failed to run command '%1': No such file or directory
yourExecutable &
e as saídas continuem aparecendo na tela eCtrl+C
não pare nada, basta digitar cegamentedisown;
e pressionarEnter
mesmo que a tela esteja rolando com saídas e você não possa ver o que você está digitando. O processo será contestado e você poderá fechar o terminal sem que o processo acabe.