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.
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
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.
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').
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.
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.
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
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.
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.