Come visualizzare l'output di un processo in esecuzione in un'altra sessione bash?


199

Ho lasciato uno script in esecuzione su una macchina remota da quando ci lavoravo localmente. Posso connettermi tramite SSH alla macchina come lo stesso utente e vedere lo script in esecuzione ps.

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

Sta semplicemente eseguendo lo stdout in una sessione locale (ho corso da ./ipchecker.shuna finestra del terminale locale, nessun reindirizzamento, nessun uso di screenecc.).

C'è comunque da una sessione SSH che posso visualizzare l'output di questo comando in esecuzione (senza fermarlo)?

Finora il migliore che ho trovato è usare strace -p 18386ma ho orde di testo che volano sullo schermo, è troppo dettagliato. Posso fermarmi stracee quindi scorrere l'output e scoprire che il testo viene stampato su stdout ma è molto lungo e confuso, e ovviamente mentre è fermo potrei perdere qualcosa. Vorrei trovare un modo per vedere l'output dello script dal vivo come se stessi lavorando localmente.

Qualcuno può migliorare su questo? La risposta ovvia è riavviare lo script con il reindirizzamento o in una screensessione ecc., Questo non è uno script mission-critical, quindi potrei farlo. Piuttosto, lo vedo come un divertente esercizio di apprendimento.


Il processo è in esecuzione in una console virtuale o in un ambiente simile a GUI / xterm?
jippie,

4
È possibile limitare l'output di strace a un syscall:strace -p 4232 -e write
otokan,

@jippie La macchina esegue una GUI completa (Linux Mynt 13, desktop XFCE), ho avviato un terminale gnome.
jwbensley,

3
Ci sono almeno una dozzina di domande simili su questo sito. Cerca reptyr qui per trovarne alcuni (e una risposta).
Stéphane Chazelas,

Risposte:


180

Se tutto ciò che vuoi fare è spiare il processo esistente, puoi usare strace -p1234 -s9999 -e writedove 1234 è l'ID del processo. ( -s9999evita che le stringhe vengano troncate a 32 caratteri e writela chiamata di sistema che produce output.) Se si desidera visualizzare solo i dati scritti su un determinato descrittore di file, è possibile utilizzare qualcosa di simile strace -p1234 -e trace= -e write=3a vedere solo i dati scritti sul descrittore di file 3 ( -e trace=impedisce al sistema chiamate dalla registrazione). Ciò non ti darà un output già prodotto.

Se l'output scorre troppo velocemente, è possibile reindirizzarlo a un cercapersone come lesso inviarlo a un file con strace -o trace.log ….

Con molti programmi, è possibile deviare l'output successivo con un hack ptrace, sul terminale corrente o su una nuova sessione dello schermo. Vedi Come posso rinnegare un processo in esecuzione e associarlo a una nuova shell dello schermo? e altri thread collegati.

Si noti che, a seconda della configurazione del sistema, potrebbe essere necessario eseguire tutti questi stracecomandi come root anche se il processo è in esecuzione sotto l'utente senza privilegi aggiuntivi. (Se il processo è in esecuzione come un altro utente o è setuid o setgid, sarà necessario eseguirlo stracecome root.) La maggior parte delle distribuzioni consente solo a un processo di rintracciare i propri figli (ciò fornisce un moderato vantaggio per la sicurezza - impedisce l'iniezione diretta di malware, ma non impedisce l'iniezione indiretta modificando i file). Questo è controllato dal kernel.yama.ptrace_scomesysctl.


18
Suppongo che non ci sia un modo per restringere l'output solo all'output standard ?
Giona

3
Puoi spiegare tutti gli argomenti?
Utente

6
C'erano molte barre rovesciate e numeri in gran parte dell'output che stavo ottenendo da nodejs; Qualche indizio su quale codifica potrebbero essere? C'era anche un sacco di testo in chiaro, che era tutto ciò di cui avevo bisogno.
ThorSummoner,

3
"Puoi spiegare tutti gli argomenti?" @Utente:man strace
Pistos

3
@RafaelMoni Un programma per fare ciò che stai chiedendo si chiama debugger.
Gilles,

139

È possibile accedere all'output tramite il procfilesystem.

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

1= stdout, 2= stderr


7
Mi dà: 'impossibile aprire / proc / <my pid> / fd / 1 per la lettura: nessun dispositivo o indirizzo del genere'.
Yaroslav Nikitenko,

18
yeah <my pid> dovrebbe essere il tuo id di processo
tvlooy

29
Questo non funzionerà se l'output sta per essere tty (o reindirizzato a /dev/null) - funzionerà solo se l'output viene reindirizzato a un file.
Mattdm,

1
Testato su Ubuntu 16.04 e non funziona. In una sessione lo faccio: ping google.ese in un altro come root: tail -f /proc/`pgrep ping`/fd/2e non viene mostrato nulla.
david.perez,

1
hai ragione. Perché fd 1 e 2 sono collegamenti simbolici al dispositivo / dev / pts. Non puoi tail -fa pts device. Pianifica il tuo comando ping come cronjob e poi fai lo stesso. tail -f funzionerà quindi
tvlooy il

9

In BSD, puoi usare watchquali snoop una determinata tty, ad es

watch /dev/pts/0

In Linux, non sarà possibile se il processo non è stato eseguito in multiplexer prima come screeno tmux. Vedi anche: Reptyr : collega un processo in esecuzione a un nuovo terminale

Sembra che l'unico modo è quello di eseguire il debug del processo (ad esempio strace, dtrace/ dtruss, gdb, lldb, etc.).

Poiché hai utilizzato strace, per recuperare qualsiasi output significativo, devi filtrare in base a un'espressione qualificante (come file), quindi analizzare l'output. Ecco un esempio:

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

Cosa fa stampa l'operazione di scrittura del processo (lunghezza 1000) specificato da PID (usare pgrepper trovarlo per nome), reindirizza l'errore standard nell'output (da filtrare) e stampa una stringa tra virgolette doppie.

Se hai a che fare con l'output binario, puoi analizzare i caratteri delle sequenze di escape usando read(con -r) e printf (con %b), ad es

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

Verificare la presenza help readdi più parametri (ad es. -nPer stampare dopo un determinato numero di caratteri, anziché la nuova riga).

Ecco un esempio più 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

Per esempi che utilizzano qualsiasi processo, si prega di controllare: Come analizzare la stringa nella shell in testo semplice? su stackoverflow


4
  1. Potresti essere in grado di sbirciare lo schermo remoto usando ssh localhost 'DISPLAY=:0.0 xwd -root' | xwud -scaledove localhostdeve essere sostituito dalle credenziali di accesso del tuo server remoto e :0.0con il numero di visualizzazione della tua GUI.

  2. Usa x11vnc, che è un server VNC per la tua sessione X sullo schermo.

  3. Quando si esegue su una delle 6 console virtuali sudo setterm -dump 2 -file /dev/stdout, provare , dove si sostituisce 2con il vc appropriato.


4

Consiglio di creare una pipe denominata ( mkfifo) e quindi scrivere su quel file. Quindi, leggi da esso. Puoi sempre farlo con cose come tail, per ridurre al minimo l'output, ecc. Ogni volta che svuoti la pipe (leggi da essa), viene cancellata, quindi l'output non viene conservato.

L'altra opzione sarebbe quella di scrivere tutto su un file (molto simile a un file di registro) e quindi analizzarlo in qualsiasi momento. Questa sarebbe l'azione preferita, se si desidera preservare tutto l'output.


3

Puoi sempre avviare un processo senza nohup e &

nohup rsync source_file dest_file &

Quindi, puoi controllare i progressi da qualsiasi tty con:

tail -f nohup.out

Questo funziona bene per me.


6
Questa domanda vorrei sapere come visualizzare l'output di un processo in esecuzione di un avviso, non come eseguire un processo in background come suggerisce la risposta
jwbensley,

In effetti, il tuo: nohup menzione mi illumini! Grazie!
Nam G VU,

1

Un modo molto semplice per ottenere l'output sarebbe catturare l'output in un file e adattarlo a quel file.

SE FARE: ./ipcheck

INSTEAD DO: ./ipcheck> [sostituisci il tuo nome file]

Ciò creerebbe un file di output in cui si trova lo script. Quindi da qualsiasi altra shell bash puoi semplicemente mettere in coda il file:

tail [sostituisci il tuo nome file] -f


Il reindirizzamento dei file tende a utilizzare il buffering basato su blocchi per impostazione predefinita (vedi setbuf(3)) che potrebbe rendere tailproblematico.
thrig

5
Anche questo non aiuta con la domanda, che riguardava come visualizzare l'output di un processo già in esecuzione, non come reindirizzare stdout per un nuovo processo.
jwbensley,

1

Analisi dell'output di strace:

Ho usato la risposta migliore (con il mio ID processo di 28223) ...

> sudo strace -p28223 -s9999 -e write
...
write(9, "Info\nI\nCare\nabout", 55) = 55
...

Per determinare che mi interessa write(9. (Il 9 è usato di seguito, probabilmente è un handle di file e potrebbe essere diverso per il tuo processo.) Poi ho scritto un rapido script Ruby per analizzarli e visualizzarli.

Incolla quanto segue in /usr/bin/parse_strace.rb

#!/usr/bin/ruby

num = ARGV[0]
STDIN.each { |line|
  if (line.match(/write\(#{ num },\s*"(.*?)"/)) then
    puts $1.split('\x').map { |s| s.to_i(16).chr }.join()
  end
}

Non dimenticare chmod a+x /usr/bin/parse_strace.rb

Invoco strace -xx(restituisce hex, quindi il regex corrisponde correttamente), eseguendo il piping (incluso STDERR) nel mio script 9come primo argomento.

sudo sh -c 'strace -xx -p28223 -s9999 -e write 2>&1 | parse_strace.rb 9'

E, voilà, produce STDOUT originale del processo, nuove linee, colore e tutto!

Collegamento al processo STDOUT


0

non riesci a ottenere l'ID processo e comunicare con esso con USR1,

$pgrep -l '^ipchecker.sh$'

che stampa il PID del tuo script, quindi usalo per

$ kill -USR1 PID

Comprendo che USR1 è un segnale "definito dall'utente", nel senso che chiunque abbia creato il programma può usarlo per significare "spegnimento" o "dump dei log" o "stampa foo mille volte" o qualsiasi altra cosa.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.