Jay Taylor's notes

back to listing index

Redirect STDERR / STDOUT of a process AFTER it's been started, using command line?

[web search]
Original source (stackoverflow.com)
Tags: bash linux command-line unix strace stackoverflow.com
Clipped on: 2016-05-31

In the shell you can do redirection, > <, etc., but how about AFTER a program is started?

Here's how I came to ask this question, a program running in the background of my terminal keeps outputting annoying text. It's an important process so I have to open another shell to avoid the text. I'd like to be able to >/dev/null or some other redirection so I can keep working in the same shell.

asked Feb 27 '09 at 6:26
Image (Asset 3/25) alt=
Ian Kelling
I know the easiest way to redirect the STDOUT/STDERR is to DUP2 their file descriptors BEFORE forking. This is a fairly standard practice, and probably the way shells accomplish it right now. Not sure if that gives an answer, but I'm thinking it diminishes the chances of there being a good one. – Stefan Mai Feb 27 '09 at 6:31
up vote 86 down vote accepted

Short of closing and reopening your tty (i.e. logging off and back on, which may also terminate some of your background processes in the process) you only have one choice left:

  • attach to the process in question using gdb, and run:
    • p dup2(open("/dev/null", 0), 1)
    • p dup2(open("/dev/null", 0), 2)
    • detach
    • quit


$ tail -f /var/log/lastlog &
[1] 5636

$ ls -l /proc/5636/fd
total 0
lrwx------ 1 myuser myuser 64 Feb 27 07:36 0 -> /dev/pts/0
lrwx------ 1 myuser myuser 64 Feb 27 07:36 1 -> /dev/pts/0
lrwx------ 1 myuser myuser 64 Feb 27 07:36 2 -> /dev/pts/0
lr-x------ 1 myuser myuser 64 Feb 27 07:36 3 -> /var/log/lastlog

$ gdb -p 5636
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Attaching to process 5636
Reading symbols from /usr/bin/tail...(no debugging symbols found)...done.
Reading symbols from /lib/librt.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib/librt.so.1
Reading symbols from /lib/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/libpthread.so.0...(no debugging symbols found)...done.
[Thread debugging using libthread_db enabled]
[New Thread 0x7f3c8f5a66e0 (LWP 5636)]
Loaded symbols for /lib/libpthread.so.0
Reading symbols from /lib/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2

(no debugging symbols found)
0x00007f3c8eec7b50 in nanosleep () from /lib/libc.so.6

(gdb) p dup2(open("/dev/null",0),1)
[Switching to Thread 0x7f3c8f5a66e0 (LWP 5636)]
$1 = 1

(gdb) p dup2(open("/dev/null",0),2)
$2 = 2

(gdb) detach
Detaching from program: /usr/bin/tail, process 5636

(gdb) quit

$ ls -l /proc/5636/fd
total 0
lrwx------ 1 myuser myuser 64 Feb 27 07:36 0 -> /dev/pts/0
lrwx------ 1 myuser myuser 64 Feb 27 07:36 1 -> /dev/null
lrwx------ 1 myuser myuser 64 Feb 27 07:36 2 -> /dev/null
lr-x------ 1 myuser myuser 64 Feb 27 07:36 3 -> /var/log/lastlog
lr-x------ 1 myuser myuser 64 Feb 27 07:36 4 -> /dev/null
lr-x------ 1 myuser myuser 64 Feb 27 07:36 5 -> /dev/null

You may also consider:

  • using screen; screen provides several virtual TTYs you can switch between without having to open new SSH/telnet/etc, sessions
  • using nohup; this allows you to close and reopen your session without losing any background processes in the... process.
answered Feb 27 '09 at 6:48
Image (Asset 5/25) alt=
1 upvote
Your gdb answer did not work with tail -f file, and it did not work with a test program in c compiled with gcc -ggdb that does a printf every second. Also cont makes it impossible to run more gdb commands, the command would be detach, then quit. – Ian Kelling Feb 27 '09 at 7:11
Correct about detach, it's 2AM. :) What exactly did not work with the gdb solution? – vladr Feb 27 '09 at 7:27
My bad, not only did I have cont/detach wrong, but my dup2 was swapped. It should work now. – vladr Feb 27 '09 at 7:38
9 upvote
If you're redirecting stdout/stderr (to anything besides /dev/null apparently), you need to open the file with write access -- open("/path/to/new/stdout",O_WRONLY). O_WRONLY probably won't be available, though; its value is 1 on Linux/glibc. – Jander Oct 21 '10 at 5:34
9 upvote
A word of caution: attaching to a process in gdb pauses the process until you detach from it. – Marty B Nov 14 '11 at 3:20

This will do:

strace -ewrite -p $PID

It's not that clean (shows lines like: write(#,<text you want to see>) ), but works!

You might also dislike the fact that arguments are abbreviated. To control that use the -s parameter that sets the maximum length of strings displayed.

It catches all streams, so you might want to filter that somehow:

strace -ewrite -p $PID 2>&1 | grep "write(1" 

shows only descriptor 1 calls. 2>&1 is to redirect STDERR to STDOUT, as strace writes to STDERR by default.

answered Sep 14 '09 at 11:39
Image (Asset 7/25) alt=
This is a great solution. – Kyle W. Cartmell Jan 12 '10 at 1:07
5 upvote
This is not what the OP asked for. OP asked to REDIRECT away from the TTY, not intercept. Also, on some platforms strace/truss will insert spaces between intercepted stream characters and/or escape non-ASCII, and you'll have to deal with processing those too. – vladr Sep 4 '10 at 16:24
2 upvote
Yes, this does the thing partially - but for some people reading this question it's all they need - to see what's happening in a program mistakenly run to write to null or on another console. I found it out after finding this question in the process and thought it's a nice hack (at least for me). AND quite a few people find it helpful if my eyes don't decieve me ;) – naugtur Sep 6 '10 at 8:35

riffing off vladr's (and others') excellent research:

create the following two files in the same directory, something in your path, say $HOME/bin:

silence.gdb, containing (from vladr's answer):

p dup2(open("/dev/null",0),1)
p dup2(open("/dev/null",0),2)

and silence, containing:

if [ "$0" -a "$1" ]; then
 gdb -p $1 -x $0.gdb
 echo Must specify PID of process to silence >&2

chmod +x ~/bin/silence  # make the script executable

Now, next time you forget to redirect firefox, for example, and your terminal starts getting cluttered with the inevitable "(firefox-bin:5117): Gdk-WARNING **: XID collision, trouble ahead" messages:

ps  # look for process xulrunner-stub (in this case we saw the PID in the error above)
silence 5117  # run the script, using PID we found

You could also redirect gdb's output to /dev/null if you don't want to see it.

answered Nov 1 '10 at 2:55
Image (Asset 8/25) alt=
1 upvote
My gdb (v7.2) has a handy option --batch-silent which suppresses output and doesn't dump you into the gdb console if something goes wrong (eg missing process). BTW, $! refers to the most recent background job, but I don't think it can be used in the script itself. I use an alias: alias silencebg='silence $!' – seanf Feb 12 '13 at 5:25

Redirect output from a running process to another terminal, file or screen:

ls -l /proc/20818/fd
gdb -p 20818

Inside gdb:

p close(1)
p open("/dev/pts/4", 1)
p close(2)
p open("/tmp/myerrlog", 1)

Detach a running process from bash terminal and keep it alive:

bg %1 && disown %1


20818 - just an example of running process pid
p - print result of gdb command
close(1) - close standard output
/dev/pts/4 - terminal to write to
close(2) - close error output
/tmp/myerrlog - file to write to
q - quit gdb
bg %1 - run stoped job 1 on background
disown %1 - detach job 1 from terminal

answered Sep 30 '10 at 20:31
Image (Asset 9/25) alt=
1 upvote
This will not work if stdin (file descriptor 0) is closed. – pabouk Nov 24 '14 at 20:35

Not a direct answer to your question, but it's a technique I've been finding useful over the last few days: Run the initial command using 'screen', and then detach.

answered Feb 27 '09 at 7:00
Image (Asset 10/25) alt=
Roger Lipscombe

this is bash script part based on previous answers, which redirect log file during execution of an open process, it is used as postscript in logrotate process


pid=$(cat /var/run/app/app.pid)

    if [ "$pid" = "" ]; then
        gdb -p $pid >/dev/null 2>&1 <<LOADLOG
p close(1)
p open("$logFile", 1)
p close(2)
p open("$logFile", 1)
        LOG_FILE=$(ls /proc/${pid}/fd -l | fgrep " 1 -> " | awk '{print $11}')
        echo "log file set to $LOG_FILE"

answered Feb 19 '14 at 14:46
Image (Asset 11/25) alt=

Your Answer


7 years ago


57651 times


3 months ago

Hot Network Questions

Technology Life / Arts Culture / Recreation Science Other
  1. Stack Overflow
  2. Server Fault
  3. Super User
  4. Web Applications
  5. Ask Ubuntu
  6. Webmasters
  7. Game Development
  8. TeX - LaTeX
  1. Programmers
  2. Unix & Linux
  3. Ask Different (Apple)
  4. WordPress Development
  5. Geographic Information Systems
  6. Electrical Engineering
  7. Android Enthusiasts
  8. Information Security
  1. Database Administrators
  2. Drupal Answers
  3. SharePoint
  4. User Experience
  5. Mathematica
  6. Salesforce
  7. ExpressionEngine® Answers
  8. more (13)
  1. Photography
  2. Science Fiction & Fantasy
  3. Graphic Design
  4. Movies & TV
  5. Seasoned Advice (cooking)
  6. Home Improvement
  7. Personal Finance & Money
  8. Academia
  9. more (9)
  1. English Language & Usage
  2. Skeptics
  3. Mi Yodeya (Judaism)
  4. Travel
  5. Christianity
  6. Arqade (gaming)
  7. Bicycles
  8. Role-playing Games
  9. more (21)
  1. Mathematics
  2. Cross Validated (stats)
  3. Theoretical Computer Science
  4. Physics
  5. MathOverflow
  6. Chemistry
  7. Biology
  8. more (5)
  1. Stack Apps
  2. Meta Stack Exchange
  3. Area 51
  4. Stack Overflow Careers
site design / logo © 2016 Stack Exchange Inc; user contributions licensed under cc by-sa 3.0 with attribution required
rev 2016.5.27.3620