Search code examples
ubuntuembedded-linuxyoctosystemd

Execute custom script after boot on Yocto-built linux system


I want to execute a script which is present in rootfs everytime system boots to indicate successful update and reset bootloader variables.

For example, the "custom-script" script in present in /etc as:

/etc
----/init.d
-----------custom-script.sh

The first step I did is to install this script in rootfs of the linux image. I have created a recipe in my custom Yocto layer. meta-custom\recipes-support\images layer directory is as follows:

.
├── files
│   ├── custom-script.sh
└── core-image-base.bb

The core-image-base.bb is:

DESCRIPTION = "Install script to Rootfs"
SUMMARY = "Install script to Rootfs and run after boot"
LICENSE = "CLOSED"

SRC_URI = "file://custom-script.sh"

do_install_append() {
    install -d 644 ${D}${sysconfdir}/init.d
    install -m 0755 ${WORKDIR}/custom-script.sh ${D}${sysconfdir}/init.d/custom-script.sh

FILES_${PN} = "${sysconfdir}/init.d"

And in the conf/layer.conf I added IMAGE_INSTALL_append = " core-image-base".

Now I want to execute this script every time the linux system boots (afrer successfully loading rootfs). Can someone please help me to accomplish this? As per my understanding, I can use systemd services to do this and this service should be executed each time the system boots. Any help would be much appreciated.

Thanks in advance.

P.S: I am using Ubuntu 20.04 and this is my first time using systemd services in Yocto with Dunfell version.


Solution

  • In order to make your custom-script.sh execute at Boot time (every time the system boots) using init.d, your custom-script.sh should have the following format

    #!/bin/bash
    # description: Description comes here....
    
    # Source function library.
    . /etc/init.d/functions
    
    start() {
        # code to start app comes here
        # insert any kernel modules prior to 
        # executing/spawning any process that depends
        # on the LKM
    
    }
    
    stop() {
        # code to stop app comes here 
        # example: killproc program_name
        # Kill all the process started in start() function
        # remove any LKM inserted using insmod in start()
    
    }
    
    case "$1" in 
        start)
           start
           ;;
        stop)
           stop
           ;;
        restart)
           stop
           start
           ;;
        status)
           # code to check status of app comes here 
           # example: status program_name
           ;;
        *)
           echo "Usage: $0 {start|stop|status|restart}"
    esac
    
    exit 0 
    

    Then you also need to add a symbolic link to your custom-script.sh in desired run-level directory e.g. /etc/rc3.d or /etc/rc5.d etc.

    To add a symbolic link you need to edit core-image-base.bb (you can use your custom *.bb file as well):

    DESCRIPTION = "Install script to Rootfs"
    SUMMARY = "Install script to Rootfs and run after boot"
    LICENSE = "CLOSED"
    
    SRC_URI = "file://custom-script.sh"
    
    do_install_append() {
        install -d 644 ${D}${sysconfdir}/init.d
        install -m 0755 ${WORKDIR}/custom-script.sh ${D}${sysconfdir}/init.d/custom-script.sh
        ln -sf ../init.d/custom-script.sh ${D}${sysconfdir}/rc4.d/S99custom-script.sh
        ln -sf ../init.d/custom-script.sh ${D}${sysconfdir}/rc4.d/K99custom-script.sh
    }
    
    FILES_${PN} = "${sysconfdir}/init.d"
    

    So, I think you are missing a symbolic link to the desired run-level directory, and maybe you need to write your custom script to have a start() and stop() functions at least.

    If you are using systemd, please refer Enable systemd services using yocto