base64でエンコードされたbashスクリプトを実行するとエラーが発生します。

base64でエンコードされたbashスクリプトを実行するとエラーが発生します。

私は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

この問題を解決する方法がわかりません。

ベストアンサー1

これを実行して、set -xシェルが実際に実行されていることを確認します。コマンドは、次から始まる行に表示されます+

+ 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。ユーザーに番号を尋ねる必要がありますが、そうではありませんか?

まあ、1つのことは、readstdinで読むことと、シェルがパイプで実行するスクリプトもbase64 ... | bashstdinから来ます。したがって、read入力ストリームの次の行(randint=......のある行)を忠実に読み、変数に入れますn

(もちろん*は参照がない$nため、いくつかのパラメータに分けられます。)$n

他のファイル記述子からスクリプトが入るように準備する必要があります。たとえば、プロセス置換を使用してスクリプトをシェル(Bash / ksh / zsh)に渡します。

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

または、read入力をfromにリダイレクトしてread端末から直接読み取るなど、別のfdから読み込みます/dev/tty。ほぼ一行でテストします。一重引用符で囲まれた文字列は、2行目まで続きます。

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

その後、インタラクティブに要求するのではなく、入力データをコマンドライン引数として渡すことを検討することもできます。コマンドライン引数はスクリプトの方が簡単で、端末を直接読むことも特に迷惑です。これは、プログラムを提供するためにスクリプトを簡単に使用できないためです。

また、これは標準のシェル機能ではないため、RANDOMスクリプトを明示的に実行する代わりに(またはまたは)を使用する必要があります。bashkshzshsh

おすすめ記事