Shell-Script

執行 base64 編碼的 bash 腳本給我錯誤

  • January 15, 2022

我有一個 bash 腳本;該腳本是生成一個隨機數並讓使用者猜測它。

printf 'Guess the number (1-10) : '
read -r n
randint=$(( ( RANDOM % 10 )  + 1 ))
if [ $n = $randint ];
then
echo "You Won !"
else
echo "Sorry, try again !"
fi

它可以工作,但在下一個腳本中,我將此程式碼編碼為 base64 並嘗試使用以下程式碼執行它。

exec="cHJpbnRmICdHdWVzcyB0aGUgbnVtYmVyICgxLTEwKSA6ICcKcmVhZCAtciBuCnJhbmRpbnQ9JCgoICggUkFORE9NICUgMTAgKSAgKyAxICkpCgppZiBbICRuID0gJHJhbmRpbnQgXTsKdGhlbgplY2hvICJZb3UgV29uICEiCmVsc2UKZWNobyAiU29ycnksIHRyeSBhZ2FpbiAhIgpmaQ=="
base64 -d <<< $exec | sh

它在 Cygwin 終端中給出了這個錯誤:

Guess the number (1-10) : sh: line 4: [: too many arguments
Sorry, try again !

我嘗試了一個線上編譯器,但它也失敗了:

sh: 5: [: =: unexpected operator

我不知道要解決這個問題。

執行它set -x以查看 shell 實際執行的內容,命令顯示在以 開頭的行中+

+ printf 'Guess the number (1-10) : '
Guess the number (1-10) : + read -r n
+ '[' 'randint=$((' '(' RANDOM % 10 ')' + 1 '))' = ']'
bash: line 4: [: too many arguments
[...]

什麼是測試,裡面[ ... ],作業randint=...(*)?它應該是read n給予的。它應該向使用者詢問號碼,但沒有?

嗯,事情就是這樣,read從標準輸入讀取,在管道base64 ... | bash中,shell 執行的腳本也來自標準輸入。因此,read盡職盡責地讀取輸入流中的下一行,即帶有randint=..., 的行,並將其放入變數n

(*$n被分詞成多個參數,當然,因為$n沒有被引用。)

您需要安排腳本從不同的文件描述符進入,例如使用程序替換將腳本傳遞給 shell(在 Bash/ksh/zsh 中):

bash <( base64 -d <<< "$exec" )

或者通過read從其他一些 fd 讀取,例如通過將輸入重定向到readfrom直接從終端讀取/dev/tty。使用幾乎單行進行測試(單引號字元串繼續到第二行):

$ printf 'read -r -p "say something: " foo < /dev/tty; 
         echo "you entered: $foo"' | bash
say something: asdfsadf
you entered: asdfsadf

再說一次,您可能會考慮只將輸入數據作為命令行參數傳遞,而不是互動式地請求它。命令行參數更容易編寫腳本,直接讀取終端也特別令人討厭,正是因為它阻止了輕鬆使用腳本來提供程序。

另請注意,這RANDOM不是標準的 shell 功能,因此您可能應該使用bash(或ksh,或zsh)顯式執行腳本,而不是sh.

引用自:https://unix.stackexchange.com/questions/686055