First, if the script is run by a system daemon and that daemon is running with root privileges, you do not need to use
sudo. This includes
systemd), which includes
rc.local. If that daemon is not running with root privileges, then
sudo will not work unless
/etc/sudoers is configured to allow such (and without a password). Raspbian users may be confused by this since the
pi user is allowed to do anything by default (and if you look in
/etc/sudoers you will see how that is accomplished).
Next, you can capture output from any
bash script, or any set of commands inside a bash script, by executing them in a subshell like this:1
/bin/foo on 3
sudo bar a
) &> /var/log/myTestLog.txt
() indicates a subshell. All output from anything inside this is being redirected to a
/var/log/myTestLog.txt file. A few notes:
&> is a bashism, so if the script is executed via a shebang on the first line, it should be
#!/bin/bash, not just
/bin/sh. "Bashisms" work only in the
/etc/rc.local, which by default uses
/bin/sh (ie., yes, you can safely change that to
/var/log requires root privileges to write to. If the process does not have such, use or create a directory you know it can. When in doubt, if you can test this without having to shutdown or reboot the system, use
/tmp, which is world writable (i.e., by anyone). However
/tmp does not persist across boots. It is also a small, RAM based partition, so do not write gigs of data to it. It is not your SD card [actually on current versions of Raspbian it is, but don't count on this in practice].
&> will overwrite anything in
myTestLog.txt. If instead you want to append to a existing log, which might be a good idea for debugging purposes, use
&>>. You could then add a command to the beginning of that subshell like this:
echo Starting $(date)
To separate the information from each run. If you're not sure what this does, try on the command line.
This last point is a good illustration of something you can do with regard to commands that don't output anything -- but most of them do if you include, e.g.,
-v for "verbose". Beware for some commands
-v means "print version information". Have a look in the man page for the command to be sure if and how this will work (some commands also use a different switch than
By convention, commands also return a value of 0 when complete. This is sometimes called the "exit status" and you do not normally see it, but the shell will show you with
echo $?. Try
You'll get 0 and 2. If you then look in the man page for
ls under "Exit status", you'll see the rather unspecific, cryptic:
2 if serious trouble (e.g., cannot access command-line argument).
Which may or may not be better than nothing, but there you go.
At the very least, this indicates the command failed for some reason. The exit status also allows you to do things like this:
/bin/foo && sudo bar
&& in this case means "if the first command succeeds", presuming the first command uses the convention of returning 0 (which is why they usually do). If
/bin/foo does not work, cannot be found, etc., then
sudo bar will never happen.
Using a combination of logging messages and conditional execution (
&&) should get you much closer to figuring out the problem, or at least getting information that might be useful to others in helping you solve the problem. Without that, the most anyone else can often do is guess.
1. You can accomplish the same output redirection for an entire script from the inside by using:
exec &> /var/log/myTestLog.txt
At the top (or anywhere, and it will apply to everything subsequent).