|
#!/bin/bash
##---------------------------------------------------------------------------##
#
# Script: inotifydev
# Author: Brian <genius@groupbcl.ca> :)
# Date: August 2017
#
# Using 'inotifywait,' watches /dev for device files being created and
# removed, usually in response to a USB device being connected and dis-
# connected. When a device appears, this script searches the directory in
# which it was started for a script named 'inotifydev-X-device', where X
# is the name of the device that appeared (e.g. 'inotifydev-ttyUSB0-device'
# for a serial device.) If no file with that name is present, it searches
# for a generic script by trimming the last character off the name (e.g.
# 'inotifydev-ttyUSB-device'.) The search continues until it gets a match
# or only one charcter remains; that is it will search down to
# 'inotifydev-tt-device' but not to 'inotifydev-t-device.')
#
# If a matching script name is found, it is called with two parameters:
# 'CREATE' or 'DELETE' and the device name (without the leading /dev/).
#
# "inotifydev" is intended to be run at startup. For systemd setups, put
# the following text into /etc/systemd/system/inotifydev.service, then
# run "systemctl enable inotifydev" (or run "inotifydev --install" to
# have this script to the work for you):
#
# [Unit]
# After=network-online.target
#
# [Service]
# Type=simple
# ExecStart=/usr/local/bin/inotifydev start
# ExecStop=/usr/local/bin/inotifydev stop
# Restart=on-failure
#
# [Install]
# WantedBy=multi-user.target
#
# The "inotifydev --install" function can also set up a System V init
# script on systems descended from Red Hat or Debian.
#
##---------------------------------------------------------------------------##
# BUUS: This script is part of Brian's Useful Utilities Set
##---------------------------------------------------------------------------##
EXEC_DN="$(dirname $0)"
[ -d /run ] && RUN_DN='/run/inotifydev'
[ -d /var/run ] && RUN_DN='/var/run/inotifydev'
[ "$RUN_DN" ] || RUN_DN='/tmp/inotifydev'
[ -d $RUN_DN ] || mkdir $RUN_DN
PIPE_FN="$RUN_DN/inotifydev.pipe"
PID_FN="$RUN_DN/inotifydev.pid"
INOTIFYWAIT_PID_FN="$RUN_DN/inotifydev-inotifywait.pid"
##---------------------------------------------------------------------------##
# startup - start inotifydev
##---------------------------------------------------------------------------##
function startup {
# If we're not running under systemd, we need to add our own timestamps
# to the log file lines
ADD_TIMESTAMPS=false
[ "$1" == '--background' ] && ADD_TIMESTAMPS=true
# At startup, look for inotifydev-*-device files. If devics enamed
# in the file exist, run the script with CREATE and the device name
ls -l $EXEC_DN/inotifydev-*-device &>/dev/null
if [ $? == 0 ]
then
for SCRIPT_FN in $EXEC_DN/inotifydev-*-device
do
DEVICE_TYPE="$(basename $SCRIPT_FN)"
DEVICE_TYPE="${DEVICE_TYPE#inotifydev-}"
DEVICE_TYPE="${DEVICE_TYPE%-device}"
echo $SCRIPT_FN $DEVICE_TYPE
ls /dev/${DEVICE_TYPE}* &>/dev/null
if [ $? == 0 ]
then
ls /dev/${DEVICE_TYPE}* | while read DEV
do
DEVICE="${DEV#/dev/}"
$ADD_TIMESTAMPS && TIMESTAMP="$(date +'%F %T') "
echo "${TIMESTAMP}Run $SCRIPT_FN CREATE $DEVICE"
$SCRIPT_FN CREATE $DEVICE &
done
fi
done
fi
# Create a pipe and start inotifwait on it
mknod $PIPE_FN p
inotifywait -qm -e create -e delete /dev >$PIPE_FN 2>/dev/null &
echo $! >$INOTIFYWAIT_PID_FN
$ADD_TIMESTAMPS && TIMESTAMP="$(date +'%F %T') "
echo "${TIMESTAMP}Created pipe file $PIPE_FN and started inotifywait on PID $!"
# Wait for create and delete events in /dev. As each new device appears
# or disappears, launch a handler script for it, if one exists.
cat $PIPE_FN | while read LINE
do
ACTION="${LINE:6:6}"
DEVICE="${LINE:13}"
L=${#DEVICE}
while [ $L -gt 1 ]
do
SCRIPT_FN="inotifydev-${DEVICE:0:$L}-device"
[ -x "$EXEC_DN/$SCRIPT_FN" -o -L "$EXEC_DN/$SCRIPT_FN" ] && L=0
L=$((L-1))
[ $L == 1 ] && SCRIPT_FN=""
done
$ADD_TIMESTAMPS && TIMESTAMP="$(date +'%F %T') "
if [ "$SCRIPT_FN" ]
then
echo "${TIMESTAMP}Run $EXEC_DN/$SCRIPT_FN $ACTION $DEVICE"
$EXEC_DN/$SCRIPT_FN $ACTION $DEVICE &
else
echo "${TIMESTAMP}$ACTION: No inotifydev device script found for $DEVICE"
fi
done
$ADD_TIMESTAMPS && TIMESTAMP="$(date +'%F %T') "
echo "${TIMESTAMP}Pipe was closed; shutting down"
}
##---------------------------------------------------------------------------##
# startup_bg: start a new instance of inotifydev in the background, for
# systems that are running System V init scripts.
##---------------------------------------------------------------------------##
function startup_bg {
# Rotate the log files
cd /var/log
[ -f inotifydev.log.9.bz2 ] && rm -f inotifydev.log.9.bz2
for N in 8 7 6 5 4 3 2
do
[ -f inotifydev.log.$N.bz2 ] &&
mv inotifydev.log.$N.bz2 inotifydev.log.$((N+1)).bz2
done
if [ -f inotifydev.log.1 ]
then
mv inotifydev.log.1 inotifydev.log.2
bzip2 inotifydev.log.2
fi
[ -f inotifydev.log ] && mv inotifydev.log inotifydev.log.1
# Now start a new instance in the background
nohup $0 start --background </dev/null &>/var/log/inotifydev.log &
echo $! >$PID_FN
# (Red Hat's startup functions really want a PID file in /var/run)
[ -d /var/run -a ! -f /var/run/inotifydev.pid ] &&
ln $PID_FN /var/run/inotifydev.pid
}
##---------------------------------------------------------------------------##
# shutdown - stop inotifydev
##---------------------------------------------------------------------------##
function shutdown {
if [ -f $INOTIFYWAIT_PID_FN ]
then
kill $(< $INOTIFYWAIT_PID_FN)
else
echo "INOTIFYWAIT_PID_FN file not found; attempting to locate and kill inotifywait"
INOTIFYWAIT_PID="$(ps -ef | grep -v awk | awk '/inotifywait -qm/{ print $2 }')"
[ "$INOTIFYWAIT_PID" ] && kill $INOTIFYWAIT_PID
fi
rm -f $PIPE_FN $INOTIFYWAIT_PID_FN $PID_FN
}
##---------------------------------------------------------------------------##
# install - set up inotifydev in a System V or systemd environment
##---------------------------------------------------------------------------##
function __install_die { echo "inotifydev: $1"; exit 1; }
function __install_sys_v {
INSTALL_TYPE=sys_v
INIT_SCRIPT='/etc/init.d/inotifydev'
[ -f "$INIT_SCRIPT" -o -L "$INIT_SCRIPT" ] &&
__install_die "inotifydev appears to be installed already (found $INIT_SCRIPT)"
# Ensure the needed utilities are in place for the install
which base64 &>/dev/null || __install_die echo "install failed; cannot find base64"
which chkconfig &>/dev/null && CONFIG_CMD=chkconfig
which update-rc.d &>/dev/null && CONFIG_CMD=update-rc.d
[ "$CONFIG_CMD" ] || __install_die "cannot determine System V setup script:" \
"not RedHat (chkconfg) or Debian (update-rc.d)"
# Extract the init script from this file
echo "Setting up /etc/init.d/inotifydev"
sed '1,/^# \/etc\/init.d\/inotifydev/d; s/^# //' $0 |
base64 -d | gunzip >$INIT_SCRIPT
chmod +x $SCRIPT_FN
# Update the System V startup links
echo "Running $CONFIG_CMD"
[ "$CONFIG_CMD" == 'RedHat' ] && chkconfig --add inotifydev
[ "$CONFIG_CMD" == 'Debian' ] && update-rc.d inotifydev start 27 3 4 5 stop 73 0 1 6
}
function __install_systemd {
INSTALL_TYPE=systemd
SERVICE_FN="/etc/systemd/system/inotifydev.service"
[ -f $SERVICE_FN ] &&
__install_die "inotifydev appears to be installed already (found $SERVICE_FN)"
echo "Setting up service file $SERVICE_FN"
UNIT_START="$(grep -n '^#[[:space:]]*\[Unit\]$' /usr/local/bin/inotifydev | cut -f1 -d:)"
UNIT_STOP="$(grep -n '^#[[:space:]]*WantedBy=' /usr/local/bin/inotifydev | cut -f1 -d:)"
sed "1,$((UNIT_START-1))d; $((UNIT_STOP+1)),\$d; s/^#[[:space:]]*//" $0 >$SERVICE_FN
systemctl enable inotifydev
echo "Starting inotifydev"
systemctl start inotifydev
[ $? == 0 ] && echo "Started" || echo "Attempt to start inotifydev failed"
}
function install {
[ -d /etc/init.d -o -L /etc/init.d ] && __install_sys_v
[ -d /etc/systemd/system ] && __install_systemd
[ "$INSTALL_TYPE" ] || echo "Unable to determine system initialization type;" \
"it's not System V nor systemd"
}
##---------------------------------------------------------------------------##
# Main processing
##---------------------------------------------------------------------------##
trap shutdown INT
case $1 in
start) startup $2;;
background) startup_bg;;
stop) shutdown;;
--install) install;;
*) echo "usage: inotifydev start|stop";;
esac
exit
# /etc/init.d/inotifydev (gzipped, base64)
# H4sICGzfvVkAA2lub3RpZnlkZXYAlVNda9tAEHz2/YqNbAIpleQmKQEbUwrtQ6FPbdKXtJDzaWUd
# tu/U+7Ad4v737p1kS6EhuMag097s7szsaniWz6XKbcWGbAjfHTfO12CFkbWDUhuQSjtZPha4eQvb
# SooKjFe2RVgKoQK6lAKhlCu0wOsauaFiUgFXBRTSNiEojV5DTuDYS1RLoVUpFxO4un4Plzdwc0Xh
# ApvSUqsJ3Fby0Or/ifykam3n16hAbbRAaxVf46TXJdzIIpSaQL7hJqd2eXfdO2aEY8E97U3o7pUI
# 9GEl54abx4xlkKMTuRFZQWnS0eMAsr1EhW6rzVKqBTTOeMMD5ljAPtrmIm+hjHUsZrm3Jl9pwVdx
# pD0l95CWMOoC8Av2e8CddDBm7Nvn2x8fv87GkQkiVHoLW6S/QaBiKywyJrhFSEbvEjKIDWxYkws2
# GMgS7mF09+UTpAphTHWn4GgQdDVAUWlI7iwaqLilPOvLUgqJypHlckPGLjBLIjQwuaZTKVmbmCpI
# 4jYGNzrmEwgJBcc1+Zum7YBOmM8z+XMulgujvSqoWCt/9KFtTQ/S1EQhxd9R1vk5OO1p52InMnmZ
# Wz+nefRtHgym02COrltvHFoHye6hpanLsGo9NSfwfkjgbAa7o61Av86gyrtoUKG36h+XArSvOhA7
# eHyqaLMOq/OK6JckxO/hYAZ33gY7mhM8s6vPIqANHjdrND7wjSeKvoB/c8G6PeML+lAJ/BTR+5C9
# bwvum+Z/gitx1y4ZWi4Yiy+tbMb+Ag+mM/4MBQAA
# vim: tabstop=4
|