5

I am using Raspbian.

I have created a Python GPIO script which is supposed to run at the time of the boot.

I have tried to use @reboot in sudo crontab -e. Unfortunately, it is not working at all. I used sudo for the crontab and have made the following crontab entry,

@reboot sudo nohup python /home/pi/test.py & 1>/dev/null 2>&1

The problem is, test.py is not invoked at the startup :(

I checked it by ps -ef | grep -i test.py in the lxterminal. It does not return any row.

The command sudo nohup python /home/pi/test.py & 1>/dev/null 2>&1 works without any issues. Please do let me know where I am making blunder.

Ashwin Pajankar
  • 183
  • 4
  • 9
  • 21
  • May be useful: http://raspberrypi.stackexchange.com/questions/40493/log-output-of-background-or-boot-script As per remarks there, using sudo in the entry is at best pointless, and nohup 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
  • 1
    If you are using Raspbian indicate this and I will give you an answer. If you are using something else, please edit the OS into your question. – goldilocks Aug 19 '16 at 11:51
  • @goldilocks, I have added the OS. Its Raspbian. Please help me. – Ashwin Pajankar Aug 20 '16 at 14:14

2 Answers2

6

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.

goldilocks
  • 58,859
  • 17
  • 112
  • 227
0

You can try next: Rewrite your script to make him possible to run as daemon with infinite cycle inside it and put it inside rc.init or another services of startup configuration. In the cycle body check the availability of GPIO and do what you want. You need cycle because some kernel module could be loaded after some delay, execution of another scripts or something else. You can also try to create systems unit what will run your script after GPIO became available.

ArhiChief
  • 27
  • 1
  • 3