La faguette
La faguette

Reputation: 581

Issue a command based on content of a continuous output stream

This command here:

stdbuf -oL -eL libinput debug-events \
  --device /dev/input/by-path/pci-0000:00:1f.0-platform-INT33D6:00-event \
  | grep SWITCH_TOGGLE

Returns in a continuos stream, listening for changes on a device, strings like these:

event7   SWITCH_TOGGLE     +2.65s   switch tablet-mode state 1
event7   SWITCH_TOGGLE     +4.62s   switch tablet-mode state 0

Thing is, when the state changes to 1 I want this command to be issued:

systemctl start iio-sensor-proxy.service

While when the state is 0 I want this command to be issued:

systemctl stop iio-sensor-proxy.service

How can I put all together?

Andrew Vickers, I even tried to do this to see if anything was returned, but nothing:

#!/bin/bash

stdbuf -oL -eL libinput debug-events --device /dev/input/by-path/pci-0000:00:1f.0-platform-INT33D6:00-event | grep SWITCH_TOGGLE |
while read string; do
  echo "$string";
done

Nothing was being echoed..

Upvotes: 1

Views: 192

Answers (2)

F. Hauri  - Give Up GitHub
F. Hauri - Give Up GitHub

Reputation: 71057

How to deal with stream input in bash: some recommendations.

  • use sed instead of grep: lighter and quicker:

  • use a dedicated FD for your command to free STDIN.

My sample:

DEVICE=/dev/input/by-path/pci-0000:00:1f.0-platform-INT33D6:00-event

exec 6< <(
      exec stdbuf -oL -eL libinput debug-events --device $DEVICE |
          sed -une /SWITCH_TOGGLE/p
)

while read -u 6 foo foo mtime action target foo state; do
  if [ "$action" = "switch" ] && [ "$target" = "tablet-mode" ] ;then
    case $state in
        0 ) systemctl stop  iio-sensor-proxy.service ;;
        1 ) systemctl start iio-sensor-proxy.service ;;
    esac
  fi
done

From there, you could use read on STDIN for some interactivity:

DEVICE=/dev/input/by-path/pci-0000:00:1f.0-platform-INT33D6:00-event

exec 6< <(
      exec stdbuf -oL -eL libinput debug-events --device $DEVICE |
          sed -une /SWITCH_TOGGLE/p
)
LIPIDS=($(ps ho pid,ppid | sed "s/ $!$//p;d"))

while :;do
  read -t 1 -u 6 foo foo mtime action target foo state &&
  if [ "$action" = "switch" ] && [ "$target" = "tablet-mode" ] ;then
    case $state in
        0 ) systemctl stop  iio-sensor-proxy.service ;;
        1 ) systemctl start iio-sensor-proxy.service ;;
    esac
  fi
  if read -t .001 -n 1 USERINPUT ;then
      case $USERINPUT in
          q ) exec 6<&- ; echo User quit.; kill ${LIPIDS[@]} ; break ;;
      esac
  fi
done

Upvotes: 2

Andrew Vickers
Andrew Vickers

Reputation: 2664

This should do it:

#!/bin/bash

stdbuf -oL -eL libinput debug-events \
    --device /dev/input/by-path/pci-0000:00:1f.0-platform-INT33D6:00-event |
  grep SWITCH_TOGGLE |
while read -a fields; do
  case ${fields[6]} in
    0) systemctl stop iio-sensor-proxy.service;;
    1) systemctl start iio-sensor-proxy.service;;
  esac
done

Upvotes: 0

Related Questions