40

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

  • did you try adding the redirect 2> /dev/null after the pkill sleep ? – rahul Feb 14 '15 at 6:22
  • @rahul: yes I did -- pkill isn't generating the message, bash is. – fearless_fool Feb 14 '15 at 6:23
  • I used kill instead of pkill and do not get the stderr. strange.. – rahul Feb 14 '15 at 6:32
  • @rahul: could it be a built in vs non-built in thing? Did you try it with pkill as well? – fearless_fool Feb 14 '15 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 Feb 14 '15 at 7:12
60

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.

  • This is such a great, detailed answer. Thank you Sir! – Keenan Lawrence Aug 20 '17 at 22:04
  • 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? – Alexej Magura Sep 15 '17 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? – Scott Sep 15 '17 at 18:49
7

According to this you could do something like following:

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.