Automatic Scripting at Boot-Up

Obviously, there’s a huge power in being able to have programs start automatically at boot with Edison. There’s a “real” linux style way to do it, and then there’s the hacked Arduino style way. I’ll go over both in this posting.

Linux: Running Scripts at System Start-Up

There are a few different ways to do this, but on Edison I found that the easiest way is using the /etc/init.d directory. There are many references out there for why and how this works, a good one can be found here. If this is your first time using init.d for start-up scripts, you’re going to have to first create the directory:

root@edison:~# cd /etc

root@edison:/etc# mkdir init.d

Now switch into that directory, well, so that you can stay aligned with this post :)

root@edison:/etc# cd init.d/

Next, we’re going to create a bash script in this folder that contains our boot commands. In this case, we’re going to be automating Edison’s wifi connection. This is a natural extension of the post here, where we setup the configuration that we’re going to be automating. If you’ve not yet got wifi going on Edison, you’re gonna wanna check that out.

In any case, open your favorite text editor and create the script wifi.sh:

root@edison:/etc/init.d# vi wifi.sh

Paste the following contents into the script

Note: This post is outdated. You no longer have to use this script to get your Edison online, simply run “configure_edison –wifi” to setup your wireless connection. However, the automatic scripting at start-up approach will work with any shell script you paste into here. 

#!/bin/sh

wpa_supplicant -B -Dnl80211 -iwlan0 -c/etc/wpa_supplicant/wpa_supplicant.conf

busybox udhcpc -i wlan0

 

Really, it’s just the two commands we landed on at the end of our wifi tutorial.

Go ahead and make the script executable by changing the permissions with chmod.

root@edison:/etc/init.d# chmod +x /etc/init.d/wifi.sh
root@edison:/etc/init.d# chmod +x wifi.sh

At this point, it might be useful to check that our script actually works before we continue trying to make it run automatically. Run the script and watch for the output as listed below.

root@edison:/etc/init.d# ./wifi.sh 
Successfully initialized wpa_supplicant
udhcpc (v1.22.1) started
Sending discover...
Sending discover...
Sending discover...
Sending select for 192.168.0.34...
Lease of 192.168.0.34 obtained, lease time 86400
/etc/udhcpc.d/50default: Adding DNS 192.168.0.1
/etc/udhcpc.d/50default: Adding DNS 205.171.2.25

 

Just to be sure it’s actually working, go ahead and ping google.

root@edison:/etc/init.d# ping google.com
PING google.com (74.125.224.40): 56 data bytes
64 bytes from 74.125.224.40: seq=0 ttl=57 time=43.711 ms
64 bytes from 74.125.224.40: seq=1 ttl=57 time=60.668 ms
^C
--- google.com ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 43.711/52.189/60.668 ms

 

Lookin’ good!

Now, to make sure this script is executed every time linux boots, issue the following command and wait for the return shown below

root@edison:/etc/init.d# update-rc.d wifi.sh defaults
Adding system startup for /etc/init.d/wifi.sh

 

Basically, this command creates symbolic links to this script in your default rc.d folders 0 through 6 (hence the flag “defaults”). You can check the creation of these folders and directories with a little ls action:

root@edison:~# ls -l /etc/rc?.d/*wifi*
lrwxrwxrwx    1 root     root            17 Sep 10 19:29 /etc/rc0.d/K20wifi.sh -> ../init.d/wifi.sh
lrwxrwxrwx    1 root     root            17 Sep 10 19:29 /etc/rc1.d/K20wifi.sh -> ../init.d/wifi.sh
lrwxrwxrwx    1 root     root            17 Sep 10 19:29 /etc/rc2.d/S20wifi.sh -> ../init.d/wifi.sh
lrwxrwxrwx    1 root     root            17 Sep 10 19:29 /etc/rc3.d/S20wifi.sh -> ../init.d/wifi.sh
lrwxrwxrwx    1 root     root            17 Sep 10 19:29 /etc/rc4.d/S20wifi.sh -> ../init.d/wifi.sh
lrwxrwxrwx    1 root     root            17 Sep 10 19:29 /etc/rc5.d/S20wifi.sh -> ../init.d/wifi.sh
lrwxrwxrwx    1 root     root            17 Sep 10 19:29 /etc/rc6.d/K20wifi.sh -> ../init.d/wifi.sh

 

By default, folders 0,1,6 are reserved for kill actions, which is why the symlink gets the prefix “K”. Similarly, folders 2,3,4,5 are reserved for start actions and are given the prefix “S”. The number 20 follows this prefix letter and defines the process hierarchy. Any process with priority number lower than 20 will run before this and anything higher than 20 will be executed after. For reference, init.d scripts are executed last in terms of kernel boot-up with this heirarchy. A nice description of the boot order can be found here.

Just a note: The whole “S/K” prefix thing is completely irrelevant here. We didn’t set our script to run certain commands on start or kill, we put our commands straight in the body and thus every command will be executed every time. For an example of how to explicitly program start, kill, and always actions, see here.

In any case, the creation of all the rcX.d folders makes it seem like everything was successful. Let’s reboot and see if it worked!

root@edison:/etc# reboot

Connection to 192.168.2.15 closed by remote host.

Connection to 192.168.2.15 closed.

Wait a minute and ssh back in (if you’re adventurous, you can try and do it wirelessly instead of the usb dongle).

smoyerma-mac02:~ smoyerma$ ssh root@192.168.2.15

Obviously, if you ssh’ed in wirelessly then you don’t have to check, it just worked! But, if you ssh’ed in via the dongle, you should see wpa_supplicant running as a process

root@edison:~# top

top

And you should be able to ping google (or whatever you like!):

 

root@edison:~# ping google.com

PING google.com (74.125.224.37): 56 data bytes

64 bytes from 74.125.224.37: seq=0 ttl=56 time=32.892 ms

64 bytes from 74.125.224.37: seq=1 ttl=56 time=47.575 ms

^C

--- google.com ping statistics ---

2 packets transmitted, 2 packets received, 0% packet loss

round-trip min/avg/max = 32.892/40.233/47.575 ms

 

Boom! Your SD card sized computer now accesses the internet like a pro!

A note for future use: Once the symlinks are created in the rcX.d folders, you don’t need to re-create them when you edit wifi.sh. In fact, you can add more bash commands to wifi.sh or even call other external, executable scripts from within this file. This way, you can start bluetooth, logging, webservers, etc. all on boot-up automatically. This is a much more expandable and lasting process that the Arduino example I’ll show below. 

 

Arduino: Running Scripts at System Start-Up

So, the following is kind of a cheat for home hackers who don’t really want to delve into the linux side of development. Let me just say in advance, there’s nothing wrong it a good work-around :)

So, Edison (as well as Galileo and Gen2) runs on an Arduino software stack that is separate from the base Arduino IDE. The download for it can be found here. It’s got an identical look and feel to the original IDE, but because the pins, base libraries, and compile are all done a bit differently, it’s been packaged separately.

A note: I’m not the most organized person in the world, but even I find it a bit annoying to see two identical icons in my taskbar if I’ve developing on Intel’s Arduino and the original Arduino platforms simultaneously. While the icon is a hassle to change, it’s easy enough to change the name so that a mouse-over reveals which is which. I’ve changed my Intel version to “EdisonArduino” on my own computer. Any name will work, but I point this out because I might use it in my jargon from here on out.

In any case, the way Edison works with EdisonArduino is that your Arduino code is compiled for your specific system (Edison vs Galileo), converted to an executable file called “sketch.elf”, transferred to Edison /sketch directory via ssh on the specified port, and then executed on Edison. The most recent sketch.elf file is also executed every time Edison boots, which is where the  magic happens for us in this tutorial.

EdisonArduino has the same structure as normal Arduino code. The blank template looks just like:

EdisonArduino

Note that in the bottom right corner you can see my system and my serial port. These can be selected from the dropdown “Tools” menu.

If you’re not familiar with Arduino, the setup() function is run exactly once when the program is initiated and the loop function is run over and over again until forever. For our purposes, we only need to exploit the setup() function. EdisonArduino, being a full Linux stack, allows you to make command line calls from the Arduino code using the command system() (if you code in c or c++, this should look familiar). Alter your EdisonArduino code to look like:

void setup() {
// put your setup code here, to run once:
system("wpa_supplicant -B -Dnl80211 -iwlan0 -c/etc/wpa_supplicant/wpa_supplicant.conf");
system("busybox udhcpc -i wlan0");
}

void loop() {
// put your main code here, to run repeatedly:
}

And that’s it. Upload this to Edison with a Command+U or clicking the right arrow at the top. Every time Edison boots it will now start wifi.

Note that if you upload future scripts and forget to include this, then all of a sudden your wifi will go down the next time Edison reboots. That’s kind of annoying, which is why I prefer solution 1 above. Once that’s implemented, there’s no upkeep anymore.

You could also do a combination of the two solutions, create the script “wifi.sh”, change the permissions to make it executable, and then call it from Edison the same way we called these two commands above, but seriously?! Now that’s just silly :)

 

Posted in Edison, Tech
9 comments on “Automatic Scripting at Boot-Up
  1. Mamallan says:

    I am able to connect the wifi when i try to execute your Shell script. When i reboot after I add the script to startup script, I got error

    [FAILED] Failed to start wifi.service.
    See ‘systemctl status wifi.service’ for details.

    root@Edison:~# systemctl status wifi.service
    ● wifi.service
    Loaded: loaded (/etc/init.d/wifi.sh)
    Active: failed (Result: exit-code) since Fri 2014-11-21 05:51:15 UTC; 1min 7s ago
    Process: 199 ExecStart=/etc/init.d/wifi.sh start (code=exited, status=203/EXEC)

    Nov 21 05:51:15 Edison systemd[1]: wifi.service: control process exited, co…03
    Nov 21 05:51:15 Edison systemd[1]: Failed to start wifi.service.
    Nov 21 05:51:15 Edison systemd[1]: Unit wifi.service entered failed state.
    Hint: Some lines were ellipsized, use -l to show in full.

    Please help me

  2. Ted Ellison says:

    Thank you so much for this post! I hesitate to tell you how long I have been searching for this information. Your simple to follow explanation was so very helpful.
    Minor detail – didn’t recognize, at first that you changed directories (to etc/..) totally my ignorance.

    Thanks gain,

    Ted

  3. Sihui Han says:

    I have tried to the second method, using the EdisonArduino, but I got the errors such as “wpa_supplicant not declared in this scope”. Do I need to include some lib to make it work?

    Thanks,

    • Stephanie Moyerman says:

      This is my fault. The strings inside of the system call should be in double quotes!

      system(“busybox udhcpc -i wlan0”);
      system(“echo 123 >> out.txt”);

      I’ve changes the post to reflect this. Thanks for catching!

  4. Ignacio says:

    This worked great. But what If I wanted to remove the the script from auto starting what would be the steps to do so?

  5. Mike R says:

    So, funny thing about using the Arduino approach; you don’t even have to actually use Arduino code at all. You can just make any executable script and name it sketch.elf and put it in the /sketch directory. Of course you still lose it if you do program the baord via Arduino, but if you dont what to program that way and like your shell script, it will work just as well!

  6. pullova says:

    Cool Tutorial, helped me a lot, thanks :-)

1 Pings/Trackbacks for "Automatic Scripting at Boot-Up"
  1. […] – /etc/wpa_supplicant.conf – auto-initialization file /etc/init.d/wifi (source): […]

Leave a Reply

Your email address will not be published. Required fields are marked *

*