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'
exit 1 exits the subshell running the code in side
(...) so that
2 is not output, and the parent shell process resumes echoing
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.
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
If you ran that command in the
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
bash-4.4$ /bin/kill -s PIPE 0
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).