exit 1
exits the current subshell environment with exit code 1, so for instance in:
sh -c '(echo 1; exit 1; echo 2); echo 3'
That exit 1
exits the subshell running the code in side (...)
so that 2
is not output, and the parent shell process resumes echoing 3
.
kill -s PIPE "$$"
¹ sends the SIGPIPE signal to the process that executed the shell interpreter currently interpreting the script. The SIGPIPE signal by default causes processes to terminate, and the fact that that process has been killed by SIGPIPE is reflected in its exit status.
So in:
sh -c '(echo 1; kill -s PIPE "$$"; echo 2); echo 3'
A SIGPIPE signal is sent by the subshell process to its parent process (the one that executed sh
). That parent process will die and not output 3
while the subshell process will carry on running in background and output 2
.
If you ran that command in the bash
or zsh
shell (and a few other Bourne-like shells), those shells will set the $?
parameter (their internal representation of the exit status of the last command) to something like 141, which is 128 + SIGPIPE (13 on most systems).
Now SIGPIPE is the signal sent by the system to processes that are attempting to write to a pipe or socket that has no reading end (a broken pipe/socket), so sending it here is a bit misleading. The signal reserved for administratively terminate a process is SIGTERM, that happens to be the signal kill
sends by default.
Now, one reason why you may want to use SIGPIPE instead of SIGTERM is that there are shells like bash
that output a message when one of their job is terminated by a signal, while they generally don't do it for SIGPIPE (as it's common for processes to be terminated by a SIGPIPE, and doesn't necessarily mean there's a problem like in cmd | head -n 1
), so using SIGPIPE is a way to avoid those messages.
bash-4.4$ /bin/kill 0
Terminated
bash-4.4$ /bin/kill -s PIPE 0
bash-4.4$
even when non-interactive:
$ bash -c 'sh -c "kill \$\$"; exit'
bash: line 1: 6665 Terminated sh -c "kill \$\$"
$ bash -c 'sh -c "kill -s PIPE \$\$"; exit'
$
1 Here adding the missing quotes around $$
for reliability and using the standard (non-optional in POSIX) kill -s PIPE
syntax for portability (though kill -PIPE
should also work on most systems).
exit 1
doesn't exit butkill -PIPE $$
does? – Joseph Sible-Reinstate Monica Oct 28 '18 at 17:08(exit 1)
instead ofexit 1
? – xenoid Oct 28 '18 at 19:44