The easiest way to have something run at boot is via /etc/rc.local
. Some systemd based distros (e.g., Arch and Fedora) have stopped including this, although it is easy to implement. Which doesn't matter in this case since currently Raspbian does still have that file. It probably contains something about printing the IP address to console, but don't worry if you've never noticed this happen, neither have I, and you can remove that stuff if you want. What must be there is at the beginning, and the end:
#!/bin/sh -e
[... everything else ...]
exit 0
The first part is worth noting, because what sh
defaults to on Raspbian is dash
, not bash
. You may want to look at man dash
to find out what the -e
means. This may or may not matter to you and although you can change it to, e.g., #!/bin/bash
(which is why I mention it), in this case you might as well leave it as is.
When /etc/rc.local
is run at boot, it is run by the init process, systemd. This means it is run with root privileges, so you do not need to use sudo
(and to prevent complication, should not).
Although there probably is a valid $PATH
set, to be paranoid you may also want to include absolute paths, meaning in this case /usr/bin/python
.
nohup
The purpose of nohup
is to "run a command immune to hangups", meaning, ignore SIGHUP
from the OS, which according to man 7 signal
indicates "hangup detected on controlling terminal or death of controlling process".
A process started via init does not have a controlling terminal, and its controlling process is init, which as per the wikipedia article will never die (or at least, if it does, it is replaced immediately and re-parents the children of the previous init process, meaning those children can never end up as orphans, and it is orphaned processes that end up getting a SIGHUP).
So you do not need and should not use nohup
in /etc/rc.local
either. If your process is mysteriously dying, that is not the problem and it will not fix anything.
Backgrounding
What will cause your process to die mysteriously is remaining in the foreground for more than a few seconds. Anything which is going to last longer than that should either fork itself and exit (leaving the fork running), which you can do in python if you want, or else it should be executed from a shell which does the same thing.
This is a very common task for shells so the POSIX standard (which covers dash
and bash
) includes the "control operator" &
to send a process to the background, which is accomplished by forking the shell itself, then executing the command from the fork.
That allows the foreground shell to continue on, which with /etc/rc.local
is important, because again, if it doesn't get to
exit 0
Within a short period of time, init will nix it. And you can't usefully put anything after that, because exit
is the end.
The &
can be a little confusing because the same character is used in redirection, as you are doing. You're also using &
to background, but you've made a mistake by putting them in the wrong order.
python /home/pi/test.py & 1>/dev/null 2>&1
The 1>/dev/null 2>&1
is effectively meaningless here, although that may be hard to notice if there is no output anyway. However, if this is run from the command line it will leave the backgrounded process more prone to "hangup" signals if the "controlling terminal" dies which is perhaps why you've resorted to nohup
. In any case, the background operator must be the last thing in the command. So the complete version for /etc/rc.local
should be:
/usr/bin/python /home/pi/test.py 1>/dev/null 2>&1 &
If that seems not to work, you need to incorporate some logging into test.py
to better diagnose what's going on.
sudo
in the entry is at best pointless, andnohup
even more so. However, if the process is persistent, it must fork to the background (blah blah 1>wherever 2>&1 &
). The fork is the last ampersand. – goldilocks Aug 19 '16 at 11:42