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?
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 ...
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.)
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.
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).
@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 ..
retty
,neercs
, etc, e ver também serverfault.com/questions/24425 , serverfault.com/questions/115998Respostas:
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
fonte
touch /tmp/thefile
. Stdout é 1, entãocall close (1)
; Também, use as permissões corretas para escrita:call open ("/tmp/thefile", 0400)
. Aecho…
é, naturalmente, não é necessário.call open("/tmp/fifo", 0600)
. qualquer ajuda seria muito apreciadaQuando o terminal original não estiver mais acessível ...
reptyr
pode ser o que você deseja, consulte https://serverfault.com/a/284795/187998Citação de lá:
fonte
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.Neste exemplo, você pode enviar informações para
9947
fazer algo parecidoecho "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.
fonte
dtach
se você não precisa de um todoscreen
.root
você pode até fazer isso com os processos de outros usuários.echo "test" > /dev/pts/1
não enviará entrada para o processo9947
- ele exibirá a palavra "test" no terminal desse processo.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:
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 -l
em / proc / pid / fd / .Consulte nohup para obter mais detalhes sobre como manter os processos em execução.
fonte
echo
algo no dispositivo do terminal imprimirá apenas o que você escreveu no terminal, ele não será transmitido ao processo.Acabar com a linha de comando
&
não desanexará completamente o processo, apenas executará em segundo plano. (Comzsh
você pode&!
desconectá-lo, caso contrário, você o farádisown
mais 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
fg
e, 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
retty
comando).fonte
>>/dev/stderr
, caso contrário, quando eu fechar o terminal, o processo "renegado" também terminará .. Eu nunca realmente entendi isso ..