J'ai des scripts qui auraient dû cesser de fonctionner mais qui traînent pour toujours. Existe-t-il un moyen de comprendre ce qu'ils écrivent sur STDOUT et STDERR de manière lisible?
J'ai essayé, par exemple, de faire:
$ tail -f /proc/(pid)/fd/1
mais ça ne marche pas vraiment. Ce fut un long coup de toute façon.
D'autres idées?
strace
seul est assez verbeux et illisible pour voir cela.
Remarque: je suis seulement intéressé par leur sortie, pas par autre chose. Je suis capable de comprendre les autres choses par moi-même; cette question se concentre uniquement sur l'accès à stdout et stderr du processus en cours après le démarrer.
Je ne sais pas si cela fonctionnera pour vous, mais j'ai lu une page tout à l'heure décrivant une méthode qui utilise gdb
Étant donné que je ne suis pas autorisé à modifier la réponse de Jauco, je donnerai la réponse complète qui a fonctionné pour moi (la page de Russell repose sur un comportement non garanti qui, si vous fermez le descripteur de fichier 1 pour STDOUT, la prochaine creat
l'appel ouvrira FD 1.
Alors, lancez un simple script sans fin comme celui-ci:
import time
while True:
print 'test'
time.sleep(1)
Enregistrez-le dans test.py, exécutez avec
$ python test.py
Obtenez le PID:
$ ps auxw | grep test.py
Maintenant, attachez gdb
:
$ gdb -p (pid)
et faites la magie de fd
:
(gdb) call creat("/tmp/stdout", 0600)
$1 = 3
(gdb) call dup2(3, 1)
$2 = 1
Maintenant vous pouvez tail /tmp/stdout
et voir la sortie utilisée pour aller à STDOUT.
Il y a plusieurs nouveaux utilitaires qui complètent 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, cela changera en fait le terminal de contrôle d'un processus (même s'il n'était pas précédemment attaché à un terminal).
La meilleure utilisation est de démarrer une session d'écran et de l'utiliser pour rattacher un processus en cours au terminal dans l'écran afin de pouvoir le détacher en toute sécurité et revenir plus tard.
Il est empaqueté sur des distributions populaires (Ex: 'apt-get install reptyr').
La méthode GDB semble meilleure, mais vous pouvez aussi le faire avec strace
:
$ strace -p <PID> -e write=1 -s 1024 -o file
Via la page de manuel de strace
:
-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 sed
cela facilement.
J'ai utilisé strace et décodé la sortie hexadécimale 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 à partir d'autres réponses.
strace
sort beaucoup moins avec seulement -ewrite
(et non le =1
suffixe). Et c'est un peu plus simple que la méthode GDB, IMO.
Je l'ai utilisé pour voir la progression d'un travail d'encodage MythTV existant (Sudo
car je ne possède 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 rerirect ( https://github.com/jerome-pouiller/reredirect/ ).
Type
reredirect -m FILE PID
et les sorties (standard et erreur) seront écrites dans FILE.
reredirect README
explique également comment restaurer l'état d'origine du processus, comment rediriger vers une autre commande ou rediriger uniquement stdout ou stderr.
Vous ne dites pas votre système d'exploitation, mais je vais essayer de dire "Linux".
Voir ce qui est écrit sur stderr et stdout ne va probablement pas aider. Si cela est utile, vous pouvez utiliser tee (1) avant de démarrer 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 appel système (bloqué). S'il s'agit d'une opération sur un descripteur de fichier, vous pouvez revenir en arrière dans la sortie et identifier l'objet sous-jacent (fichier, socket, pipe, etc.). De là, la réponse est probablement claire.
Vous pouvez également envoyer au processus un signal qui le fait vider le core, puis utiliser le débogueur et le fichier core pour obtenir une trace de pile.