Skip to content

HOWTO Custom Commands



Custom Commands in IGEL OS 12

Custom commands are executed at specific points of the system startup process.

Since multiple profiles with custom commands can overwrite each other, a method for combining custom commands is needed.



Method for Managing Custom Commands

A profile can be setup with a wrapper script to look for custom command scripts. The wrapper script looks for related scripts.

  • Use UMS Files to deploy the scripts to IGEL OS
  • Create profile for Custom Commands that call the wrapper scripts

Final desktop command:

1
System --> System Customization --> Custom Commands --> Desktop --> Final desktop command --> /wfs/cc-desktop-3fdc.sh &


Desktop

Desktop Execution Times Description Basename of Scripts
Desktop initialization Executed during the boot process, before the X server is started cc-desktop-1ini-
Before desktop start The command is executed before the windowmanager and the autostart sessions are started. cc-desktop-2bds-
Final desktop command The command is executed after each user logon and desktop restart cc-desktop-3fdc-
Name Script
Wrapper - Final desktop command LINK to script
Sort Desktop Icons LINK to script
Add CUPS Network Printers LINK to script
USB Always On LINK to script
Set Permissions on Apache Webdav Folder LINK to script
Set Island.io as default browser LINK to script
How to remove --> Currently being shadowed - Disconnect LINK to script
AVD Post Session Logoff LINK to script
Reboot when lock screen running for WAIT_AFTER_START time LINK to script
Set terminal window to black background LINK to script

  • Wrapper - Final desktop command
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/bin/bash
#set -x
#trap read debug

#
# Version: 
# Run all Final Desktop Commands
#
# Custom Commands: Desktop: Final Desktop Command
#

ACTION="cc-desktop-3fdc"

# Send all stdout/stderr from this script to journald/syslog
exec > >(logger -t "$ACTION") 2>&1

echo "Starting"

# run all final desktop scripts
ls /wfs/cc-desktop-3fdc-*.sh | while read LINE
  do
  echo "Starting: ${LINE}"
  $LINE &
  done

echo "Finished"

exit 0

  • Add CUPS Network Printers
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#!/bin/bash
#set -x
#trap read debug

#
# Version:
# Add CUPS network printers
#
# Custom Commands: Desktop: Final Desktop Command
#

ACTION="cc-desktop-3fdc-cupsnetworkprinters"

# Send all stdout/stderr from this script to journald/syslog
exec > >(logger -t "$ACTION") 2>&1

COUNT=1

echo "Starting"

if [ ! -e /usr/lib/cups/backend/snmp ]; then
  echo "ERROR: CUPS not installed. Please install CUPS app"
fi

# create network printers from /usr/lib/cups/backend/snmp
/usr/lib/cups/backend/snmp | while read LINE
  do
    URI=ipp://`echo "${LINE}" | awk --field-separator " " '{print $2}' | sed -e 's|^.*//||' -e 's|[:/].*||'`/ipp/print
    lpadmin -p wifiprinter${COUNT} -E -v $URI -m everywhere
    if [ ${COUNT} -eq 1 ]; then
      lpoptions -d wifiprinter${COUNT}
    fi
    COUNT=$COUNT+1
  done

echo "Finished"

exit 0

  • USB Always on (Printer, Scanner, etc.)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/bin/bash
#set -x
#trap read debug

#
# Version: 
# USB always on (Printer, Scanner, etc.)
# System > Firmware Customization > Custom Commands > Desktop
#
# Custom Commands: Desktop: Final Desktop Command
#

ACTION="cc-desktop-3fdc-usb-power"

# Send all stdout/stderr from this script to journald/syslog
exec > >(logger -t "$ACTION") 2>&1

echo "Starting"

echo on | tee /sys/bus/usb/devices/*/power/level > /dev/null

echo "Finished"

exit 0

  • Set Permissions on Apache Webdav Folder
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#!/bin/bash
#set -x
#trap read debug

#
# Version: 
# Set Permissions on /var/www/webdav
#
# Custom Commands: Desktop: Final Desktop Command
#

# set up logging function
ACTION="apache2_set_permissions"
function log {
    logger -it "$ACTION" "$1"
}

log "Starting $ACTION"
chown -R www-data:www-data /services_rw/apache/var/www/webdav
chmod -R 775 /var/www/webdav/* /services_rw/apache/var/www/webdav
log "Ending $ACTION"

  • Sort Desktop Icons
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#!/bin/bash
#set -x
#trap read debug

#
# Version: 
# Sort Desktop Icons
#
# Custom Commands: Desktop: Final Desktop Command
#

# set up logging function
ACTION="sort_icons"
function log {
    logger -it "$ACTION" "$1"
}

# function to sort icons
function sort_icons {
    # iterate over each .desktop file in the directory
    for file in "$desktop_dir"/*.desktop; do
        # extract the file name without numeric prefix
        file_name="$(basename $file .desktop | sed 's/^[0-9]*_//')"
        # read the session name from the .desktop file
        session_name="$(grep -Po "(?<=^Name=).*" $file | sed -e 's/ /_/g')"
        # extract the app name from the file name
        app_name="$(echo $file_name | sed 's/_[0-9]*$//')"
        # extract the session ID from the filename
        session_id="$(basename $file .desktop | grep -Po "\d+$")"
        # construct the new filename based on the sorting format
        if [ "$sorting_format" -eq 1 ]; then
            new_filename="${session_name}_${app_name}_${session_id}.desktop"
        elif [ "$sorting_format" -eq 2 ]; then
            new_filename="${app_name}_${session_name}_${session_id}.desktop"
        else
            log "Invalid sorting format specified. Exiting."
            exit 1
        fi
        # check if the filename is already in the correct format
        if [[ ! "$file" =~ "${session_name}" ]]; then
        https://kb.igel.com/en/igel-apps/current/citrix-workspace-app    if [[ "$file" =~ "cwa" ]]; then
                log "Skipping ${file##*/} as cwa shortcuts should not be renamed"
            else
                # rename the .desktop file
                mv "$file" "$desktop_dir/$new_filename"
                log "Renamed ${file##*/} to $new_filename"
            fi
        else
            log "Skipping ${file##*/} as it is already in the correct format"
        fi
    done
}

log "Starting sort_icons script"

# define the directory containing the .desktop files
desktop_dir="/userhome/Desktop"

# specify the sorting format:
# set to 1 for "sessionname_appname_sessionid.desktop"
# set to 2 for "appname_sessionname_sessionid.desktop"
sorting_format=1

# execute the sorting function at the start of the script
sort_icons

# monitor for changes in the directory
while inotifywait -qq -e create -e modify -e delete "$desktop_dir"; do
    # execute the sorting function inside the loop
    sort_icons
done

  • Set Island.io as the default browser
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/bin/bash
#set -x
#trap read debug

#
# Version:
# Set Island.io as the default browser
#
# Custom Commands: Desktop: Final Desktop Command
#

ACTION="cc-desktop-3fdc-island"

# Send all stdout/stderr from this script to journald/syslog
exec > >(logger -t "$ACTION") 2>&1

echo "Starting"

if [ -e /services/island/usr/bin/island-browser-stable ]; then
  echo "APT FOUND: /services/island/usr/bin/island-browser-stable found"
  echo "Set Default Browser to Island"
  xdg-settings set default-web-browser island-browser.desktop
  echo "Clear Island Browser CacheStorage"
  rm -rf /userhome/.config/island/Default/Service\ Worker/CacheStorage/*
else
  echo "APT NOT FOUND: /services/island/usr/bin/island-browser-stable not found"
fi

echo "Finished"

exit 0

  • UMS Shadow to device -- How to remove --> Currently being shadowed - Disconnect
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/bin/bash
#set -x
#trap read debug

#
# Version:
# UMS Shadow to device -- How to remove --> "Currently being shadowed - Disconnect"
#
# Custom Commands: Desktop: Final Desktop Command
#

ACTION="cc-desktop-3fdc-remove-being-shadowed"

# Send all stdout/stderr from this script to journald/syslog
exec > >(logger -t "$ACTION") 2>&1

echo "Starting"

sed -ie '/vncmessage/d' /config/vncserver/x11vnc0

echo "Finished"

exit 0

  • AVD Post Session Logoff
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#!/bin/bash
#set -x
#trap read debug

#
# Log off device after AVD ends
#

PROCESS_NAME="igelrdp3-avd"
# seconds between checks
CHECK_INTERVAL=5

ACTION="cc-desktop-3fdc-avd-post-session_logoff"

# Send all stdout/stderr from this script to journald/syslog
exec > >(logger -t "$ACTION") 2>&1

echo "Started"

while true; do
  # Check if the process is running
  PID=$(pgrep -x "$PROCESS_NAME")
  if [ -n "$PID" ]; then
    echo "Found AVD Session" $PID
    while pgrep -x "$PROCESS_NAME" > /dev/null; do
      echo "$PROCESS_NAME is still running..."
      sleep $CHECK_INTERVAL
    done
    #logoff
    echo "AVD Session Ended - Now Logoff" $PID
    logoff
  fi
  sleep $CHECK_INTERVAL
done

  • Reboot after lock screen running for WAIT_AFTER_START
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#!/bin/bash
#set -x
#trap read debug

#
# Version:
# Reboot when lock screen running for WAIT_AFTER_START
#
# Custom Commands: Desktop: Final Desktop Command
#

ACTION="cc-desktop-3fdc-reboot-after-lock-screen"

# Send all stdout/stderr from this script to journald/syslog
exec > >(logger -t "$ACTION") 2>&1

PROCESS_NAME="lightdm-igel-greeter"
CHECK_INTERVAL=5    # seconds between checks
WAIT_AFTER_START=300  # 5 minutes in seconds
#WAIT_AFTER_START=10  # 5 minutes in seconds

echo "Starting"

while true; do
    # Check if the process is running
    PID=$(pgrep -f "$PROCESS_NAME")
    echo $PID

    if [ -n "$PID" ]; then
        echo "[$(date)] $PROCESS_NAME started with PID $PID. Waiting $WAIT_AFTER_START seconds..."
        sleep "$WAIT_AFTER_START"

        # Recheck if process is still running
        PID=$(pgrep -f "$PROCESS_NAME")
        if [ -n "$PID" ]; then
            echo "[$(date)] $PROCESS_NAME still running. Reboot ..."
            pkill -f ${PROCESS_NAME}
            reboot
        fi
    fi

    sleep "$CHECK_INTERVAL"
done

  • Set terminal window to black background
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#!/bin/bash
#set -x
#trap read debug

#
# Version: Tue Mar 17 10:17:19 AM MDT 2026
#
# Custom Commands: Desktop: Final Desktop Command
#

ACTION="cc-desktop-3fdc-terminal"

# Send all stdout/stderr from this script to journald/syslog
exec > >(logger -t "$ACTION") 2>&1

echo "Starting"

if [ -e /wfs/terminalrc ]; then
  echo "Terminal settings found and removed"
  rm -f /wfs/terminalrc
fi

cat << "EOF" > /wfs/terminalrc
ColorForeground=#FFFFFF
ColorBackground=#000000
ColorCursor=#FFFFFF
ColorPalette=#000000;#AA0000;#00AA00;#AA5500;#0000AA;#AA00AA;#00AAAA;#AAAAAA;#555555;#FF5555;#55FF55;#FFFF55;#5555FF;#FF55FF;#55FFFF;#FFFFFF
EOF

chmod a+r /wfs/terminalrc
mkdir -p /userhome/.config/xfce4/terminal
chown -R user:users /userhome/.config/xfce4
ln -svf /wfs/terminalrc /userhome/.config/xfce4/terminal/terminalrc


echo "Finished"

exit 0


Base

Base Execution Times Description Basename of Scripts
Final initialization command command is executed during boot, after the initialization cc-base-4fic-
Name Script
Wrapper - Final initialization command LINK to script
Link /media/hostname to /media mount point (GParted) LINK to script
Link Shokz fix for 12.8+ LINK to script

  • Wrapper - Final Base initialization command
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/bin/bash
#set -x
#trap read debug

#
# Version: 
# Run all Final Base Initialization Commands
#
# Custom Commands: Base: Final Initialization Command
#

ACTION="cc-base-4fic"

# Send all stdout/stderr from this script to journald/syslog
exec > >(logger -t "$ACTION") 2>&1

echo "Starting"

# run all final desktop scripts
ls /wfs/cc-base-4fic-*.sh | while read LINE
  do
  echo "Starting: ${LINE}"
  $LINE &
  done

echo "Finished"

exit 0

  • Link /media/hostname to /media mount point (GParted)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/bin/bash
#set -x
#trap read debug

# 
# Custom Commands: Base: Final Initialization Command
#
# After using GParted to format rest of desk
#
# Link /media/hostname to /media mount point
# 

ACTION="cc-base-4fic-linkmediadisk"

# Send all stdout/stderr from this script to journald/syslog
exec > >(logger -t "$ACTION") 2>&1

MOUNTPOINT=$(mount | grep "/media" | cut -d " " -f 3)
NEWLINK="/media/$(hostname)"

# exit if no media mount point
if [ "${MOUNTPOINT}" == "" ]; then
  echo "No media mount point to link to."
  exit 0
fi

if [ -L ${NEWLINK} ]; then
  echo "Unlinking ${NEWLINK}"
  unlink ${NEWLINK}
elif [  -d ${NEWLINK} ]; then
  echo "${NEWLINK} is a directory. Not linking ${NEWLINK} to ${MOUNTPOINT}"
  exit 1
fi

ln -svf ${MOUNTPOINT} ${NEWLINK}

  • Shokz shutdown fix found in 12.8.0-12.8.4 12.9.0
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/bin/bash
#set -x
#trap read debug

# 
# Custom Commands: Base: Final Initialization Command
#
# Shokz shutdown fix found in 12.8.0-12.8.4 12.9.0
#

ACTION="cc-base-4fic-shokz"

# Send all stdout/stderr from this script to journald/syslog
exec > >(logger -t "$ACTION") 2>&1

echo "Starting"

# Get IGEL OS version from /etc/os-release
IGEL_VERSION=$(sed -n 's/^VERSION="\([^"]*\)"/\1/p' /etc/os-release)

MIN_VERSION="12.8.0"

echo "IGEL OS version: $IGEL_VERSION"

if [ "$(printf '%s\n' "$MIN_VERSION" "$IGEL_VERSION" | sort -V | head -n1)" = "$MIN_VERSION" ]; then
    echo "IGEL OS version is greater than or equal to 12.8.x"
    printf '%s\n' 'ACTION!="remove", SUBSYSTEM=="input", KERNEL=="event*", ENV{ID_VENDOR_ID}=="3511", ENV{ID_MODEL_ID}=="2b0a|2b1e|2f06", ENV{ID_INPUT_KEY}="0"' > /etc/udev/rules.d/69-shokz-no-power-switch.rules
    udevadm control --reload-rules
else
    echo "IGEL OS version is less than 12.8.x"
    echo "Shokz fix not required for IGEL OS < 12.8.x"
    printf '%s\n' 'ACTION!="remove", SUBSYSTEM=="input", KERNEL=="event*", ENV{ID_VENDOR_ID}=="3511", ENV{ID_MODEL_ID}=="2b0a|2b1e|2f06", ENV{ID_INPUT_KEY}="0"'
fi

echo "Finished"