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.
The tail –pid=PID with -f option, will terminate the display once the process ID (PID) dies.
Since you have the PID (returned from posix_spawn ) and you are running Linux, you will find the stdout of the process at /proc/<pid>/fd/1 . Just open (or fopen ) the file for reading. The standard way is to use fork though. Use pipe and dup2 to get a file descriptor for reading the child's output, as in this question.
See Redirecting Output from a Running Process.
Firstly I run the command
cat > foo1
in one session and test that data from stdin is copied to the file. Then in another session I redirect the output.Firstly find the PID of the process:
$ ps aux | grep cat rjc 6760 0.0 0.0 1580 376 pts/5 S+ 15:31 0:00 cat
Now check the file handles it has open:
$ ls -l /proc/6760/fd total 3 lrwx—— 1 rjc rjc 64 Feb 27 15:32 0 -> /dev/pts/5 l-wx—— 1 rjc rjc 64 Feb 27 15:32 1 -> /tmp/foo1 lrwx—— 1 rjc rjc 64 Feb 27 15:32 2 -> /dev/pts/5
Now run GDB:
$ gdb -p 6760 /bin/cat GNU gdb 6.4.90-debian [license stuff snipped] Attaching to program: /bin/cat, process 6760 [snip other stuff that's not interesting now] (gdb) p close(1) $1 = 0 (gdb) p creat("/tmp/foo3", 0600) $2 = 1 (gdb) q The program is running. Quit anyway (and detach it)? (y or n) y Detaching from program: /bin/cat, process 6760
The
p
command in GDB will print the value of an expression, an expression can be a function to call, it can be a system call… So I execute aclose()
system call and pass file handle 1, then I execute acreat()
system call to open a new file. The result of thecreat()
was 1 which means that it replaced the previous file handle. If I wanted to use the same file for stdout and stderr or if I wanted to replace a file handle with some other number then I would need to call thedup2()
system call to achieve that result.For this example I chose to use
creat()
instead ofopen()
because there are fewer parameter. The C macros for the flags are not usable from GDB (it doesn’t use C headers) so I would have to read header files to discover this – it’s not that hard to do so but would take more time. Note that 0600 is the octal permission for the owner having read/write access and the group and others having no access. It would also work to use 0 for that parameter and run chmod on the file later on.After that I verify the result:
ls -l /proc/6760/fd/ total 3 lrwx—— 1 rjc rjc 64 2008-02-27 15:32 0 -> /dev/pts/5 l-wx—— 1 rjc rjc 64 2008-02-27 15:32 1 -> /tmp/foo3 <==== lrwx—— 1 rjc rjc 64 2008-02-27 15:32 2 -> /dev/pts/5
Typing more data in to
cat
results in the file/tmp/foo3
being appended to.If you want to close the original session you need to close all file handles for it, open a new device that can be the controlling tty, and then call
setsid()
.
You can also do it using reredirect
(https://github.com/jerome-pouiller/reredirect/).
The command bellow redirects the outputs (standard and error) of the process PID
to FILE
:
reredirect -m FILE PID
The README
of reredirect
also explains other interesting features: how to restore the original state of the process, how to redirect to another command or to redirect only stdout or stderr.
The tool also provides relink
, a script allowing to redirect the outputs to the current terminal:
relink PID
relink PID | grep usefull_content
(reredirect
seems to have same features than Dupx described in another answer but, it does not depend on Gdb).
Dupx
Dupx is a simple *nix utility to redirect standard output/input/error of an already running process.
Motivation
I've often found myself in a situation where a process I started on a remote system via SSH takes much longer than I had anticipated. I need to break the SSH connection, but if I do so, the process will die if it tries to write something on stdout/error of a broken pipe. I wish I could suspend the process with ^Z and then do a
bg %1 >/tmp/stdout 2>/tmp/stderr
Unfortunately this will not work (in shells I know).
http://www.isi.edu/~yuri/dupx/
Screen
If process is running in a screen session you can use screen's log command to log the output of that window to a file:
Switch to the script's window, C-a H to log.
Now you can :
$ tail -f screenlog.2 | grep whatever
From screen's man page:
log [on|off]
Start/stop writing output of the current window to a file "screenlog.n" in the window's default directory, where n is the number of the current window. This filename can be changed with the 'logfile' command. If no parameter is given, the state of logging is toggled. The session log is appended to the previous contents of the file if it already exists. The current contents and the contents of the scrollback history are not included in the session log. Default is 'off'.
I'm sure tmux has something similar as well.
I collected some information on the internet and prepared the script that requires no external tool: See my response here. Hope it's helpful.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With