Conditional execution is used in Bash to control the flow of a script on the basis of the exit status of a subprocess. However, there are situations when a subprocess (application) is launched in the background, to be used for interactive purposes, so there is no exit and no exit status, until it is closed.
Consider some examples, say launching a pdf viewer, mupdf. Consider the first case with a file that exists, example.pdf:
$ mupdf example.pdf &
[1] 16220
That works, so let's try conditional execution:
$ mupdf example.pdf & && echo TRUE
bash: syntax error near unexpected token '&&'
Hmmm. Ok, let's try another (contrived) way, trying to avoid errors:
$ if mupdf example.pdf &; then echo TRUE; fi
bash: syntax error near unexpected token ';'
How about:
$ if (mupdf example.pdf &); then echo TRUE; fi
TRUE
That looks promising, But then we try the second case, with a file that does not exist:
$ mupdf nofile.pdf &
[1] 16282
$ error: cannot open nofile.pdf
error: cannot load document 'nofile.pdf'
mupdf: error: cannot open document
$ if (mupdf nofile.pdf &); then echo TRUE; fi
TRUE
$ error: cannot open nofile.pdf
error: cannot load document 'nofile.pdf'
mupdf: error: cannot open document
That construct is not working either. So the usual approach to conditional execution does not work because there is no exit status. But I noted that a pid is initially created in both successful and unsuccessful cases (mupdf does not open in the second case - launching ultimately fails).
So try another approach, wait to see what happens with the background pid, so we put together the following script:
#!/usr/bin/env bash
# usage: ./show <file>.pdf
mupdf "$1" &>/dev/null &
sleep 2
if kill -0 $! &>/dev/null
then
echo TRUE
else
echo FALSE
fi
# end file
And test the first case:
$ ./show example.pdf # case 1
[1] 16602
TRUE
That's OK. Now the second case:
$ ./show nofile.pdf # case 2
[2] 16699
[2]+ Exit 1 mupdf nofile.pdf &> /dev/null
FALSE
Well that works too. But this seems a very convoluted way to check the process and may fail if the launch takes more time (more than 2 seconds). So my question becomes, is there a better (cleaner) way to solve this problem?
nofile.pdfexists?{ mupdf some.pdf || kill -"$(($?&127))" "$$"; } &&bitwise op will strip any eighth bit which might have been added to the return. Since you're raising withkillanyway, whatever you do is going to be signal - you can't help that. You really should do more testing than that - for examplekill -127 0; command ""; echo "$?". My linux system only handles signal numbers 1-64, sokill -"$(($?&63))" pid...? Trykill -lfor a name list, orset -x "$((x=0))"; while trap "" "$((x+=1))"; do trap; trap - "$x"; done"maybe.