GNU/Linux >> Tutoriels Linux >  >> Linux

Forcer le vidage du tampon de sortie dans le programme en cours d'exécution

SI on voulait vraiment ces données, je suggérerais de joindre le gdb débogueur à l'interpréteur python, arrêtant momentanément la tâche, appelant fsync(1) (sortie standard ), détachez-vous de celui-ci (reprise du processus) et allez parcourir le fichier de sortie.

Regardez dans /proc/$(pidof python)/fd pour voir les descripteurs de fichiers valides. $(pidof x) renvoie le PID du processus nommé 'x '.

# your python script is running merrily over there.... with some PID you've determined.
#
# load gdb
gdb
#
# attach to python interpreter (use the number returned by $(pidof python))
attach 1234
#
# force a sync within the program's world (1 = stdout, which is redirected in your example)
call fsync(1)
#
# the call SHOULD have returned 0x0, sync successful.   If you get 0xffffffff (-1), perhaps that wasn't stdout.  0=stdin, 1=stdout, 2=stderr
#
# remove our claws from poor python
detach
#
# we're done!
quit

J'ai utilisé cette méthode pour modifier les répertoires de travail, modifier les paramètres à la volée... beaucoup de choses. Hélas, vous ne pouvez appeler que des fonctions définies dans le programme en cours d'exécution, fsync fonctionne bien cependant.

(commande gdb 'info functions ' listera toutes les fonctions disponibles. Soyez prudent cependant. Vous opérez EN DIRECT sur un processus.)

Il y a aussi la commande peekfd (trouvé dans psmisc package sur Debian Jessie et autres) qui vous permettra de voir ce qui se cache dans les tampons d'un processus. Encore une fois, /proc/$(pidof python)/fd vous montrera des descripteurs de fichiers valides à donner comme arguments à peekfd.

Si vous ne vous souvenez pas de -u pour python, vous pouvez toujours préfixer une commande avec stdbuf (en coreutils , déjà installé) pour définir stdin/stdout/stderr sur unbuffered, line buffered ou block buffered comme vous le souhaitez :

stdbuf -i 0 -o 0 -e 0 python myscript.py > unbuffered.output

Bien sûr, man pages sont vos amis, hé! peut-être qu'un alias pourrait être utile ici aussi.

alias python='python -u'

Maintenant, votre python utilise toujours -u pour tous vos efforts en ligne de commande !


Assurez-vous d'abord que vous avez les symboles de débogage pour Python (ou au moins glibc). Sur Fedora, vous pouvez les installer avec :

dnf debuginfo-install python

Attachez ensuite gdb au script en cours d'exécution et exécutez les commandes suivantes :

[[email protected] ~]$ pidof python2
9219
[[email protected] ~]$ gdb python2 9219
GNU gdb (GDB) Fedora 7.7.1-13.fc20
...
0x00007fa934278780 in __read_nocancel () at ../sysdeps/unix/syscall-template.S:81
81  T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
(gdb) call fflush(stdout)
$1 = 0
(gdb) call setvbuf(stdout, 0, 2, 0)
$2 = 0
(gdb) quit
A debugging session is active.

    Inferior 1 [process 9219] will be detached.

Quit anyway? (y or n) y
Detaching from program: /usr/bin/python2, process 9219

Cela videra stdout et également désactiver la mise en mémoire tampon. Le 2 du setvbuf call est la valeur de _IONBF sur mon système. Vous devrez découvrir ce qu'il y a sur le vôtre (un grep _IONBF /usr/include/stdio.h devrait faire l'affaire).

D'après ce que j'ai vu dans l'implémentation de PyFile_SetBufSize et PyFile_WriteString dans CPython 2.7, cela devrait fonctionner plutôt bien, mais je ne peux donner aucune garantie.


Il n'y a pas de solution à votre problème immédiat. Si votre script a déjà démarré, vous ne pouvez pas modifier le mode de mise en mémoire tampon après coup. Ce sont tous des tampons en mémoire et tout cela est configuré lorsque le script démarre, les descripteurs de fichiers sont ouverts, les canaux sont créés, etc.

À long terme, si et seulement si une partie ou la totalité de la mise en mémoire tampon en question est effectuée au niveau IO en sortie, vous pouvez faire un sync commande; mais cela est généralement peu probable dans un cas comme celui-ci.

À l'avenir, vous pourrez utiliser le -u de Python possibilité d'exécuter le script. En général, de nombreuses commandes ont des options spécifiques à la commande pour désactiver la mise en mémoire tampon stdin/stdout, et vous pouvez également avoir un certain succès générique avec le unbuffer commande du expect paquet.

Un Ctrl +C entraînerait le vidage des tampons au niveau du système lorsque le programme est interrompu à moins que la mise en mémoire tampon est effectuée par Python lui-même et il n'a pas implémenté la logique pour vider ses propres tampons avec Ctrl +C . Une suspension, un crash ou un kill ne serait pas si gentil.

Forcer stdin, stdout et stderr à être totalement sans tampon.


Linux
  1. Comment ne rien faire pour toujours de manière élégante ?

  2. Installer un programme Python sous Linux

  3. Python peut-il détecter sous quel système d'exploitation s'exécute-t-il?

  4. Exécuter une commande linux à partir de python

  5. Exécuter un script Python à partir de PHP

Comment redémarrer (ou réinitialiser) un processus en cours d'exécution sous Linux ?

redirection de sortie à la volée, voir la sortie de redirection de fichier pendant que le programme est toujours en cours d'exécution

Sortie couleur du programme exécuté sous BASH

Programme Python consommant de la RAM

Code Python pour vérifier si le service est en cours d'exécution ou non. ?

Arrêter le programme en cours d'exécution au démarrage sous Linux