Bash – Improving the Bash script

bashshell-scriptudev

I need to improve my Bash script so that it runs flawlessly without having issues. This script uses ds4drv in it and it has some issues that I'm unsure on how to correct.

First issue is that it doesn't always run or work when the controller is detected, I had created a udev rule for it but it's not clear why it doesn't always run this script when it's detected.

Second issue, ds4drv can only be allowed to run as root only, instead of being run as normal user.

Third issue, I do not know the proper way of dealing with PID lock files once they've been created, so that when the PID process no longer exists it deletes the PID lock file after. It's hard to find proper documentation on how to use PID files in bash scripts so that there can only be 1 running instance.

heres' my udev rule for ds4drv: 50-ds4drv.rules

KERNEL=="uinput", GROUP="users", MODE="0666"
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="054c", ATTRS{idProduct}=="05c4", GROUP="users", MODE="0
666"
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", KERNELS=="0005:054C:05C4.*", GROUP="users" MODE="0666"
ACTION=="add", SUBSYSTEM="usb", ATTRS{idProduct}=="054c", RUN+="/home/user/scripts/ds4check.sh", GROUP="users"
, MODE="0666"

I'm pretty sure that's how the udev rule should be like, permissions seem to be correct to me since it's read-write for GROUP users. There does seem to be some instance of an issue that once my bash script has run and this rule is set to run automatically when the controller device is connected, that some games become unresponsive like there is no controller device connected when there is, it's suppose to act on /dev/js0 but instead acts on /dev/js1 instead. It may often return this error in particular if it's not executed as root;

OSError: [Errno 13] Permission denied: '/dev/input/event17'

and the bash script of course; ds4check.sh

#!/bin/bash
# DS4 Check Script

pidfile=/tmp/ds4drv.pid

# check if process is already running
for pid in $(pidof -x /home/user/scripts/ds4check.sh $pidfile); do
    if [ $pid != $$ ]; then
      echo "[$(date)] : ds4check.sh : Proccess is already running with PID $pid" >> /home/user/.cache/ds4drv.log
      exit 1
# if not running then run and apply config
      else  ( ds4drv --hidraw --config /home/user/.config/ds4drv.conf )

      exit 0
    fi
done

# remove PID file on exit... hopefully
trap "srm -rv -- '$pidfile'" EXIT >> /home/user/.cache/ds4drv.log

Best Answer

I'm concerned about 2 points

  • PID files which I'm not familiar with, but I would suggest using pgrep as workaround.
  • ds4drv seems a daemon but udev supports only short running processes.

    RUN{type}

    ...

    This can only be used for very short-running foreground tasks. Running an event process for a long period of time may block all further events for this or a dependent device.

    Starting daemons or other long-running processes is not appropriate for udev; the forked processes, detached or not, will be unconditionally killed after the event handling has finished.

Make a copy of that script:

#!/bin/bash
# DS4 Check Script

pgrep ds4drv || ds4drv --hidraw --config /home/user/.config/ds4drv.conf & disown
Related Question