首页 > 解决方案 > 根据连续输出流的内容发出命令

问题描述

这个命令在这里:

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

在连续流中返回,监听设备上的变化,字符串如下:

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

问题是,当状态更改为 1 时,我希望发出以下命令:

systemctl start iio-sensor-proxy.service

当状态为 0 时,我希望发出此命令:

systemctl stop iio-sensor-proxy.service

我怎样才能把所有东西放在一起?

Andrew Vickers,我什至尝试这样做以查看是否有任何返回,但什么也没有:

#!/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

什么都没有回音。。

标签: bash

解决方案


如何处理 bash 中的流输入:一些建议。

  • 使用sed而不是grep:更轻更快:

  • 为您的命令使用专用的FD来释放STDIN

我的样本:

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

从那里,您可以使用readonSTDIN进行一些交互

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

推荐阅读