GNU/Linux >> Linux Esercitazione >  >> Linux

Forza lo svuotamento del buffer di output nel programma in esecuzione

SE uno volesse davvero quei dati, suggerirei di allegare il gdb debugger all'interprete python, interrompendo momentaneamente l'attività, chiamando fsync(1) (stdout ), staccati da esso (riprendendo il processo) e vai a esaminare il file di output.

Cerca in /proc/$(pidof python)/fd per visualizzare descrittori di file validi. $(pidof x) restituisce il PID del processo denominato '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

Ho usato questo metodo per cambiare directory di lavoro, modificare le impostazioni al volo... molte cose. Purtroppo, puoi chiamare solo funzioni che sono definite nel programma in esecuzione, fsync funziona bene però.

(comando gdb 'info functions ' elencherà tutte le funzioni disponibili. Stai attento però. Stai operando DAL VIVO su un processo.)

C'è anche il comando peekfd (si trova in psmisc pacchetto su Debian Jessie e altri) che ti permetterà di vedere cosa si nasconde nei buffer di un processo. Di nuovo, /proc/$(pidof python)/fd ti mostrerà descrittori di file validi da dare come argomenti a peekfd.

Se non ricordi -u per python, puoi sempre prefissare un comando con stdbuf (in coreutils , già installato) per impostare stdin/stdout/stderr su unbuffered, line buffered o block buffered come desiderato:

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

Certo, man pages sono tuoi amici, ehi! forse un alias potrebbe essere utile anche qui.

alias python='python -u'

Ora il tuo pitone usa sempre -u per tutti i tuoi sforzi da riga di comando!


Per prima cosa assicurati di avere i simboli di debug per Python (o almeno glibc). Su Fedora puoi installarli con:

dnf debuginfo-install python

Quindi allega gdb allo script in esecuzione ed eseguire i seguenti comandi:

[[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

Questo cancellerà stdout e disabilita anche il buffering. Il 2 dal setvbuf call è il valore di _IONBF sul mio sistema. Dovrai scoprire cosa c'è nel tuo (un grep _IONBF /usr/include/stdio.h dovrebbe funzionare).

Sulla base di ciò che ho visto nell'implementazione di PyFile_SetBufSize e PyFile_WriteString in CPython 2.7, dovrebbe funzionare abbastanza bene, ma non posso dare alcuna garanzia.


Non c'è soluzione al tuo problema immediato. Se il tuo script è già iniziato, non puoi modificare la modalità di buffering dopo il fatto. Questi sono tutti buffer in memoria e tutto ciò viene impostato all'avvio dello script, all'apertura degli handle di file, alla creazione di pipe, ecc.

Come azzardo, se e solo se parte o tutto il buffering in questione viene eseguito a livello di IO sull'output, potresti eseguire un sync comando; ma questo è generalmente improbabile in un caso come questo.

In futuro potrai usare -u di Python opzione per eseguire lo script. In generale, molti comandi hanno opzioni specifiche per disabilitare il buffering stdin/stdout e potresti anche avere qualche successo generico con unbuffer comando dal expect pacchetto.

Un Ctrl +C causerebbe lo svuotamento dei buffer a livello di sistema quando il programma viene interrotto a meno che il buffering è fatto da Python stesso e non ha implementato la logica per svuotare i propri buffer con Ctrl +C . Una sospensione, un crash o un kill non sarebbero così gentili.

Forza stdin, stdout e stderr per essere totalmente unbuffered.


Linux
  1. Un programma in grado di eseguire il buffering di Stdin o file?

  2. Come non fare nulla per sempre in modo elegante?

  3. reindirizzamento dell'output al volo, visualizzando l'output del reindirizzamento del file mentre il programma è ancora in esecuzione

  4. Output a colori del programma eseguito in BASH

  5. Come visualizzare l'elenco dei processi in esecuzione Python?

Programma Python che consuma RAM

Esecuzione di uno script Python da PHP

pytest in esecuzione con un'altra versione di python

Determina se l'output è stdout o stderr

Arresta il programma in esecuzione all'avvio in Linux

Aumenta la dimensione del buffer durante l'esecuzione dello schermo