Sunday, 10 June 2012

Raspberry Pi - run program at start-up

Anyway, I wanted to get my Raspberry Pi to start no-ip dynamic dns service when it started-up, so I wouldn't have to remember to start it every time it was powered up.  For details on how to install no-ip on the Pi, see this post.

There are loads of ways of running a command at start-up in Linux but my favoured approach is to create an initialisation script in /etc/init.d and register it using update-rc.d.  This way the application is started and stopped automatically when the system boots / shutdowns.

Create script in /etc/init.d
sudo nano /etc/init.d/NameOfYourScript

The following is an example based on starting up the no-ip service [/usr/local/bin/noip], but change the name of the script and the command to start and stop it and it would work for any command.

#! /bin/sh
# /etc/init.d/noip

### BEGIN INIT INFO
# Provides:          noip
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Simple script to start a program at boot
# Description:       A simple script from
www.stuffaboutcode.com which will start / stop a program a boot / shutdown.
### END INIT INFO


# If you want a command to always run, put it here

# Carry out specific functions when asked to by the system
case "$1" in
  start)
    echo "Starting noip"
    # run application you want to start
    /usr/local/bin/noip2
    ;;
  stop)
    echo "Stopping noip"
    # kill application you want to stop
    killall noip2
    ;;
  *)
    echo "Usage: /etc/init.d/noip {start|stop}"
    exit 1
    ;;
esac

exit 0

Warning - its important you test your script first and make sure it doesn't need a user to provide a response, press "y" or similar, because you may find it hangs the raspberry pi on boot waiting for a user (who's not there) to do something!

Make script executable
sudo chmod 755 /etc/init.d/NameOfYourScript

Test starting the program
sudo /etc/init.d/NameOfYourScript start

Test stopping the program
sudo /etc/init.d/NameOfYourScript stop

Register script to be run at start-up
To register your script to be run at start-up and shutdown, run the following command:

sudo update-rc.d NameOfYourScript defaults

Note - The header at the start is to make the script LSB compliant and provides details about the start up script and you should only need to change the name.  If you want to know more about creating LSB scripts for managing services, see http://wiki.debian.org/LSBInitScripts

If you ever want to remove the script from start-up, run the following command:

sudo update-rc.d -f  NameOfYourScript remove

61 comments:

  1. Hi Martin,

    Thanks for the Blog! I've tried using your code above to run no-ip on start-up (I have the Raspberry Pi B Model running Debian Squeeze) but keep getting the error below when trying to run it:

    "11: Syntax error: word unexpected (expecting ")")"

    I've installed the same version of no-ip as you have above, and have installed it in the same location. Any ideas on what is causing this error?

    I've done a bit of reading and think i wonder what O/S you are using as it may be that you have writted your code for something other than Debian.

    Cheers,

    James

    ReplyDelete
    Replies
    1. Hi James,

      I don't know what to suggest, I am using the Debian Squeeze distro (19-04-2012). To make sure I have just recreated this script on my pi copying and pasting the script from above and I didn't experience any errors.

      Have you made any changes to the distro, installing dev libraries anything like that which might be causing an issue?

      Sorry I cant be of more help.

      Mart

      Delete
    2. James,

      Something came to mind, have you included the #! /bin/sh directive at the top of your script? This tells the linux program loader to use the /bin/sh interpreter, although its ignored by the script itself. If you have, check that /bin/sh exists and its not in a different directory.

      Mart

      Delete
    3. I had same problem. I found that when you copy and paste from the web site you get some hidden characters in the white spaces.
      This can be fixed by deleting all if the white space indenting on each line... Even the spaces before any # must be deleted. You can put back the spacing using space bar if you wish.

      Also found that if I use:
      sudo /etc/init.d/xxx start
      The script works but the imbedded program never starts without any indication. Starting without using sudo works fine. Must use sudo to stop the program.
      Kevin


      Delete
  2. Hi Martin,

    Thanks for the help, i did have the #!/bin/sh and it was in the right directory. I found another script similar to yours above, except with the addition of

    "User:root
    UserHome:/root/home/

    $Export USERINFO"

    (or something along those lines)

    Which allows me to run vnc and noip on startup!

    However, with the downside of having to startup my vnc server as root, which isnt ideal.

    Im thinking maybe i have some permission problems, but can't seem to figure out what is wrong.

    Thanks for the help.

    James

    ReplyDelete
  3. Hi Martin,

    I might have an issue here. I used this script to loop a video on startup (works great!) with OMXPlayer using the same code as they used here:
    http://www.raspberrypi.org/phpBB3/viewtopic.php?t=10218&p=115800

    **************
    #!/bin/sh -x

    SERVICE='omxplayer'
    while true; do
    if ps ax | grep -v grep | grep $SERVICE > /dev/null
    then
    echo "runing" # sleep 1
    else
    omxplayer /usr/local/bin/LTC.mp4

    fi
    done
    **************

    When I stop the video (Q) the shell code starts the video again.
    It works perfect for the initial idea (fool-proof plug and play video loop for exhibition, except for the small gap between end&start), but I wonder if there are options to get out without needing to format the card :)
    If any of you have some suggestions, except for typing
    "sudo update-rc.d -f NameOfYourScript remove" in a second..

    Thanks!

    Paul

    ReplyDelete
  4. Martin, great post! This worked right out of the box for me. Two questions for you as I'm a bit of a UNIX noob:

    1) If I should have a typo in my script, will that cause the entire boot process to stop or will it just ignore the bad script? IOW, will I be able to easily fix the bug?
    2) I'm running my NodeJS server at start up and I see the following processes when I check:

    root 1919 1 4 10:56 ? 00:00:03 node /var/www/vevo/app.js
    root 1921 1 0 10:56 ? 00:00:00 startpar -f -- nodejs
    root 2286 2275 0 10:57 pts/0 00:00:00 grep node

    Now, the first one and the last one I'm expecting but what is the second one?

    Thanks,

    - MT

    ReplyDelete
    Replies
    1. BTW, my script is named "nodejs" (all lowercase).

      Delete
    2. 1) No, if you have an error in your script it wont stop the boot process, you will probably see the error on screen when your Pi boots up. I would recommend you test your script before commiting it to run at boot by using /etc/init.d/nodejs start - this will show you whether it works or not
      2) Not a clue, I know nothing about nodejs or how it runs, startpar is a linux utility used to run scripts in parallel, but thats where my insight ends!

      Delete
    3. Thanks Martin! Script was tested as per your instructions above and it works great!

      Delete
  5. Hello Martin, thanks for your blog!

    I followed your steps to make my python script auto run after raspberry pi power on but got some error message when run command "sudo update-rc.d lcd12864 defaults":

    update-rc.d: using dependency based boot sequencing
    insserv: warning: script 'Fonts.pyc' missing LSB tags and overrides
    insserv: warning: script 'Fonts.py' missing LSB tags and overrides
    insserv: warning: script 'ST7565.pyc' missing LSB tags and overrides
    insserv: warning: script 'main.py' missing LSB tags and overrides
    insserv: warning: script 'ST7565.py' missing LSB tags and overrides

    I googled the error message and got this link http://wiki.debian.org/LSBInitScripts, but after i did what it said i still got the same error message after run that command.

    Do you have some ideas of this? thanks in advance!

    ReplyDelete
    Replies
    1. They are warnings letting you know you have scripts in init.d which aren't LSB compliant. They look a bit scary but they wont affect the script and it will still work. Creating LSB compliant scripts for a simple startup program is overkill and quite frankly a pain in the backside. So, in summary, my advice would be "dont worry".

      Delete
    2. Yes, as you said, I just test that my python script can auto run after power on. Even if i got warnings message when add it to the init.d. Thanks very very much! :)

      Delete
  6. @Martin - thank you very much. This is precisely what I was looking for! Works great.

    ReplyDelete
  7. Martin, Thanks for this explanation.
    Yet: Now I have put it in, it works only sometimes (Random if it works or not).

    The script I am using is also using an SQL database (it's a thermostat that start/stop the heating, and it is controlled remotely by writing values in a MySQL. The script then looks at the database to see if it should enable/disable the heating in the house).

    As far as I can see it seems that the SQL server sometimes comes up later then the script, causing the python-script to stop because it cannot connect.

    My question therefore: Can you actually control which service should start first or last? Would it make sense to have a pause at the start of the script?

    ReplyDelete
    Replies
    1. You have some control over when your script runs by modifying the Required-Start tag in the LSB header, you should be able to add $all to the tag (after $syslog) which tells the script to run after all other scripts.

      See http://wiki.debian.org/LSBInitScripts for more info.

      Delete
    2. Hey Martin,
      Thanks for the reply; I now now where to look!
      I have implemented it over SSH remotely, so I will be able to see if it works only once I am at the Raspberry, to see if the GPIO is really functioning. Yet, I am confident it will!

      Thanks again!

      Delete
  8. Hi Martin I tried the above for iPLayer and it doesn't seem to start it automatically.

    when running (I called the file iPlayer)

    sudo /etc/init.d/iPlayer start
    sudo update-rc.d NameOfYourScript defaults

    both run without errors and iPlayer starts, but after reboot this has to be run manually, I copied your script about and replaced

    /usr/local/bin/noip2
    with
    perl ./get_iplayer-2.82/get_iplayer.cgi --port=1935 --getiplayer=./get_iplayer-2.82/get_iplayer 2>> /logfile/path/logfile.log &

    does it not like perl on bootup?

    Regards

    John

    ReplyDelete
  9. Hi John,

    I think you problem is due to 'relative' paths, when you use ./ it effectively says use "my current directory". dot [.] is your current directory dot dot [..] is the parent directory.

    When your command ./get_iplayer-2.82/get_iplayer.cgi runs at start-up the current directory will be different and your program wont be found.

    So I think you will be able to solve your problem by using full paths (which is always a good idea when creating scripts), if get_iplayer is installed in your home directory (/home/pi), referred to as ~, the following should work

    perl /home/pi/get_iplayer-2.82/get_iplayer.cgi --port=1935 --getiplayer=/home/pi/get_iplayer-2.82/get_iplayer 2>> /logfile/path/logfile.log &

    Let me know how you get on.

    Mart

    ReplyDelete
  10. Martin - thanks very much for your help.
    I can confirm this is now loading on boot perfectly

    ReplyDelete
  11. Hello,
    I'm having a little problem with my script. I wanted to test if a simple script that I already had written starts on boot. It does, however I didn't think about including a way to stop the script and now I can't log in to my Raspberry. CTRL+C doesn't work as well as any other commands I tried. I tried searching for a way to stop the script manually but I didn't find anything usefull. Any suggestions?

    ReplyDelete
    Replies
    1. Im surprised you cant login - What does the script do? Is it waiting for a user input? Has it hung while starting up?

      Can you login to the pi via ssh from another machine? If you can I would use sudo update-rc.d -f NameOfYourScript remove, to remove the script from the startup process and reboot. If you cant login at all, Im stumped, you might be able to modify the contents of the SD card if you have a linux pc and delete your script from /etc/init.d.

      Let me know how you get on.

      Delete
    2. I tried everything I could think of, everything I found with google, I even asked a friend of mine who is a linux expert, but nothing worked. The script was waiting for user input so basically none of the linux commands worked.
      I didn't set up SSH either so that wasn't an option.

      So the only option left was to back up all the important data from my SD card and reinstall Rasbian.

      Leasons learned: always include a failsafe in your code.

      Delete
    3. Oh yeah, almost forgot. I reinstalled Rasbian because I didn't have a linux pc at my disposal and for Windows I could only find a ext reader application, no write permission.

      Delete
    4. Ill update the post to put a warning about making sure your script doesn't hang waiting for a user input which wont ever happen.

      Delete
  12. Like Marko I ended up with a non interrupable script running preventing me doing anything and only option I could do was to rebuild SD card. Therefore I would appreciate your post update you mention above and any tips on how to run a prpgram at startup in the background. Or what not to do!
    Many thanks!

    ReplyDelete
  13. Thank you very much!
    I tried this , but when the ip address changes it does not work . I can't access it online (it's not recognizing the change in ip)
    I thought it might be a problem with the startup so I went to run it it said it already is running ..

    Do you have any idea what might be the problem?

    ReplyDelete
  14. Thanks for the post, but I just can't get mine to work on boot!

    I want to open iceweasel on startup and have written the following script called startweasel:

    -------------------------------------
    #! /bin/sh
    # /etc/init.d/startweasel

    ### BEGIN INIT INFO
    # Provides: iceweasel
    # Required-Start: $remote_fs $syslog $all
    # Required-Stop: $remote_fs $syslog
    # Default-Start: 2 3 4 5
    # Default-Stop: 0 1 6
    # Short-Description: Simple script to start a program at boot
    # Description: A simple script from www.stuffaboutcode.com which will start / stop a program a boot / shutdown.
    ### END INIT INFO

    # If you want a command to always run, put it here
    echo "Starting Iceweasel"
    iceweasel

    # Carry out specific functions when asked to by the system

    exit 0
    -------------------------------------

    The script runs fine but doesn't run at startup. I have run "sudo update-rc.d startweasel defaults"

    Do you have any suggestions?

    ReplyDelete
    Replies
    1. I think the problem is that it S04 on the start whereas x11 is S16 so it's trying to start the browser before the GUI. I've tried running "sudo update-rc.d startweasel defaults 17 17" but it still comes up as S04

      Delete
    2. Hi Miles, have you had any luck? I've never tried to start up X programs using a init.d script, so sorry Im not a lot of help.

      Delete
  15. Hello Martin,

    How can you build in dependencies, i have to wait till apache is started before my specific program may start.

    regards,W

    ReplyDelete
    Replies
    1. You have some control over when your script runs by modifying the Required-Start tag in the LSB header, you should be able to specify the apache service here, although it might be easier to add $all to the tag (after $syslog) which tells the script to run after all other scripts.

      See http://wiki.debian.org/LSBInitScripts for more info.

      Delete
  16. hello Martin

    I start noip at boot (works) but when I shutdown my rpi, it halts. I guess that noip doesn't properly be killed.

    My script is the same as yours.
    I tried killall en pkill but nothing.

    Regards DM

    ReplyDelete
    Replies
    1. Sounds odd are you sure its noip which is halting the shutdown?

      If you use killall noip from the command prompt does that work?

      Delete
    2. This comment has been removed by the author.

      Delete
    3. Ok problem is fixed but I don't know how.
      I didn't change a thing on the script and now everything works.

      Thanks for helping

      Delete
  17. Hi Martin,
    Im trying to start a bluetooth dongle which auto starts on boot and scans for other bluetooth devices. I used your code to start it on boot up. The code works perfect but it shows an error during boot
    "Error Initializing the bluetooth device"
    But once i login into the pi and run the program, it works!
    I guess the bluetooth is only started after the init script is run. I tried adding $all but still it doesnt work. Pls help me!!

    ReplyDelete
  18. Hey Martin!
    I am trying to make my passcode program run on startup, and I tried this. The program runs correctly, but the RPi still starts up as normal and does not wait for the program to finish. Is there a way for it to not boot into the GUI until the program has finished running (the passcode is correct)?

    ReplyDelete
    Replies
    1. I dont know! Ive had a quick read of the debian lsb init scripts documentation and it suggests that you can put the tag X-Interactive: true into the header to stop the program running in parallel and give the user acces to the console.

      I havent tried it so have a go add # X-Interactive: true just before the ### END INIT INFO line. One word of catuion though... Make sure you have got stuff backed up, a few guys have said that they have been locked out f their pi when experimenting with the boot sequence. But if we dont try we dont learn!

      Delete
  19. i have found this post useful in finding out a way to create a automatic method to connect the pi to a 3g internet via sakis3g script. the details are posted in
    http://goo.gl/w01Bdz.
    thanks for the info

    ReplyDelete
  20. Hi Martin,

    Thank you for being so active in responding to these questions. I have an issue I wasn't able to find answered above (though I may not have recognized the answer - I'm new to linux). I'm running Debian on a Raspberry Pi as a server in my home. (lightweight, but fun to experiment with). I've installed Google Cloud Print and Chromium, and am able to print from my Android devices through the RPi IF I manually start Chromium after boot in an ssh window. (chriomium -- type=service) This actually works without the X environment started.

    The problem (at least in my mind) is that this does not 'complete' and return to a command line prompt. It will just monopolize the session and never return a command prompt.

    Since this command never actually completes, can I use an init.d script?

    Thanks

    ReplyDelete
    Replies
    1. Hi,

      You can run any command in linux in the background by adding a & to the end of the command e.g chromium --type=service & .

      This is known as a daemon. Init.d scripts are designed to run these types of commands. S put an ampersand, &, at the end and all should be good.

      Mart

      Delete
  21. Maby this might seem as a rather strange question, but what programming language is the script written in? It looks like the one you can use in windows to.
    (compeletely new to the Linux and the Raspberry universe.)

    ReplyDelete
    Replies
    1. Er, I would just call it a bash script. If you're used to windows its the equivalent of a command (aka batch) file.

      Delete
  22. Thank you for your nice explanation.
    I just wrote a small tutorial about starting applications at boot time with root privileges in Debian.

    You can find it in here:

    http://cosmolinux.no-ip.org/raconetlinux2/boot.html

    I wish it is useful to someone.

    ReplyDelete
  23. I tried your tutorial but when I try to start the program it says "permission denied". Any ideas how to fix that?

    ReplyDelete
    Replies
    1. Are you using sudo to run your program?

      Delete
  24. Right, massive problem here, I run this to operate a looping python script, which works, however, now I cannot connect via ssh or anything (Connection refused), because whilst this is looping, it seems to stop it from continuing on with the boot phase, is this right? What can I do?!?!?!?!?!?!

    ReplyDelete
  25. You need to put an ampersand & on the end of your command e.g. python myprogram.py & . To make it run in the background. Otherwise the boot sequence will wait for the command to finish.

    ReplyDelete
  26. Great tutorial. I am trying to implement this for a node.js app. If I manually run it it will run just fine, but I can't get it start on boot. Any suggestions?

    ReplyDelete
    Replies
    1. Are you getting an errors? It might be worth writing the output to a file. E.g. node.js ###### >> /home/pi/logfile.txt.

      One thing, make sure you are using full paths in your commands. e.g. /home/pi/file not ~/file or file.

      Delete
  27. This comment has been removed by the author.

    ReplyDelete
  28. Hi, thanks for the post!

    I can get messages that my startup script is running, but I need to run the command as the "pi" user. I have tried runuser, but that does not work. Help would be greatly appreciated

    ReplyDelete
    Replies
    1. Have you tried executing your command with:

      su -c /path/to/command pi

      Delete
  29. Hi Martin,
    Is it possible to run a pi cam to make a time lapse video when the pi boots up, and then shut down when it has finished? What if you want to remove it when you have finished the project? Thanks

    ReplyDelete
    Replies
    1. Sorry I just found your blog about time lapse video. Thanks. Great stuff

      Delete