There's no error checking or handling at all in those scripts. If you don't have that and something is failing mysteriously, the first thing you need to do is add it -- otherwise there is not much point in doing anything else.
Foreground process calls always exit with a status code, and while not all programs necessarily use this, the vast majority do. Unfortunately, what the values mean is often undocumented, but conventionally the approach is to consider many kinds of failure and only one kind of success, and indicate the latter with an exit status of 0.
The exit status of the last foreground process is available within POSIX shell scripts via the special variable $?
. For example:
#!/bin/sh
ls /home > /dev/null
echo $?
ls /nosuchthing > /dev/null
echo $?
This should print:
0
ls: cannot access '/nosuchthing': No such file or directory
2
A few things to notice:
The first ls
call, which succeeded because /home
is a real directory which is world readable, returned 0. The actual output was redirected to /dev/null
, so we don't see it.
The second call, which failed because /nosuchthing
does not exist for me here, failed. Why ls
returns 2 is another question; what is important for us is that it isn't 0, because ls
follows convention and only exits 0 when it succeeds.
The error output from ls
was not redirected to /dev/null
, because it is printed to a separate stream, "standard error". It could have been redirected to the same place as "standard output" (which is what ls /home
printed to) by using ls /nosuchthing > /dev/null 2>&1
.
The last point is important, because by not combining the output and error streams, we can discard one (which is sometimes what you want to do in a shell script, if you don't care about what's output when a process succeeds), and redirect errors to a log!
ls /nosuchthing > /dev/null 2>> err.log
The script will now simply spit out:
0
2
And, if your current directory is writable, leave an err.log
behind it with the error message. Some fancier approaches to this are described here:
Log output of background or boot script
Again, what we are most concerned with is that exit code, because even if the program does not spit out messages on failure, we can:
if [ $? -ne 0 ]; then
echo "Whatever failed!" >> /home/pi/whatever/err.log
fi
Notice that here, and in the last example, I'm using append (>>
) instead of truncate (>
) with redirection. That's also described in the other Q&A about logging. It is important.
If a program's exit status is undocumented, which it often is, you'll need to do a bit of experimentation on the command line (which is a POSIX shell, so $?
is available there too). Note that while not all programs make use of the exit status, they all have one. If they don't make use of it, they probably just return 0 for everything.
I don't have a camera connected and running anywhere right now to check that way WRT to raspistill
, but from a quick glance at main()
in the source code it should be apparent to anyone who understands C that raspistill
does implement a variable exit status, and in fact makes use of sysexits.h
, a header file which includes some standardized exit values, including 0 for success.
So, raspistill
, and most (possibly, all) of the commands you use will exit 0 on success and something else on failure.
You need to:
- Check and respond to the exit status of foreground/blocking calls within the script appropriately, and
- Use a log.
Note that this may or may not isolate your problem, but until you rule out the possibilities it covers, there is no point in contemplating anything else.