Como faço para conectar um terminal a um processo desanexado?

99

Eu desanexei um processo do meu terminal, assim:

$ process &

Esse terminal está fechado há muito tempo, mas processainda está em execução, e quero enviar alguns comandos para o stdin desse processo. Isso é possível?

Rogach
fonte

Respostas:

112

Sim. Primeiro, crie um tubo: mkfifo /tmp/fifo. Use o gdb para anexar ao processo: gdb -p PID

Em seguida, feche stdin: call close (0); e abra-o novamente:call open ("/tmp/fifo", 0600)

Por fim, escreva (de um terminal diferente, pois o gdb provavelmente travará):

echo blah > /tmp/fifo

Ansgar Esztermann
fonte
6
Muito impressionante!
Samuel Edwin Ward
1
Posso fazer algo semelhante para redirecionar o processo stdout para um arquivo?
Rustyx
@rustyx: Não testado, mas isso deve funcionar: crie um arquivo em vez de um pipe touch /tmp/thefile. Stdout é 1, então call close (1); Também, use as permissões corretas para escrita: call open ("/tmp/thefile", 0400). A echo…é, naturalmente, não é necessário.
Ansgar Esztermann 26/08/14
Isso é ótimo! Estou usando isso para enviar respostas "y" ou "n" a determinados processos que foram completamente desanexados. O processo desanexado tem seu stdout em uma janela separada. No entanto, quando eu faço esse truque, vejo que ele não "recebe" o 'y' ou 'n' assim que o eco, preciso sair do gdb e desanexá-lo e, em seguida, ele recebe todos os ecos de acordo. existe uma maneira de fazer isso sem precisar sair do gdb antes que o processo receba a entrada do fifo?
krb686
infelizmente, parece que está pendurado call open("/tmp/fifo", 0600). qualquer ajuda seria muito apreciada
arqueiro
27

Quando o terminal original não estiver mais acessível ...

reptyrpode ser o que você deseja, consulte https://serverfault.com/a/284795/187998

Citação de lá:

Dê uma olhada no reptyr , que faz exatamente isso. A página do github tem todas as informações.

reptyr - Uma ferramenta para "re-escrever" programas.

reptyr é um utilitário para pegar um programa em execução existente e anexá-lo a um novo terminal. Iniciou um processo de execução demorada pelo ssh, mas precisa sair e não quer interrompê-lo? Basta iniciar uma tela, use reptyr para pegá-la e, em seguida, mate a sessão ssh e vá para casa.

USO

reptyr PID

"reptyr PID" pega o processo com o ID PID e o anexa ao seu terminal atual.

Após a conexão, o processo recebe e grava a saída no novo terminal, incluindo ^ C e ^ Z. (Infelizmente, se você tiver experiência em segundo plano, ainda precisará executar "bg" ou "fg" no terminal antigo. É provável que seja impossível corrigir isso de uma maneira razoável sem corrigir o shell.)

NiKiZe
fonte
12

Tenho certeza que você não pode.

Verifique usando ps x. Se um processo tem um controle? como tty , você não pode mais enviar entrada para ele.

9942 ?        S      0:00 tail -F /var/log/messages
9947 pts/1    S      0:00 tail -F /var/log/messages

Neste exemplo, você pode enviar informações para 9947fazer algo parecido echo "test" > /dev/pts/1. O outro processo ( 9942) não está acessível.

Da próxima vez, você pode usar o screen ou tmux para evitar essa situação.

andcoz
fonte
5
Ou dtachse você não precisa de um todo screen.
manatwork
4
Não há nenhuma maneira nos padrões (POSIX, SUS), mas em muitos sistemas (a maioria?) É possível usando os mecanismos que os depuradores usam. Veja a resposta de Ansgar . Com rootvocê pode até fazer isso com os processos de outros usuários.
dmckee
3
Doing echo "test" > /dev/pts/1não enviará entrada para o processo 9947- ele exibirá a palavra "test" no terminal desse processo.
Psmears
6

EDIT : Como Stephane Gimenez disse, não é tão simples. Só permite imprimir em um terminal diferente.

Você pode tentar gravar nesse processo usando / proc . Ele deve estar localizado em / proc / pid / fd / 0 , portanto, é simples:

echo "hello" > /proc/PID/fd/0

deve fazê-lo. Eu não tentei, mas deve funcionar, desde que esse processo ainda tenha um descritor de arquivo stdin válido . Você pode verificá-lo ls -lem / proc / pid / fd / .

  • se for um link para / dev / null => está fechado
  • se é um link para / dev / pts / X ou um soquete => está aberto

Consulte nohup para obter mais detalhes sobre como manter os processos em execução.

Coren
fonte
2
Não é tão simples assim. Por exemplo, se o stdin estiver vinculado a um terminal, echoalgo no dispositivo do terminal imprimirá apenas o que você escreveu no terminal, ele não será transmitido ao processo.
Stéphane Gimenez
5

Acabar com a linha de comando &não desanexará completamente o processo, apenas executará em segundo plano. (Com zshvocê pode &!desconectá-lo, caso contrário, você o fará disownmais tarde).

Quando um processo é executado em segundo plano, ele não recebe mais entradas de seu terminal de controle. Mas você pode enviá-lo de volta ao primeiro plano com fge, em seguida, ele lerá a entrada novamente.

Caso contrário, não é possível alterar externamente seus descritores de arquivos (incluindo stdin) ou reconectar um terminal de controle perdido ... a menos que você use ferramentas de depuração (consulte a resposta de Ansgar ou dê uma olhada no rettycomando).

Stéphane Gimenez
fonte
E há uma pergunta relacionada aqui: unix.stackexchange.com/q/17648/9426
Stéphane Gimenez
@Rogach declarou "Esse terminal está fechado há muito tempo".
andcoz
1
@andcoz: Sim, mas ele teve sorte de o programa não ter sido SIGHUPed. Eu estava sugerindo um método mais seguro.
Stéphane Gimenez
aqui, o renegado só funciona realmente se eu redirecionar o stdout pela primeira vez com >>/dev/stderr, caso contrário, quando eu fechar o terminal, o processo "renegado" também terminará .. Eu nunca realmente entendi isso ..
Aquarius Power