linux - Bash 脚本 - 从 Systemd 启动脚本时的用户交互

标签 linux bash debian

我一直在谷歌搜索很多,但我没有找到任何信息来帮助我完成我的任务。也许这是不可能的。我正在 Raspberry Pi 上使用 Raspbian 发行版,但我认为它与任何 bash 脚本编写都相关。

我已经创建了 udev 规则和一个 systemd 服务,当系统检测到插入 usb 的谷歌手机(例如插入 nexus 4、5 6P 等)时,它会执行我编写的 bash 脚本。这一切都有效。您插入手机,我的脚本将执行并使用 fastboot 获取设备产品名称,然后将适当的 twrp 镜像闪存到手机上的恢复分区(twrp 是为手机定制的恢复操作系统)。

如果我在终端手动执行 bash 脚本,您将进行用户交互。回显信息什么的。我有一个 5 秒倒计时计时器,让用户有机会在检测到设备后停止执行。这也行。

我的问题是:当脚本由 systemd 在它自己的虚拟终端或其他任何东西中执行时,如果您在控制台上,您将看不到脚本中的任何内容,并且脚本无法看到任何用户输入(例如击键)取消。

我想知道,如果您坐在我的脚本的控制台前,是否可以开始显示 5 秒倒计时警告并允许用户取消?

我目前在 headless 模式下设置了 raspberry pi,因此它可以启动到控制台,仅此而已。它不会启动任何图形环境。我通常通过 ssh 进入 raspberry PI 来使用它。因此,当我 ssh 进入并执行 w 命令时,我看到我的 tty 是/pts/0。

是否可以让我的脚本从当前控制台输出和读取任何击键?我希望这是有道理的。

我最终在我的脚本中创建了一个函数,我可以调用它来回显所有事件的、打开的 tty,但我不知道如何读入。而且我认为可能有一种更优雅的方式来实现我的目标我正在做提前感谢任何人可以提供的任何帮助或建议。我将在下面放置代码和输出。

保罗。

USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
pi       tty1                      18:22    1:08m  1.18s  0.92s -bash
pi       pts/0    fe80::187c:321f: 18:49    1.00s  2.98s  0.05s w

我的 udev 规则

# Google
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", MODE:="0666", GROUP:="plugdev", TAG+="systemd", ENV{SYSTEMD_WANTS}+="load-fastboot-flasher.service"

我的systemd服务单元文件

[Unit]
Description=Google Device TWRP Recovery
After=multi-user.target

[Service]
Type=idle
User=pi
ExecStart=/home/pi/fastboot-twrp/fastboot-twrp-flash.sh > /dev/null &
StandardOutput=console

[Install]
WantedBy=multi-user.target

最后是我的 bash 脚本

#!/bin/bash

######################################################################################
# Our function that performs the flash after a device was detected.
######################################################################################
fastboot-test() {
 GOOGLEDEVICENAME=`fastboot getvar product 2>&1 | grep "product:" | awk '{print $2}'`
 if [[ "$GOOGLEDEVICENAME" != "" ]]; then
    echoall "Device Product_Name: $GOOGLEDEVICENAME"
    if [ ! -d "$GOOGLEDEVICENAME" ]; then
       # Control will enter here if $DIRECTORY doesn't exist.
       echoall "Error!  Device folder & recovery image dont exist.  Aborting!"
       echoall ""
       echoall "Please create a folder using the same product name as your device in the folder"
       echoall "that this script resides in and place your twrp image in this new folder."
       echoall "e.g. for a Nexus 4 make a folder called mako with your twrp image inside it."
       echoall ""
       exit 1
    fi
    cd $GOOGLEDEVICENAME
    echoall "Selecting twrp image: " $PWD/twrp*
    sleep 1
    echoall ""
    fastboot flash recovery $PWD/twrp*
    echoall ""
    echoall "twrp recovery image flash complete!"
    echoall "Enjoy your fishing.... ;-)"
    echoall ""
 else
    echoall "No connected Google devices"
 fi
}

######################################################################################
# Our function to print output to all currently open consoles (e.g. type w a terminal to see users)
######################################################################################
echoall() {
 for PTS in $(w |grep -o pts/.) ; do echo $1 $2 $3 >>/dev/$PTS; echo $1 $2 $3 >>/home/pi/load-fastboot-flasher.log; done
}



######################################################################################
# START
######################################################################################
#set +x
echoall ""
echoall "$(date)"
echoall ""
echoall "Google device detected.  Press C then ENTER to cancel TWRP recovery flash in 5 seconds"
COUNT=5
while (( COUNT > 0 ))
 #This is our 5 sec timer.
 do
   read -t 1 -n 1 -r
   if [[ $REPLY == ^[Cc]$ ]]; then
      Exit 0
   fi
   sleep 1
   (( COUNT -- ))
   echoall $COUNT
 done
echoall ""
echoall ""
#set -x

DETECTED=`fastboot devices | awk '{print $2}'`
if [[ "$DETECTED" == "fastboot" ]]; then

  #Save the current working directory
  RESTOREPATH=`pwd`

  #Change the current working directory to the directory that this script resides in
  cd $(dirname $(readlink -f $0))
  echoall "changed working directory to: "$PWD
  echoall ""
  #

  echoall "Device detected: Yes"
  fastboot-test
  cd $RESTOREPATH
  echoall "changed working directory to: "$PWD
  echoall ""
  echoall "### END TWRP FLASH ###"
  echoall ""
  for PTS in $(w |grep -o pts/.) ; do echo -ne '\n' >>/dev/$PTS; done
  exit
else
  echoall "Error! Fastboot not properly detecting Google device."
fi

最佳答案

答案很简单:你不能。如果可以,你不应该。

写入所有终端很容易; wall 会为你做这件事。但是,已经有一个进程读取您的终端输入,那就是您的 shell(bash 如果一切都是默认的)。因此,如果您希望第二个进程从同一个终端读取,您将遇到这样的问题,即您键入的某些字符将进入脚本,而另一些则进入 shell。也许一个例子可以说明问题:

您在 ssh session 中键入 rm -rf/a 并且电话已连接。几乎所有的东西都会被 shell 捕捉到,但是你的脚本会捕捉到 a 并且当你按下 enter 时,你会得到警告说对/进行递归操作是危险的。

您可能想探索其他选项;例如 dancer2 网络应用程序。

关于linux - Bash 脚本 - 从 Systemd 启动脚本时的用户交互,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44862337/

相关文章:

linux - 如何使 BASH 脚本仅在特定目录中运行?

linux - 将图像从 TrueColor 更改为 1Bpp 调色板?

c++ - ‘.’ token 之前应有非限定 ID

automation - 将密码通过管道传送到 smbpasswd

java - 如何复制文件名中带有空格的文件

bash - 回显但保留双引号

regex - Bash 匹配字符串与正则表达式

bash - Java 命令在 bash 上运行,在 zsh 上失败

linux - 在 Debian(托管帐户)上将 Subversion 1.4.3 升级到 1.5.2

linux - bash 脚本中的 while 循环破坏了 systemd 服务