Reindirizza stderr da uno script già in esecuzione


14

Gestisco una sceneggiatura da diversi giorni. Ho reindirizzato stdout a $HOME/mylog, ma non ho reindirizzato stderr poiché pensavo che non ci sarebbe stato nulla. All'improvviso migliaia di linee iniziarono a uscire su Stderr, quindi ho sospeso il lavoro. C'è un modo in cui posso reindirizzare stderr $HOME/myerrda ora in poi, senza bisogno di riavviare lo script?

Ho accesso sudo sulla scatola ed è OS X.

Forse qualcosa usando l'intrappolamento dei dtools?

Non posso perdere il lavoro svolto dalla sceneggiatura finora e riavviarlo da zero. Esiste un modo per "scaricare gli oggetti in memoria" sul disco, bloccare il programma, modificare le variabili (ad esempio i descrittori di file) e riprendere con il nuovo contesto?


Risposte:


12

Penso che sia possibile se si collega il processo dell'interprete correlato a gdb. L'ho provato con questo perl one-liner

 perl -e 'do { print "x\n"; sleep(1) } while(1)'

e funziona ma sfortunatamente non con uno script bash simile.


Prima di tutto devi capire il PID di quel processo di cui vuoi catturare l'output. Quindi avviare gdbin un altro terminale ed eseguire i seguenti comandi gdb

attach PID
call close(2)
call open("/abs/olu/te/path/filename", 65, 384)
detach PID

dopo che tutti i dati a cui viene scritto stderrvengono reindirizzati /abs/olu/te/path/filename, da allora

  • attach PID allega il processo a gdb e lo interrompe
  • call close(2)chiude il stderrfiledescriptor del processo (per stdoutil filedescriptor è 1)
  • call open(...) apre un nuovo file e accetta il numero intero non utilizzato più basso per il filedescriptor appena creato e
  • detach PID continua il processo

Almeno sulla mia macchina. Le prime due linee sono compatibili POSIX ma non la terza.

Il secondo e il terzo argomento di opennella terza riga sono documentati in man 2 open. Nel mio caso 65 significa che opendovrebbe creare il file e aprire il file in sola scrittura, cioè O_WRONLY | O_CREAT(definito in fcntl.h). Il terzo argomento dice open per creare il file con l'autorizzazione in lettura e scrittura per l'utente, ovvero S_IWUSR | S_IRUSR(definito in sys/stat.h). Quindi forse devi scoprire i valori appropriati sulla tua macchina da solo.


Questo ha funzionato così meravigliosamente bene ... via di cappello !!
Robottinosino,

8

Questa è una risposta volgare e spero che qualcun altro faccia meglio, ma se non emergono altre idee, allega gdb e forza il processo a fare qualche syscall:

(gdb) attach 12345 # target PID
(gdb) p close(2)
(gdb) p open("errfile", O_WRONLY)
(gdb) c

Nifty. Non sapevo che gdb potesse farlo. Esiste un modo per forzarlo a un numero descrittore di file specifico? Come dire se FD 1 non è in uso, e open()afferra FD 1? O devi solo chiamare dup()alcune volte?
Patrick,

funziona p open("errfile", O_WRONLY)davvero sulla tua macchina?
user1146332

È possibile inserire a p dup2(xxx, 2)e quindi p close(xxx)dov'è xxxil valore di ritorno di open. Questa è roba difficile, meglio non usare questi comandi su un processo a lungo termine finché non sei sicuro che non ci sia altra scelta.
Alan Curry,

@ user1146332 è successo quando l'ho provato perché l'ho usato /dev/nullcome mio, errfilequindi non ne avevo bisogno O_CREAT. Ed O_WRONLYessendo una macro, se si espande o meno dipende dal fatto che gdb abbia interrotto il processo su una riga in cui sono disponibili simboli di debug e la macro è definita. L'iniezione di codice in un processo con gdb è pericolosa e nessuno dovrebbe semplicemente copiare questi comandi senza capirli.
Alan Curry,

@AlanCurry Non penso che gdb espanda le macro se sono disponibili informazioni generali sul debug. Devi compilare i sorgenti con flag speciali (vedi qui ). Inoltre è molto raro che un eseguibile arbitrario sul tuo sistema includa informazioni di debug (lascia che le informazioni vengano estese con informazioni macro). Ma sono d'accordo con te sul fatto che l'iniezione di codice non è generalmente consigliabile, ma potrebbero esserci casi in cui ne trarrai beneficio.
user1146332
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.