Como posso negar um processo em execução e associá-lo a um novo shell de tela?


159

Eu tenho um programa em execução em um shell SSH. Quero pausá-lo e poder interromper sua execução quando voltar.

Uma maneira que pensei em fazer isso foi transferir sua propriedade para um shell de tela, mantendo-o funcionando lá.

Existe uma maneira diferente de proceder?


8
Consulte também Posso nohup / tela de um processo já iniciado? e o comando Resume em execução na sessão SSH descartada , que menciona várias soluções baseadas em ptrace (atualmente) não mencionadas aqui.
Gilles

Em perguntas como unix.stackexchange.com/a/4039/13496 , estou ouvindo sobre retty e neercs . Hmmm ... pergunto-me se há algo como uma camada " tela aqui" antes de executar um processo na próxima vez que eu perder o terminal superior no futuro, o que facilitará o retorno do stdin / out / err
Marcos

O problema secundário / implícito nesta pergunta que não consigo entender é ... por que o shell optou por rejeitar um trabalho suspenso quando há um mais recente / acaba de lançar um em segundo plano que nem precisa / espera pelo stdin? Este é o tratamento com o qual me acostumei, então não sei o que foi diferente aqui ...
Marcos

Respostas:


86

Usar o GNU screené sua melhor aposta.

Iniciar a tela em execução quando você entra pela primeira vez - eu corro screen -D -R, execute seu comando e desconecte ou suspenda-o CTRL-Ze desconecte-o da tela pressionando CTRL-Aentão D.

Quando você fizer login novamente na máquina, reconecte executando screen -D -R. Você estará no mesmo shell de antes. Você pode executar jobspara ver o processo suspenso, se o fez, e executar %1(ou o respectivo número da tarefa) para o primeiro plano novamente.


2
Uau, não acredito que uma resposta do GNU Screen seja atualmente a mais baixa. Estou esquecendo de algo?
Faheem Mitha 21/03

1
Possivelmente! Parece o melhor para mim.
Andrew Yochum 21/03

1
Olhando para trás, parece claramente a solução mais simples, desde que você possa planejar adequadamente e iniciar seus processos a partir de um ambiente de tela. Enfim, eu fiz a resposta oficial!
Leveque

28
Eu acho que isso não responde à pergunta. A pergunta começa com " Eu tenho um programa em execução ". Esta resposta assume que não está funcionando ainda ...
Anko

sim, ele escreveu claramente que deseja colocá-lo em uma sessão de tela :-)
Florian Heigl

112

Você pode revogar a "propriedade" do programa a partir do shell com o disownbuilt-in:

# press Ctrl+Z to suspend the program
bg
disown

No entanto, isso diz apenas ao shell para não enviar um SIGHUPsinal ao programa quando o shell sair. O programa reterá qualquer conexão que tenha com o terminal, geralmente como fluxos de entrada, saída e erro padrão. Não há como reconectá-las a outro terminal. (A tela funciona emulando um terminal para cada janela, para que os programas sejam anexados à janela da tela.)


É possível reconectar os descritores de arquivo a um arquivo diferente, anexando o programa em um depurador (por exemplo, usando ptrace) e fazendo-o chamar open, dupe close. Existem algumas ferramentas que fazem isso; esse é um processo complicado e, às vezes, eles interrompem o processo. As possibilidades incluem (links coletados das respostas para Como posso negar um processo em execução e associá-lo a um novo shell de tela? E Posso nohup / rastrear um processo já iniciado? ):


disownremove o processo da lista de controle de tarefas.
ctrl-alt-Delor


@CeesTimmerman Isso deixa o trabalho na tabela de trabalhos do shell, mas qual é a vantagem disso?
Gilles

@ Gilles: para que você possa parar fgou killver, e veja se termina por conta própria.
Peter Cordes

O que os utilitários mencionados funcionam com um grupo de processos (por exemplo bzcat a.bz2 | grep text)? Man for reptyrdiz que ele não suporta mover os processos com crianças.
dma_k

64

Para mover um processo entre terminais ou reconectar um renegado, você pode usar, por exemplo, reptyr .


1
Sim, isso salvou, obrigado! Eu li o site do autor como ele funciona melhor do que ferramentas semelhantes ou mais antigas, por exemplo. para programas ncurses.
Marcos

4
Isso é incrível; deve resolver a situação de uma amiga de perder constantemente seu trabalho, executando-o diretamente no ssh e, em seguida, precisando pegar um trem. "Opa, esqueci de usar a tela. Novamente."
Adam Katz

3
+1 Embora a screenresposta aceita seja obviamente ideal, na verdade ela não responde à pergunta, que solicita especificamente uma maneira de mover um processo em execução no momento screen. Veja também esta resposta: serverfault.com/a/284795
toxefa

1
Proteção ao vivo absoluta. Permitiu que eu me reconectasse à execução do apt dist-upgrade que estava aguardando a confirmação do usuário.
andig

28

Minha solução favorita é usar tmux, você pode desanexar a sessão e reconectá-la em outro terminal.

Quando você se desconectou da sessão anterior, pode fechar o terminal com segurança; use mais tarde tmux attachpara voltar à sessão, mesmo se você tiver desconectado.


1
você também pode compartilhar sua sessão com seu amigo e usar várias janelas e painéis e muito mais! ^ _ ^
igor

exemplo de uso por favor?
Vitaly Zdanevich

21

Há também um pequeno utilitário chamado retty que permite anexar programas em execução a outro terminal.


19

Eu não o uso regularmente, mas a neercs afirma apoiar isso. É um screenprograma parecido com diversos recursos sofisticados, como melhor gerenciamento de painéis, mas o principal que ele oferece é a capacidade de importar um processo para um painel


2
Interessante. Ele toca sujo ( ptrace), mas não apenas manipula os descritores de arquivo, mas bifurca o processo. É capaz de agarrar find /, mas travou uma festa interativa.
Gilles

@Gilles não me lembro como foi quando eu tentei, mas não tem uma grande reputação, me disseram que não bastante regularidade
Michael Mrozek

9

Se você quiser apenas fazer uma pausa e reiniciar depois, pode usar killcom STOPou CONTsinalizar.

Em primeiro lugar, descubra os processos PID com

$ ps aux

Em seguida, envie os sinais para o PID listado no processo

$ kill -STOP <PID>

$ kill -CONT <PID>

9

"injcode" do ThomasHabets parece ser exatamente o que eu preciso:

https://github.com/ThomasHabets/injcode

O programa injcode permite que um código arbitrário seja injetado em um processo em execução, você sabia ou não de antemão e estava executando o screen ou tmux

No README:

Exemplo 1: mova o irssi de um terminal para outro

Talvez mova para uma tela.

Primeiro inicie o irssi em um terminal.

Execute o injcode em outro terminal: $ injcode -m retty

O Irssi agora deve ser movido para o segundo terminal, incluindo um novo terminal de controle.


1

Isso funcionou para mim:

  1. bg o processo
  2. jobs -l encontre o número do processo
  3. tmux iniciar gerenciador de janelas shell
  4. reptyr -L PROCESSNUMBER

reptyr's -Lfoi necessário chegar a este trabalho:

-L Like '-l', but also redirect the child's stdio to the slave.

devido a este erro:

$ reptyr 30622

[-] Unable to open the tty in the child.
Unable to attach to pid 30622: Permission denied

E com -L

$ reptyr -L 30622
Opened a new pty: /dev/pts/4
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.