93

Consider the following (slightly silly) script name 'test1.sh':

#/bin/bash
#
sleep 10 &
echo sleep pid = $!
pkill sleep

When I run it, I get not only the output of the echo, but bash's reporting of the death of sleep on stderr:

$ ./test1.sh
sleep pid = 3551
./test1.sh: line 5:  3551 Terminated              sleep 10

In this case, I'd like to suppress the printout to stderr. I know I can do it on the command line, as in:

$ ./test1.sh 2> /dev/null

... but is there a way to suppress it from within the script? (I know I could wrap it in a second script and have the wrapper redirect it, but there must be something easier...)

5
  • did you try adding the redirect 2> /dev/null after the pkill sleep ?
    – rahul
    Commented Feb 14, 2015 at 6:22
  • 1
    @rahul: yes I did -- pkill isn't generating the message, bash is. Commented Feb 14, 2015 at 6:23
  • I used kill instead of pkill and do not get the stderr. strange..
    – rahul
    Commented Feb 14, 2015 at 6:32
  • @rahul: could it be a built in vs non-built in thing? Did you try it with pkill as well? Commented Feb 14, 2015 at 6:38
  • yes, i believe it is. I get the same error with pkill, but not with kill. While using kill, i used the pid instead of the proc name.
    – rahul
    Commented Feb 14, 2015 at 7:12

2 Answers 2

128

You're right; pkill isn't generating the message, bash is.  You suggest that

$ ./test1.sh 2> /dev/null

is a possible solution.  As UVV points out, the equivalent action from within the script is

exec 2> /dev/null

This redirects the stderr for the script to /dev/null from this statement until it is changed back.  Clumsy ways of changing it back include

exec 2> /dev/tty

which redirects stderr to the terminal.  This is probably (but not necessarily) where it was originally.

Or

exec 2>&1

which sets stderr to be the same as stdout, and is likely to be wrong.

A more reliable way is

exec 3>&2
exec 2> /dev/null
(do stuff where you don't want to see the stderr.)
exec 2>&3

which saves the original stderr in file descriptor 3, and later restores it.

Other ways to suppress just the announcement of the process death include

(sleep 10 & pkill sleep) 2> /dev/null

and

{ sleep 10 & pkill sleep;} 2> /dev/null

which change the stderr for only the grouped commands.

4
  • Are there any dangers associated with saving stdin and stderr to new file descriptors, sending the original descriptors to /dev/null and then restoring them? Commented Sep 15, 2017 at 18:37
  • Well, I suppose that, if you ran a program that (unbeknownst to you) wrote to file descriptor 3 (or 4), that operation would fail under normal circumstances.  But the program could be written to ignore the failure and carry on without reporting it; then you’d never know.  But if your file descriptor 1 (or 2) was “parked” on file descriptor 3 (or 4), then that program would suddenly be writing to your script’s stdout or stderr.  But that’s a very contrived example, and still minimal danger.   Did you have something in mind? Commented Sep 15, 2017 at 18:49
  • 1
    FWIW, I favor Scott's grouped command approach, i.e. { sleep 10 & pkill sleep;} 2> /dev/null Commented Sep 10, 2019 at 21:01
  • Running exec 2> /dev/null appears to also disable local echo in Bash 5.x (no prompt and no characters printed on screen when typing.)
    – Tuaris
    Commented Mar 15 at 0:11
13

According to this you could do something like following:

#!/bin/bash
exec 2>/dev/null
ls -al test
0

You must log in to answer this question.

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