14

I've been running a script for several days now. I redirected stdout to $HOME/mylog, but didn't redirect stderr since I thought there would be nothing on it. Suddenly thousands of lines started coming out on stderr, so I suspended the job. Is there a way I can redirect stderr to $HOME/myerr from now on, without needing to restart the script?

I have sudo access on the box and it's OS X.

Perhaps something using dtools trapping?

I cannot lose the work the script has done so far and restart it from scratch. Is there a way to "dump the in-memory objects" on disk, freeze the program, edit the variables (e.g. the file descriptors) and resume with the new context?

1

2 Answers 2

12

I think it is possible if you attach the process of the related interpreter to gdb. I tried it with this perl one-liner

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

and it works but unfortunately not with a similar bash script.


First of all you have to figure out the PID of that process whose output you want to capture. Then start gdb in another terminal and execute the following gdb-commands

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

after that the whole data that is written to stderr is redirected to /abs/olu/te/path/filename, since

  • attach PID attaches the process to gdb and stops it
  • call close(2) closes the stderr filedescriptor of the process (for stdout the filedescriptor is 1)
  • call open(...) opens a new file and takes the lowest unused integer for the newly created filedescriptor and
  • detach PID continues the process

At least on my machine. The first two lines are POSIX compatible but not the third one.

The second and the third argument of open in the third line are documented in man 2 open. In my case 65 means that open should create the file and open the file write-only i.e. O_WRONLY | O_CREAT (defined in fcntl.h). The third argument tells open to create the file with read and write permission for the user i.e. S_IWUSR | S_IRUSR (defined in sys/stat.h). So maybe you have to find out appropriate values on your machine by yourself.

1
  • This worked so stupendously well... hats off!! Commented Aug 19, 2012 at 20:24
8

This is a crude answer and I hope someone else does better, but if no other ideas surface, attach gdb and force the process to make a few syscalls:

(gdb) attach 12345 # target PID
(gdb) p close(2)
(gdb) p open("errfile", O_WRONLY)
(gdb) c
5
  • Nifty. I wasn't aware gdb could do that. Is there any way to force it to a specific file descriptor number? Like say if FD 1 is unused, and the open() grabs FD 1? Or do you just have to call dup() a few times?
    – phemmer
    Commented Aug 14, 2012 at 23:53
  • does p open("errfile", O_WRONLY) really work on your machine? Commented Aug 15, 2012 at 0:07
  • You could stick in a p dup2(xxx, 2) and then p close(xxx) where xxx is the return value of the open. This is tricky stuff, better not use these commands on a long-running process until you're sure there's no other choice.
    – Alan Curry
    Commented Aug 15, 2012 at 0:08
  • @user1146332 it did when I tried it because I used /dev/null as my errfile so I didn't need O_CREAT. And O_WRONLY being a macro, whether it expands or not depends on whether gdb stopped the process at a line where debugging symbols are available and the macro is defined. Injecting code into a process with gdb is dangerous and nobody just should be copying these commands without understanding them.
    – Alan Curry
    Commented Aug 15, 2012 at 0:18
  • @AlanCurry I don't think that gdb expands macros if general debugging information is available. You have to compile the sources with special flags (see here ). Besides it is very uncommon that an arbitrary executable on your system has debugging information included (let anlone the information are extended with macro information). But i agree with you that code injection is generally not advisable, but there might be cases where you benefit. Commented Aug 15, 2012 at 8:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .