【问题标题】:Bash Scripting - user interaction when script launched from SystemdBash 脚本 - 从 Systemd 启动脚本时的用户交互
【发布时间】:2017-07-01 14:59:25
【问题描述】:

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

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

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

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

我想知道,如果您坐在控制台上让我的脚本开始显示 5 秒倒计时警告并允许用户取消,有没有办法?

我目前将树莓派设置为无头模式,因此它可以引导至控制台,仅此而已。它不会启动任何图形环境。我通常通过 ssh 进入树莓派来使用它。所以当我 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

【问题讨论】:

  • 你可以考虑systemd user mode。我不知道的是在这种情况下如何插入udev。

标签: linux bash debian


【解决方案1】:

答案很简单:你不能。如果可以的话,你不应该这样做。

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

您在 ssh 会话中输入 rm -rf /a 并连接了电话。几乎所有内容都被 shell 捕获,但您的脚本捕获了 a,当您按下回车键时,您会收到警告说在 / 上递归操作很危险。

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

【讨论】:

  • 感谢您的回复。是的,我认为这可能不是明智之举,而您的示例 jsut 证明了它的危险性。谢谢。
  • 我刚刚有了另一个想法。我可以让我的脚本创建一个新的 tty 并切换到该 tty,然后在完成后切换回原始 tty?
  • 但这会产生同样的问题。假设有可能,无论是从终端读取的两个进程还是从您键入的内容读取的两个终端,问题都是一样的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-06-07
  • 1970-01-01
  • 1970-01-01
  • 2014-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多