如何強制 bash 腳本等待使用者回答?

如何強制 bash 腳本等待使用者回答?

已經有類似的問題,但我發布此問題是因為沒有答案有效。我正在編寫一個 bash 腳本來自動在我的 Arch 系統上安裝 pacman 和 AUR 套件。這個想法是先逐行讀取包含套件名稱的檔案(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 提示我輸入號碼時,如何暫停腳本?在這種情況下,一般的做法是什麼?當我運行腳本時,如何從一開始就給出特定包的答案(例如 1 代表包 x)?

答案1

基本問題是 stdin(試圖aurman從中讀取)不是來自用戶,它首先從 重定向$myfile,然後從包含要運行的 shell 命令的此處文件重定向sudo。一種選擇是透過不同的文件描述符傳遞這些文件,例如#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,有睡覺命令,該命令使腳本進入休眠狀態,直到經過一段時間(以秒為單位)。但是,如果您想要捕獲密碼,我會推薦您使用以下兩種方法之一(檢查我放在底部的腳本,以說明睡眠如何工作,以及下面提到的兩種替代方法)。

  • 您可以在啟動腳本時將密碼作為參數發送。
  • 您可以使用命令,這將記錄輸入,直到客戶按 Enter 鍵。

[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 ~]#

相關內容