如何强制 bash 脚本等待用户答复?

如何强制 bash 脚本等待用户答复?

已经有类似的问题,但我发布这个是因为没有一个答案有效。我正在编写一个 bash 脚本来自动安装 pacman 和 AUR 包在我的 Arch 系统上。这个想法是先逐行读取一个包含包名称的文件 (myfile),然后逐字读取,并针对每个单词执行安装。这对 pacman 很有效,但对 AUR Helper (aurman) 无效。aurman 的部分如下所示:

while read line; do
if [[ "$line" =~ \$[[:space:]]aurman[[:space:]]-S[[:space:]][[:alnum:]]* ]]
then
    aurline=$(echo "$line" | awk '{ $1=""; $2=""; $3=""; print}' | sed 's/^ *//')
    for aurpkg in $aurline
    do
       sudo -u "${my_user}" bash << EOF
aurman -S --noconfirm --needed --noedit "$aurpkg"
wait
EOF
    done
fi
done < "$myfile"

使用选项--noconfirm --needed --noeditaurman 不会提示我输入是/否,但对于某些软件包,它会提示我输入数字。因此,在这种情况下,问题是脚本不会等待,软件包不会安装,并且 aurman 会产生错误“EOFError:读取一行时出现 EOF”。我尝试过像这样暂停脚本:

aurman ...
wait

或者像这样:

aurman ... &
wait

但这些都不起作用。

那么,当 aurman 提示我输入数字时,我该如何暂停脚本?在这种情况下,一般的方法是什么?当我运行脚本时,如何从一开始就为特定包给出答案(例如,包 x 的答案为 1)?

答案1

基本问题是 stdin(试图aurman读取)不是来自用户,它首先从 重定向$myfile,然后从包含以下 shell 命令的此处文档重定向:sudo运行的 shell 命令的此处文档重定向。一种选择是通过不同的文件描述符传递这些文件,例如 #3(通常不使用)。我思考您还可以通过消除在其下运行的 shell 来简化它sudo——因为您在前台运行aurman,所以不需要wait它,所以您不需要 shell(因此不需要此处的文档)。

while read line <&3; do
    if [[ "$line" =~ \$[[:space:]]aurman[[:space:]]-S[[:space:]][[:alnum:]]* ]]
    then
        aurline=$(echo "$line" | awk '{ $1=""; $2=""; $3=""; print}' | sed 's/^ *//')
        for aurpkg in $aurline
        do
            sudo -u "${my_user}" aurman -S --noconfirm --needed --noedit "$aurpkg"
        done
    fi
done 3< "$myfile"

如果这不起作用并且您确实需要在下运行 shell sudo,那么您也可以通过 FD #3 重定向它,并将bash其读取为脚本,如下所示:

            sudo -u "${my_user}" bash /dev/fd/3 3<< EOF
aurman -S --noconfirm --needed --noedit "$aurpkg"
wait
EOF

答案2

对于 bash,有睡觉命令,使脚本进入休眠状态,直到经过一定时间(以秒为单位)。但是,如果您想要获取密码,我建议您使用以下两种方法之一(查看我放在底部的脚本,以说明休眠的工作原理,以及下面提到的两种替代方法)。

  • 您可以在启动脚本时将密码作为参数发送。
  • 您可以使用命令,这将记录输入,直到客户按下回车键。

[root@client ~]# cat readPass.sh
#!/bin/bash

# Author: @djcerdas
password="$1"

# Sample sleep command
echo "Hi, I am the PID $$, I am going to sleep 3 seconds"
date&&sleep 3&&date
echo "---------------------------------------"
# Sample method 1: passing password a parameter
echo  "Method 1: The password is $password"
password=""
echo "---------------------------------------"
# Sample method 2: using read
echo "Method 2: Please provide your password:"
read password
echo The password is $password

[root@client ~]# ./readPass.sh myPasswordX
Hi, I am the PID 2257, I am going to sleep 3 seconds
Tue Apr  3 01:17:55 CST 2018
Tue Apr  3 01:17:58 CST 2018
---------------------------------------
Method 1: The password is myPasswordX
---------------------------------------
Method 2: Please provide your password:
myNewPassword
The password is myNewPassword
[root@client ~]#

相关内容