181

Normally I would start a command like

longcommand &;

I know you can redirect it by doing something like

longcommand > /dev/null;

for instance to get rid of the output or

longcommand 2>&1 > output.log

to capture output.

But I sometimes forget, and was wondering if there is a way to capture or redirect after the fact.

longcommand
ctrl-z
bg 2>&1 > /dev/null

or something like that so I can continue using the terminal without messages popping up on the terminal.

Sheldon Ross
  • 5,364
  • 7
  • 31
  • 37
  • 2
    SO is probably not optimal for this questions. I'm guessing SU is best, though the SF might have a better chance of answering it. MY best understanding, BTW: try `disown` if that fails you are out of luck. – dmckee --- ex-moderator kitten Aug 24 '09 at 18:32
  • 1
    You probably mean > where you wrote |. Both sides of a pipe have to be executables. If you're redirecting to a file or device (such as /dev/null) you use > and <. – Tyler McHenry Aug 24 '09 at 18:34
  • http://stackoverflow.com/questions/249703/how-can-a-process-intercept-stdout-and-stderr-of-another-process-on-linux http://stackoverflow.com/questions/682783/linux-redirect-stdout-after-the-process-started – mark4o Aug 24 '09 at 18:44
  • 1
    [reptyr](https://github.com/nelhage/reptyr) – lsl Aug 19 '13 at 07:02
  • i know it's a workaround but you can also do `shopt huponexit` logout and login, – jimh May 04 '20 at 06:39

5 Answers5

162

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 a close() system call and pass file handle 1, then I execute a creat() system call to open a new file. The result of the creat() 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 the dup2() system call to achieve that result.

For this example I chose to use creat() instead of open() 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().

Will Vousden
  • 32,488
  • 9
  • 84
  • 95
user37875
  • 13,904
  • 9
  • 37
  • 43
  • 31
    Always better to copy the gist of it here rather than just linking. – dmckee --- ex-moderator kitten Aug 24 '09 at 18:37
  • 6
    The gist: attach to the running process using `gdb`, then do 'p close(1)' and 'p creat("/tmp/foo3", 0600)' to redirect STDOUT, then disconnect gdb while leaving the program running. A clever trick! – cjm Aug 24 '09 at 18:52
  • 7
    If i could have gave you an Up Vote for every time i have used that link from your post, you would've been in the top 100 at least. By the way don't you feel the urge to get out of the userXXX league? – khael Apr 04 '12 at 01:48
  • 2
    This solution works, but I had to use gdb as root or the process failed to attach. – Seth Difley Mar 29 '13 at 18:13
  • Why would you link to such a trashy website filled with advertisers? It's obvious that the answer to this question did not originate from this site. Damn, backlink spammers. I hope someone teaches them a lesson. Maybe that person is me? – Eric Leroy Dec 14 '13 at 11:40
  • 1
    Usually a good way to get the header file constants in C is through python. For example: `import os; print(os.O_RDRW)` – mic_e Jun 20 '14 at 09:32
  • 3
    how does `creat` call know that it has to overwrite file handle `1` i.e. `stdout` ? – iggy Apr 13 '15 at 18:19
  • 2
    @iggy I guess it just uses the first free handle (and `1` was just closed, so obviously free and also first). – Ruslan Sep 05 '16 at 19:19
  • The nice thing is that this works also on cygwin :D – Zibri Aug 29 '17 at 16:14
  • Tried this with `python` code and got error regarding return type: `'close' has unknown return type; cast the call to its declared return type` Fixed it by adding `(int)` in front of called functions, like `p (int)close(1)` – MarSoft Jan 11 '19 at 15:26
  • Similarly, one can also use the dup2 function in combination with open to replace the file descriptor `(gdb) p dup2(open("/tmp/process_stdout", 1089, 0777), 1)` ( from https://www.baeldung.com/linux/redirect-output-of-running-process ) – Shawn May 26 '23 at 12:32
29

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).

Jérôme Pouiller
  • 9,249
  • 5
  • 39
  • 47
16

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/

Community
  • 1
  • 1
blah
  • 169
  • 1
  • 2
12

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.

Community
  • 1
  • 1
lemonsqueeze
  • 1,041
  • 8
  • 19
1

I collected some information on the internet and prepared the script that requires no external tool: See my response here. Hope it's helpful.

Community
  • 1
  • 1
Krzysztow
  • 781
  • 9
  • 11