Re: How to get bash to shut up about SIGPIPE?
From: Paul Jackson <hidden>
Date: 2016-06-15 22:41:55
bash is being an ass about SIGPIPE
You have a multiprocessor, don't you.
The following silly little shell script will provoke the bash SIGPIPE
complaint reliably on a multiprocessor. It writes a big file, twice,
from a for-loop in a separate bash subshell through a pipe to a command
that exits after seeing one line.
Code Sample 1:
#!/bin/bash
for x in 1 2
do
cat /etc/termcap # a big text file
done | sed 1q
Adding a right trap _inside_ the shell loop that is _before_ the pipe
will reduce the verbosity of the complaint substantially (not show the
line number and text for each command inside the loop that is killed by
the SIGPIPE; rather just show the simple "Broken pipe" error message):
Code Sample 2:
#!/bin/bash
for x in 1 2
do
trap continue PIPE # reduce broken pipe screeching
cat /etc/termcap # a big text file
done | sed 1q
Then wrapping the entire pipeline (now that the bogus output is a
constant "Broken pipe" string) in the following manner will filter out
just that noise, leaving whatever else was on stdout and/or stderr
unscathed:
Code Sample 3:
#!/bin/bash
( ( (
for x in 1 2
do
trap continue PIPE # reduce broken pipe screeching
cat /etc/termcap # a big text file
done | sed 1q
) 1>&3 ) 2>&1 | grep -vxF 'Broken pipe' 1>&2 ) 3>&1
The following patch to bash jobs.c will enable "Code Sample 2" to do the
right thing, without depending (so much) on the DONT_REPORT_SIGPIPE
compile time flag. With this patch, you don't have to go all the way to
the baroque code in "Code Sample 3" to shut bash up. Just a well placed
trap is sufficient.
Whether or not this is actually worth persuing (or was even worth
reading ;) I don't know.
--- jobs.c.orig 2001-03-26 10:08:24.000000000 -0800
+++ jobs.c 2005-04-29 17:09:44.294763496 -0700@@ -2686,11 +2686,8 @@ notify_of_job_status () } else if (IS_FOREGROUND (job)) { -#if !defined (DONT_REPORT_SIGPIPE) - if (termsig && WIFSIGNALED (s) && termsig != SIGINT) -#else - if (termsig && WIFSIGNALED (s) && termsig != SIGINT && termsig != SIGPIPE) -#endif + if (termsig && WIFSIGNALED (s) && termsig != SIGINT && + (termsig != SIGPIPE || signal_is_trapped (termsig) == 0)) { fprintf (stderr, "%s", strsignal (termsig));
--
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <pj@engr.sgi.com> 1.650.933.1373, 1.925.600.0401