Como visualizar a saída de um processo em execução em outra sessão bash?

161

Deixei um script em execução em uma máquina remota de quando estava trabalhando localmente nele. Eu posso conectar via SSH à máquina como o mesmo usuário e ver o script sendo executado em ps .

$ ps aux | grep ipcheck
myuser  18386  0.0  0.0  18460  3476 pts/0    S+   Dec14   1:11 /bin/bash ./ipchecker.sh

É simplesmente saída para stdout em uma sessão local (eu corri ./ipchecker.sh de uma janela de terminal local, sem redirecionamento, sem uso de screen etc).

Existe alguma maneira de uma sessão SSH? Posso ver a saída deste comando em execução (sem pará-lo)?

Até agora, o melhor que encontrei é usar strace -p 18386 , mas recebo hordas de texto voando pela tela, muito detalhadas. Eu posso parar strace e, em seguida, peneirar a saída e encontrar o texto trazido para impressão stdout, mas é muito longo e confuso, e, obviamente, enquanto estiver parado, eu poderia perder alguma coisa. Eu gostaria de encontrar uma maneira de ver a saída do script ao vivo como se eu estivesse trabalhando localmente.

Alguém pode melhorar isso? A resposta óbvia é reiniciar o script com redirecionamento ou em uma sessão screen etc, esse não é um script de missão crítica para que eu possa fazer isso. Em vez disso, vejo isso como um exercício de aprendizado divertido.

    
por jwbensley 15.12.2012 / 15:04

8 respostas

153

Se tudo o que você quer fazer é espionar o processo existente, você pode usar strace -p1234 -s9999 -e write , em que 1234 é o ID do processo. ( -s9999 evita ter strings truncadas em 32 caracteres e write a chamada do sistema que produz saída.) Se quiser visualizar apenas os dados gravados em um descritor de arquivo específico, você pode usar algo como strace -p1234 -e trace= -e write=3 para ver apenas dados escrito no descritor de arquivo 3 ( -e trace= impede que as chamadas do sistema sejam registradas). Isso não lhe dará saída que já tenha sido produzida.

Se a saída estiver rolando muito rápido, você poderá enviá-la para um pager como less ou enviá-la para um arquivo com strace -o trace.log … .

Com muitos programas, você pode desviar a saída subsequente com um hack ptrace, para o seu terminal atual ou para uma nova sessão de tela. Veja Como posso deserdar um processo em execução e associá-lo a um novo shell de tela? e outros encadeamentos vinculados.

    
por 16.12.2012 / 01:23
103

Você pode acessar a saída através do sistema de arquivos proc .

tail -f /proc/<pid>/fd/1

1 = stdout, 2 = stderr

    
por 08.09.2016 / 16:19
6

No BSD, você pode usar watch que espia um dado tty, por exemplo

watch /dev/pts/0

No Linux, não será possível se o processo não foi executado sob o multiplexador antes de screen ou tmux . Veja também: Reptyr: Anexar um processo em execução a um Novo Terminal

Parece que a única maneira é depurar o processo (por exemplo, strace , dtrace / dtruss , gdb , lldb , etc.).

Como você usou strace para buscar qualquer saída significativa, é necessário filtrar por uma expressão de qualificação (como file ) e, em seguida, analisar a saída. Aqui está o exemplo:

strace -e trace=write -s1000 -fp 18386 2>&1 | grep -o '".\+[^"]"'

O que ele faz imprime a operação de gravação do processo (comprimento 1000) especificado pelo PID (usa pgrep para localizá-lo pelo nome), redireciona o erro padrão para a saída (a ser filtrada) e imprime uma cadeia de aspas duplas.

Se você estiver lidando com saída binária, poderá analisar caracteres de seqüências de escape usando read (com -r ) e printf (com %b ), por exemplo,

while read -r -t1 line; do printf "%b" $line; done

Verifique help read para mais parâmetros (por exemplo, -n para imprimir após uma determinada quantidade de caracteres, em vez de uma nova linha).

Aqui está um exemplo mais completo:

strace -e trace=write -s1000 -fp 18386 2>&1 \
| grep --line-buffered -o '".\+[^"]"' \
| grep --line-buffered -o '[^"]\+[^"]' \
| while read -r line; do
  printf "%b" $line;
done

Para exemplos usando qualquer processo, verifique: Como analisar strace no shell em texto simples? em stackoverflow

    
por 11.04.2016 / 23:53
4
  1. Você pode espiar a tela remota usando ssh localhost 'DISPLAY=:0.0 xwd -root' | xwud -scale , em que localhost deve ser substituído por suas credenciais de login do servidor remoto e :0.0 com o número de exibição de sua GUI.

  2. Use x11vnc , que é um servidor VNC para sua sessão X na tela.

  3. Ao executar em um dos seis consoles virtuais, tente sudo setterm -dump 2 -file /dev/stdout , onde você substitui 2 pelo vc apropriado.

por 15.12.2012 / 16:27
4

Eu aconselharia criar um pipe nomeado ( mkfifo ) e, em seguida, gravar nesse arquivo. Então, leia a partir dele. Você sempre pode fazer isso com coisas como tail , para minimizar a saída, etc. Sempre que você limpa o pipe (leia a partir dele), ele é limpo, então a saída não é preservada.

A outra opção seria escrever tudo em um arquivo (muito parecido com um arquivo de log) e analisá-lo a qualquer momento. Essa seria a ação preferida, se você quiser preservar toda a saída.

    
por 15.12.2012 / 15:11
1

Você sempre pode iniciar um processo com nohup e &

nohup rsync source_file dest_file &

Depois, você poderá verificar o progresso de qualquer tty com:

tail -f nohup.out

Isso funciona bem para mim.

    
por 23.11.2016 / 17:47
1

Um muito simples para obter a saída seria capturar sua saída em um arquivo e seguir esse arquivo.

SE DO: ./ipcheck

INSTEAD DO: ./ipcheck > [substitua o seu nome de arquivo]

Isso criaria um arquivo de saída onde seu script está localizado. Então, a partir de qualquer outro shell bash você pode simplesmente seguir o arquivo:

tail [substitua o nome do seu arquivo] -f

    
por 26.04.2017 / 20:08
0

você não pode obter o ID do processo e se comunicar com ele com USR1,

$pgrep -l '^ipchecker.sh$'

que imprime o PID do seu script e o usa para

$ kill -USR1 PID

Eu entendo que USR1 é um sinal "definido pelo usuário", o que significa que quem criou o programa pode usá-lo para "encerrar" ou "descarregar seus logs" ou "imprimir milhares de vezes" ou qualquer outra coisa.

    
por 16.12.2012 / 12:35