Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can a process intercept stdout and stderr of another process on Linux?

Tags:

linux

stdout

I have some scripts that ought to have stopped running but hang around forever. Is there some way I can figure out what they're writing to STDOUT and STDERR in a readable way?

I tried, for example, to do:

$ tail -f /proc/(pid)/fd/1 

but that doesn't really work. It was a long shot anyway.

Any other ideas?

strace on its own is quite verbose and unreadable for seeing this.

Note: I am only interested in their output, not in anything else. I'm capable of figuring out the other things on my own; this question is only focused on getting access to stdout and stderr of the running process after starting it.

like image 577
Thomas Vander Stichele Avatar asked Oct 30 '08 09:10

Thomas Vander Stichele


People also ask

How would you redirect both stdout and stderr of any command to a file?

Redirecting stdout and stderr to a file: The I/O streams can be redirected by putting the n> operator in use, where n is the file descriptor number. For redirecting stdout, we use “1>” and for stderr, “2>” is added as an operator.

Which is used to redirect both stdout and stderr?

Understanding the concept of redirections and file descriptors is very important when working on the command line. To redirect stderr and stdout , use the 2>&1 or &> constructs.

How do I redirect stdout of a running process?

The way we can redirect the output is by closing the current file descriptor and then reopening it, pointing to the new output. We'll do this using the open and dup2 functions. There are two default outputs in Unix systems, stdout and stderr. stdout is associated with file descriptor 1 and stderr to 2.

What is stdout and stderr in Linux?

The Linux Standard StreamsText output from the command to the shell is delivered via the stdout (standard out) stream. Error messages from the command are sent through the stderr (standard error) stream. So you can see that there are two output streams, stdout and stderr , and one input stream, stdin .


2 Answers

Since I'm not allowed to edit Jauco's answer, I'll give the full answer that worked for me (Russell's page relies on un-guaranteed behaviour that, if you close file descriptor 1 for STDOUT, the next creat call will open FD 1.

So, run a simple endless script like this:

import time  while True:     print 'test'     time.sleep(1) 

Save it to test.py, run with

$ python test.py 

Get the PID:

$ ps auxw | grep test.py 

Now, attach gdb:

$ gdb -p (pid) 

and do the fd magic:

(gdb) call creat("/tmp/stdout", 0600) $1 = 3 (gdb) call dup2(3, 1) $2 = 1 

Now you can tail /tmp/stdout and see the output that used to go to STDOUT.

like image 116
Thomas Vander Stichele Avatar answered Sep 17 '22 09:09

Thomas Vander Stichele


There's several new utilities that wrap up the "gdb method" and add some extra touches. The one I use now is called "reptyr" ("Re-PTY-er"). In addition to grabbing STDERR/STDOUT, it will actually change the controlling terminal of a process (even if it wasn't previously attached to a terminal).

The best use of this is to start up a screen session, and use it to reattach a running process to the terminal within screen so you can safely detach from it and come back later.

It's packaged on popular distros (Ex: 'apt-get install reptyr').

http://onethingwell.org/post/2924103615/reptyr

like image 43
Mark Renouf Avatar answered Sep 21 '22 09:09

Mark Renouf