In your code with set -e (short for set -o errexit) unhandled command failures cause the shell to exit.
pidof returns with a failure exit status when no matching process is found, but you do handle that failure. pidof is used as part of a and-or list, so its failure does not trigger errexit.
However because you used an and-or list where you should have used a if construct, the pidof && othercommand itself exits with a non-zero exit status and because that and-or list is the last thing run in the checkIfRunning function, the checkIfRunning function itself will also return with a failure exit status.
And that failure is not handled, so errexit is triggered. errexit is triggered not because pidof fails but because checkIfRunning failed.
Here, you should have written:
checkIfRunning() {
if pidof -o %PPID -x -- "$0" >/dev/null; then
echo >&2 'Already running!'
exit 1
fi
}
The exit status of a if construct is that of the last command run in the then or else part or 0 if none was run, not the exit status of the condition part.
Generally, replacing if constructs with and-or lists is wrong. Besides the problem of the overall exit status, if echo fails in your pidof && echo && exit 1, the script doesn't exit.
I'd argue that as soon as you use functions or anything other than the simplest script, errexit should be avoided and proper error handling be done.
See the corresponding section about set -euo pipefail in the bash wiki (short for set -o errexit -o nounset -o pipefail) or this FAQ entry.
Regarding your (now deleted) answer which tried to address the problem with:
checkIfRunning() {
set +e # <---
pidof -o %PPID -x $0 >/dev/null \
&& echo "running!" && exit 1
set -e # <---
}
The only reason it works is because set -e happens to exit with a success status, so checkIfRunning does as well, the set +e is irrelevant and not needed, set -e could have been replaced with true or return 0.
./myscript.sh. Are you implying the above should work and the problem is elsewhere? – lonix Jul 16 '22 at 07:29$0inside a function expands to the name of the function. Something to bear in mind if you intend to switch to another shell in the future. HavingSCRIPTNAME=$0at the start of the script and refer to that instead would make your script more portable. – Stéphane Chazelas Jul 16 '22 at 08:58function f { ...;}syntax. – Stéphane Chazelas Jul 16 '22 at 09:04man setsays that The-esetting shall be ignored when executing the compound list following the while, until, if, or elif reserved word (...) or any command of an AND-OR list other than the last. -- I read this as: "set -ewill not react to anything in a&&-chain except the last command", which in this case simply exits 1 (successfully). – pzkpfw Jul 16 '22 at 09:56setcommand. It seems on your systemsetman page documents thesetspecial builtin of some POSIX-like shell, or maybe it's actually the POSIX specification of the specialsetshbuiltin. Here, the OP would want to look at the documentation of their own shell. Likeinfo bash setforbashorinfo zsh errexitforzsh– Stéphane Chazelas Jul 16 '22 at 14:58