Skip to content

Create usbip_systemd_monitor.sh #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 148 additions & 0 deletions usbip_systemd_monitor.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
#!/bin/bash

# Enancement for https://github.com/psct/usbip
# This utility expects the systemd dynamic unit files
# provided at https://github.com/psct/usbip
#
# Issue/Problem to solve:
# When the usbipd server is rebooted;
# When the USB device at usbipd server is removed (and re-inserted)
# The binding by uspip client with the server USB device gets disconnected
# The binding does not auto recover
#
# This utility will ONLY restore the binding for
# dynamic unit files which have been started
# Unit files which have not been enabled/started, will be ignored
#
# dynamic unit file example:
# usbip@pi4:0403:6001.service
#
# USAGE:
# Call this script on a regular basis, eg from a cron.d job (every minute)
# /etc/cron.d/uspib_monitor:
# PATH=/bin:/usr/bin:/sbin:/usr/sbin !!IMPORTANT, add in cron.d file!!
# * * * * * root /<path to script>/usbip_systemd_monitor

scriptname=`basename "$0"`
logger -t ${scriptname} "START ${scriptname[$BASHPID]} PID = $BASHPID"

# Find all dynamic unit files with pattern like
# usbip@usbipdserver:2341:8036.service
# and store in serviceArray
# Ignore duplicates
# systemctl --no-pager --type=service --state=failed | grep usbip@
# systemctl --no-pager --type=service --state=active | grep usbip@

# counter for array
arrayindex=0

# Store retrieved info on unit files in 3 different arrays:
# 1. servicesArray: Full name of dynamic unit file, e.g. "usbip@pi4:0403:6001.service"
# 2. deviceID: USB device id, e.g. "0403:6001"
# 3. usbipdServer, e.g. "pi4"


# Query usbip@ unit files, based on state failed, active and exited
systemctlOutput=$(systemctl --no-pager --type=service --state=failed | grep usbip@)
for str in ${systemctlOutput[@]}; do

# With regex and BASH_REMATCH, find dynamic unit filename, deviceID and usbipdServer
if [[ "${str}" =~ ^usbip@(.*):(.*:.*)\.service$ ]]; then

# Already store deviceID and usbipdServer, as
# BASH_REMATCH will lose content after duplicate check
# In case it is a duplicate, results are omitted
# As servicesArray is leading
deviceID[${arrayindex}]=${BASH_REMATCH[2]}
usbipdServer[${arrayindex}]=${BASH_REMATCH[1]}

# Check if unit file is already in array; if so, skip
if [[ "${servicesArray[*]}" =~ "${str}" ]]; then
continue
fi

servicesArray[${arrayindex}]=${str}
(( arrayindex++ ))
fi
done

systemctlOutput=$(systemctl --no-pager --type=service --state=active | grep usbip@)
for str in ${systemctlOutput[@]}; do
if [[ "${str}" =~ ^usbip@(.*):(.*:.*)\.service$ ]]; then

# Already store deviceID and usbipdServer, as
# BASH_REMATCH will lose content after duplicate check
# In case it is a duplicate, results are omitted
# As servicesArray is leading
deviceID[${arrayindex}]=${BASH_REMATCH[2]}
usbipdServer[${arrayindex}]=${BASH_REMATCH[1]}

# Check if unit file is already in array; if so, skip
if [[ "${servicesArray[*]}" =~ "${str}" ]]; then
continue
fi

servicesArray[${arrayindex}]=${str}
(( arrayindex++ ))
fi
done

systemctlOutput=$(systemctl --no-pager --type=service --state=exited | grep usbip@)
for str in ${systemctlOutput[@]}; do
if [[ "${str}" =~ ^usbip@(.*):(.*:.*)\.service$ ]]; then

# Already store deviceID and usbipdServer, as
# BASH_REMATCH will lose content after duplicate check
# In case it is a duplicate, results are omitted
# As servicesArray is leading
deviceID[${arrayindex}]=${BASH_REMATCH[2]}
usbipdServer[${arrayindex}]=${BASH_REMATCH[1]}

# Check if unit file is already in array; if so, skip
if [[ "${servicesArray[*]}" =~ "${str}" ]]; then
continue
fi

servicesArray[${arrayindex}]=${str}
(( arrayindex++ ))
fi
done

arrayLength=${#servicesArray[@]}

# print dynamic unit files found
for (( i=0; i<${arrayLength}; i++ )); do
logger -t ${scriptname} "Found dynamic unitfile: ${servicesArray[${i}]}; deviceID: ${deviceID[${i}]}; server: ${usbipdServer[${i}]}"
done

# Actual checking if unit file is active and usb available for binding
for (( i=0; i<${arrayLength}; i++ )); do
logger -t ${scriptname} "Check unit file: ${servicesArray[${i}]}........"

# Check if unit file is active (if not, we will skip)
systemctl is-active --quiet ${servicesArray[${i}]}

if [ "$?" -eq "0" ]; then
logger -t ${scriptname} "${servicesArray[${i}]} STARTED";

# Check if USB device is available for binding
# This means that server is back; or USB has been re-inserted
deviceavailable=$(usbip list -r ${usbipdServer[${i}]} | grep "${deviceID[${i}]}" | wc -l)
logger -t ${scriptname} "deviceavailable: ${deviceavailable}"

if [ "${deviceavailable}" -eq "1" ]; then
logger -t ${scriptname} "Remote USB device available for binding....restart unit file ${servicesArray[${i}]}"
systemctl restart ${servicesArray[${i}]}
else
logger -t ${scriptname} "No remote USB device available for binding OR device is already binded"
fi

else
logger -t ${scriptname} "${servicesArray[${i}]} STOPPED";
logger -t ${scriptname} "No further checking..."
fi

done

logger -t ${scriptname} "EXIT ${scriptname[$BASHPID]} PID = $BASHPID"
exit 0;