Running a Script On Startup

The default Linux image on the Intel Edison can be configured to run a script on startup using three methods - directly, by creating a startup service, or using an autologin script. The direct method is the simplest but least flexible. The service method allows for more customisation and timing control, and the autologin method is best suited for systems which only need to run a script if no user is connected.

Direct method

The simplest method for running a script on startup is as follows:

  1. If the init.d directory does not exist, create it first using:

    mkdir /etc/init.d
    
  2. Ensure the script file to be run (“yourscript.sh” in this tutorial) is executable and copy it into /etc/init.d using:

    chmod 755 yourscript.sh
    cp yourscript.sh /etc/init.d
    
  3. Update the rc daemon with the details of the script using:

    update-rc.d yourscript.sh defaults
    

The script will now run when the Edison starts. The timing can vary slightly but the script will generally run around the time the network services are initialised, several seconds before the boot process finishes.

To remove the script from the startup sequence, use:

update-rc.d -f yourscript.sh remove

Service method

Creating a service allows for more precise control over when the script is run. It also allows a program to be automatically restarted when closed.

  1. Create a .service file with the desired settings using this template (replace the text in {braces} with the desired settings)

    [Unit]
    Description={service name}
    After={service to start after, eg. xdk-daemon.service}
    
    [Service]
    ExecStart={/path/to/yourscript.sh}
    Restart=always
    RestartSec=10s
    Environment=NODE_ENV=production
    
    [Install]
    WantedBy=multi-user.target
    

    The file must be saved with a .service file extension. It will be referred to as yourservice.service in this example.

  2. Copy the service file into the system services directory using:

    cp yourservice.service /lib/systemd/system
    
  3. Refresh systemctl so that it recognises your new service:

    systemctl daemon-reload
    
  4. Enable your service so that it runs on boot:

    systemctl enable yourservice.service
    

The service will now run your script when the Edison starts, after the service specified in the “After” section of the .service file. If your script terminates, the service will restart and run your script again.

To remove the script from the startup sequence, use:

systemctl disable yourservice.service

Autologin method

The autologin method is suitable for systems where a script needs to be run if the system is headless (no users / SSH sessions connected). This method is based on the guide here: http://gallinazo.flightgear.org/software/setting-up-autologin-on-a-gumstix/

  1. Create a file named autologin.c with the following contents:

    #include <unistd.h>
    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
               int nrv = 0;
               FILE* fptr = 0;
               char user[64];
    
               // clear buffer
               memset(user,'\0',64);
    
               // open autologin profile file
               fptr = fopen("/etc/autologin.profile\0","r\0");
    
               // make sure the file exists and was opened
               if (fptr != 0)
               {
                               // the return value from fscanf will be 1 if the autologin profile name is read correctly
                               nrv = fscanf(fptr,"%s\0",user);
               }
    
               // only autologin if the profile name was read successfully,
               // otherwise show the regular login prompt
               if (nrv > 0)
                               nrv = execlp("login\0","login\0","-f\0",user,0);
               else
                               nrv = execlp("login\0","login\0","\0",0,0);
    
               return 0;
    }
    
  2. Compile the code and install it to the sbin folder using:

    gcc autologin.c -o /sbin/autologin
    
  3. Create an autologin profile using:

    echo "root" > /etc/autologin.profile
    
  4. Set up the systemd configuration:

    cp /lib/systemd/system/serial-getty@.service /etc/systemd/system/autologin@.service
    ln -sf /etc/systemd/system/autologin@.service /etc/systemd/system/getty.target.wants/serial-getty@ttyO2.service
    
  5. Edit the tty service to run your autologin program:

    cd /etc/systemd/system/getty.target.wants/
    vi serial-getty@ttyO2.service
    

    Change this:

    ExecStart=-/sbin/agetty -s %I 115200
    

    To this:

    ExecStart=-/sbin/agetty -n -l /sbin/autologin -s %I 115200
    
  6. Create another file named pressanykey.c with the contents:

    1. Create a file named autologin.c with the following contents:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>
    #include <termios.h>
    #include <unistd.h>
    
    int kbhit(void)
    {
            fd_set rfds;
            struct timeval tv;
            int retval;
            struct termios term, oterm;
            int fd = 0;
            tcgetattr( fd, &oterm );
            memcpy( &term, &oterm, sizeof(term) );
            cfmakeraw(&term);
            tcsetattr( fd, TCSANOW, &term );
            /* Watch stdin (fd 0) to see when it has input. */
            FD_ZERO(&rfds);
            FD_SET(0, &rfds);
            /* Wait up to one seconds. */
            tv.tv_sec = 1;
            tv.tv_usec = 0;
            retval = select(1, &rfds, NULL, NULL, &tv);
            /* Don't rely on the value of tv now! */
            tcsetattr( fd, TCSANOW, &oterm );
            return(retval);
    }
    
    int mygetch( ) {
            struct termios oldt, newt;
            int ch;
            tcgetattr( STDIN_FILENO, &oldt );
            newt = oldt;
            newt.c_lflag &= ~( ICANON | ECHO );
            tcsetattr( STDIN_FILENO, TCSANOW, &newt );
            ch = getchar();
            tcsetattr( STDIN_FILENO, TCSANOW, &oldt );
            return ch;
    }
    
    int main(int argc, char **argv) {
            int count = 5;
    
            if ( argc > 1 ) {
            int tmp = atoi(argv[1]);
            if ( tmp > 0 ) {
                    count = tmp;
            }
            }
    
            printf("Press any key ... ");
            fflush(stdout);
    
            while ( count >= 0 ) {
            printf("%d ", count);
            fflush(stdout);
    
            //int result = mygetch();
            if ( kbhit() ) {
                    return 1;
            }
            //sleep(1);
            count--;
            }
    
            return 0;
    }
    
  7. Compile the code and install it to the sbin folder using:

    gcc pressanykey.c -o /sbin/pressanykey
    
  8. Create a file in /etc/ named autologin.profile containing (add your script to the path):

    /sbin/pressanykey 5
    if [ $? != 0 ]; then
            echo "Starting interactive shell"
    else
            echo "Continuing with default"
            /path/to/myscript.sh
    fi
    

The Edison will now present you with a 5 second countdown on startup. If a key is pressed, you will be able to log in to the system normally and if not, the system will run your script.