Comment le processus d'interception stdout et stderr d'un autre processus sur Linux?

j'ai quelques scripts qui aurait cessé de fonctionner, mais l'accrocher autour pour toujours.

y a-t-il un moyen de savoir ce qu'ils écrivent à stdout et stderr de façon lisible ?

j'ai essayé, par exemple, de faire

tail -f /proc/(pid)/fd/1

mais ça ne marche pas vraiment. C'était un long shot de toute façon.

d'autres idées ? strace tout seul est assez verbeux et illisible pour voir cela.

Note: je suis intéressé à leur sortie, pas autre chose. Je suis capable de comprendre les autres choses par moi-même; cette question est uniquement axée sur l'accès à stdout et stderr du processus en cours d'exécution après départ.

39
demandé sur Paweł Hajdan 2008-10-30 12:55:50

8 réponses

Je ne suis pas sûr que ça va marcher pour vous, mais j'ai lu une page il y a quelques temps décrivant un méthode qui utilise gdb

7
répondu Jauco 2008-10-30 18:50:23

puisque je ne suis pas autorisé à éditer la réponse de Jauco, je vais donner la réponse complète qui a fonctionné pour moi (la page de Russell repose sur un comportement non garanti que, si vous fermez fd 1 pour stdout, le prochain creat call ouvrira fd 1.

Donc, l'exécution d'un simple sans fin de script comme ceci:

import time

while True:
    print 'test'
    time.sleep(1)

Enregistrer à test.py avec

python test.py

Obtenir le pid:

ps auxw | grep test.py

maintenant, attachez gdb:

gdb -p (pid)

et faire le fd magie:

(gdb) call creat("/tmp/stdout", 0600)
 = 3
(gdb) call dup2(3, 1)
 = 1

Maintenant vous pouvez tail /tmp/stdout et voir la sortie qui allait à stdout.

40
répondu Thomas Vander Stichele 2008-10-30 11:57:31

il y a plusieurs nouveaux utilitaires qui enveloppent la "méthode gdb" et ajoutent quelques touches supplémentaires. Celui que j'utilise maintenant s'appelle "reptyr" ("Re-PTY-er"). En plus de saisir STDERR/STDOUT, il va en fait changer le terminal de contrôle d'un processus (même s'il n'était pas précédemment attaché à un terminal).

la meilleure utilisation de ceci est de démarrer une session d'écran, et de l'utiliser pour rattacher un processus en cours d'exécution au terminal à l'intérieur de l'écran de sorte que vous pouvez se détacher en toute sécurité de lui et revenir tard.

il est empaqueté sur des distributions populaires (Ex: 'apt-get install reptyr').

http://onethingwell.org/post/2924103615/reptyr

9
répondu Mark Renouf 2012-09-11 01:07:09

la méthode Gdb semble meilleure, mais vous pouvez le faire aussi avec strace:

strace -p -e écrire=1 -s 1024 -o fichier

   -e write=set
               Perform a full hexadecimal and ASCII dump of all the
               data written to file descriptors listed in the spec-
               ified  set.  For example, to see all output activity
               on file descriptors 3 and 5 use -e write=3,5.   Note
               that  this is independent from the normal tracing of
               the write(2) system call which is controlled by  the
               option -e trace=write.

cela imprime un peu plus que ce dont vous avez besoin (la partie hexadécimale), mais vous pouvez le faire facilement.

8
répondu Daniel Lopez 2011-09-28 12:20:24

j'ai utilisé strace et dé-codé la sortie hex pour effacer le texte:

PID=some_process_id
sudo strace -f -e trace=write -e verbose=none -e write=1,2 -q -p $PID -o "| grep '^ |' | cut -c11-60 | sed -e 's/ //g' | xxd -r -p"

j'ai combiné cette commande avec d'autres réponses.

3
répondu Lari Hotari 2012-08-09 22:09:40

strace produit beaucoup moins avec just-ewrite (et pas le suffixe =1). Et c'est un peu plus simple que la méthode gdb, imo.

je l'ai utilisé pour voir les progrès d'une tv replay codage de l'emploi (sudo parce que je n'ai pas le processus d'encodage):

$ ps -aef | grep -i handbrake
mythtv   25089 25085 99 16:01 ?        00:53:43 /usr/bin/HandBrakeCLI -i /var/lib/mythtv/recordings/1061_20111230122900.mpg -o /var/lib/mythtv/recordings/1061_20111230122900.mp4 -e x264 -b 1500 -E faac -B 256 -R 48 -w 720
jward    25293 20229  0 16:30 pts/1    00:00:00 grep --color=auto -i handbr

$ sudo strace -ewrite -p 25089
Process 25089 attached - interrupt to quit
write(1, "\rEncoding: task 1 of 1, 70.75 % "..., 73) = 73
write(1, "\rEncoding: task 1 of 1, 70.76 % "..., 73) = 73
write(1, "\rEncoding: task 1 of 1, 70.77 % "..., 73) = 73
write(1, "\rEncoding: task 1 of 1, 70.78 % "..., 73) = 73^C
2
répondu Jeff Ward 2011-12-30 23:46:50

Vous pouvez utiliser reredirect (https://github.com/jerome-pouiller/reredirect/).

Tapez

reredirect -m FILE PID

et les sorties (standard et erreur) seront écrites en fichier.

reredirect README explique aussi comment restaurer l'état original du processus, comment rediriger vers une autre commande ou rediriger seulement stdout ou stderr.

2
répondu Jezz 2014-10-14 14:28:03

vous ne déclarez pas votre système d'exploitation, mais je vais tenter ma chance et dire "Linux".

voir ce qui est écrit à stderr et stdout ne va probablement pas aider. Si c'est utile, vous pouvez utiliser tee(1) avant de lancer le script pour prendre une copie de stderr et stdout.

vous pouvez utiliser ps(1) pour rechercher wchan. Cela vous indique ce que le processus attend. Si vous regardez la sortie strace, vous pouvez ignorer la majeure partie de la sortie et identifier le dernier (bloqué) de l'appel système. Si c'est une opération sur un descripteur de fichier, vous pouvez revenir en arrière dans la sortie et d'identifier l'objet sous-jacent (fichier, socket, pipe, etc.) A partir de là, la réponse sera probablement claire.

vous pouvez également envoyer au processus un signal qui lui fait basculer le noyau, puis utiliser le débogueur et le fichier core pour obtenir une trace de la pile.

1
répondu janm 2008-10-30 10:22:58