Distributing and running scripts

Distributing and executing scripts remotely

It is possible to deliver and run complex scripts with qbee. The function used for this is file distribution. Please upload your files or scripts with the qbee file manager and follow the following steps. Then you can deliver and run scripts on any number of embedded remote edge devices:

  1. Upload any files with the file manager. Please note the path.

  2. In the qbee app go to "Configure" and select "System->File Distribution".

    On the device tab select the group or device that is in scope. For more inofrmation please see the configuration management documentation.

  3. Start the actual file distribution definition:

    File Source:


    File Destination:


    This plays out the script to the defined remote devices. If "command to run" is defined this command will be run anytime a new file is distributed.

    When does this script get distributed?

    qbee checks if the file exists in the defined destination. If not it will be transfered. Both the file in the file manager and the file on the machine have a checksum. If the file manager file is replaced a new file distribution happens. Likewise, if the file on the target machine is changed or deleted this will also trigger a new file download and the changes will be overwritten with the original file from the file manager.

    Please check that the file distribution logic does not work against any other process

    This behaviour is very useful. But if a process on the target device is working against a file that is watched by qbee file distribution this can cause continuous file downloads. This will be seen in the logs.

  4. In order to do anything with the script the optional "Command to run" function can be used. Here commands can be chained using && and this opens up for a lot of options. In this case we do a simple operations:

    Run the script in the bash shell with according permissions by using the following in "command to run":

       bash /usr/local/bin/cpu_temp.sh > /dev/null 2>&1 &

    This runs the script in the background and the appendix > /dev/null 2>&1 & pipes bash output to /dev/null. It is also possible to use "python" or "python3" to run a python file. In addition, it is possible to run this with the rights of another user sudo -u user in order to avoid running a script as root. But then it needs to be made executable:

        chmod 755 /home/pi/cpu_temp.sh && sudo -u pi /home/pi/cpu_temp.sh > /dev/null 2>&1 &

    The "command to run" always runs as root user and with root context. Therefore you need to specify if you want to execute things as a different user or expect different environment variables.

    These commands will be triggered any time the file is distributed again

    If the file in the file manager or the file on the target is replaced or changed these commands get run again. This means that for a regular device this script usually only runs once. If you want to trigger it again you can learn how to do this here.

    It is possible to run the script with bash or alternatively you can work with chmod to make the script executable and then run it. See below:

    When using chmod please read this!

    If a script or a file is distributed the qbee agent will try to adjust the ownership rights according to the folder used. Sometimes additional chown or chmod commands are needed. If no templating is used this does not pose a problem. If templating is used please DO NOT chmod the file that is expanded as template. Below in point 5 you can see how you can get around this for scripts. If you need to do chmod on a config file you can copy it with cp or use something like this install -C -m 700 /some/temporary/collection/location/monitrc /etc/monit/monitrc.

    Simple script distribution:


  5. (Optional) It is possible to parametrize a scripts from the qbee UI. This is done by working with key-value pairs that are used as templates. In the following example we use a script that can control the Node-Red service. It should be able to start,stop,restart and disable or enable the service. In order to make this work you do the following:

    Create a script file and source a file with the templating variables. The variable $STATE contains the specific command ("restart").


    #!/usr/bin/env bash
    source /home/pi/node-red-service.conf
    sudo systemctl $STATE nodered.service

    This script is uploaded to the qbee file manager with the name node-red-service.js.

    Then the template file is created and uploaded as node-red-service.tmpl.


    # node-red service template for node-red-service script
    # run once trigger {{epoch}}
    # use start,stop,restart, disable, enable
    export STATE="{{service-state}}"

    This works in a way that variables can be exported and then they get sourced into the script. Key-value pairs that should be available in the UI are characterized through Mustache notation with double curly brackets {{key}}.

    File endings: .tmpl and .conf

    Template files are uploaded with a .tmpl ending and then in the file distribution it is defined into which name they expand. In this case the node-red-service.tmpl file will be expanded on the device into node-red-service.conf with the mustache notation replaced by the key-value pairs from the UI

    So the node-red-service.conf file that will end on the device looks as follows:


    # node-red service template for node-red-service script
    # run once trigger 1598358209
    # use start,stop,restart, disable, enable
    export STATE="restart"

Since both the template file and the script file are part of a single file distribution if any of those changes the command to run will be triggered and executed. So any change in the key-values will trigger the script to run. The "command to run" makes the script executable and then runs it:

chmod 755 /home/pi/node-red-service.sh && sudo -u pi /home/pi/node-red-service.sh > /dev/null 2>&1 &

Why is there a {{epoch}} in the template comment and in the UI?

The qbee agent monitors the checksum of the file. If a key-value change is detected in the UI a new .conf file is written as the existing .conf file on the device is different than the new expanded .conf file on the server. Only if a file change occurs the "command to run" is triggered. So the systemctl in the script is only run when the STATE would change from "restart" to something else. This would make it impossible to run restart two times after another. The trick here is to put in the current epoch time (or any other unique variable) and just change that. Then a change is detected and the script is run. Thus we can run "restart" any number of times.