Redirigir stderr desde un script que ya se está ejecutando

14

Llevo varios días ejecutando un script. Redirigí stdout a $HOME/mylog, pero no redirigí stderr ya que pensé que no habría nada en él. De repente, miles de líneas comenzaron a salir en stderr, así que suspendí el trabajo. ¿Hay alguna manera de redirigir stderr a $HOME/myerrpartir de ahora, sin necesidad de reiniciar el script?

Tengo acceso a sudo en la caja y es OS X.

¿Quizás algo que usa dtools trapping?

No puedo perder el trabajo que el script ha hecho hasta ahora y reiniciarlo desde cero. ¿Hay alguna forma de "volcar los objetos en memoria" en el disco, congelar el programa, editar las variables (por ejemplo, los descriptores de archivo) y reanudar con el nuevo contexto?

Robottinosino
fuente
posible duplicado de redireccionamiento / grep'ing STDOUT de una concha existente
Gilles 'SO- deja de ser malvado'

Respuestas:

12

Creo que es posible si adjunta el proceso del intérprete relacionado a gdb. Lo probé con este perl one-liner

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

y funciona pero desafortunadamente no con un script bash similar.


En primer lugar, debe averiguar el PID de ese proceso cuya salida desea capturar. Luego comience gdben otra terminal y ejecute los siguientes comandos gdb

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

después de eso, todos los datos que se escriben stderrse redirigen a /abs/olu/te/path/filename, ya que

  • attach PID adjunta el proceso a gdb y lo detiene
  • call close(2)cierra el stderrdescriptor de archivo del proceso (para stdoutel descriptor de archivo es 1)
  • call open(...) abre un nuevo archivo y toma el número entero sin usar más bajo para el descriptor de archivo recién creado y
  • detach PID continúa el proceso

Al menos en mi máquina. Las dos primeras líneas son compatibles con POSIX, pero no la tercera.

El segundo y el tercer argumento de openen la tercera línea están documentados en man 2 open. En mi caso, 65 significa que opendebería crear el archivo y abrir el archivo de solo escritura, es decir O_WRONLY | O_CREAT(definido en fcntl.h). El tercer argumento le dice a open que cree el archivo con permiso de lectura y escritura para el usuario, es decir S_IWUSR | S_IRUSR(definido en sys/stat.h). Entonces, tal vez tenga que encontrar los valores apropiados en su máquina usted mismo.

usuario1146332
fuente
Esto funcionó tan bien ... ¡me quito el sombrero!
Robottinosino
8

Esta es una respuesta cruda y espero que alguien más lo haga mejor, pero si no surgen otras ideas, adjunte gdb y fuerce el proceso a realizar algunas llamadas al sistema:

(gdb) attach 12345 # target PID
(gdb) p close(2)
(gdb) p open("errfile", O_WRONLY)
(gdb) c
Alan Curry
fuente
Hábil. No sabía que gdb pudiera hacer eso. ¿Hay alguna forma de forzarlo a un número de descriptor de archivo específico? ¿Como decir si FD 1 no se usa, y la open()captura FD 1? ¿O solo tienes que llamar dup()algunas veces?
Patrick
¿ p open("errfile", O_WRONLY)realmente funciona en tu máquina?
user1146332
Podría pegarse en ay p dup2(xxx, 2)luego p close(xxx)dónde xxxestá el valor de retorno de open. Esto es algo complicado, mejor no use estos comandos en un proceso de larga duración hasta que esté seguro de que no hay otra opción.
Alan Curry
@ user1146332 lo hizo cuando lo probé porque lo usé /dev/nullcomo mi, errfileasí que no lo necesitaba O_CREAT. Y al O_WRONLYser una macro, si se expande o no depende de si gdb detuvo el proceso en una línea donde los símbolos de depuración están disponibles y la macro está definida. Inyectar código en un proceso con gdb es peligroso y nadie debería copiar estos comandos sin entenderlos.
Alan Curry
@AlanCurry No creo que gdb expanda macros si hay información de depuración general disponible. Tienes que compilar las fuentes con banderas especiales (ver aquí ). Además, es muy poco común que un ejecutable arbitrario en su sistema tenga información de depuración incluida (deje que solo la información se extienda con información macro). Pero estoy de acuerdo con usted en que la inyección de código generalmente no es aconsejable, pero puede haber casos en los que se beneficie.
user1146332