読み取りコマンドを実行するときにshが対話型オプションを使用しないのはなぜですか?

読み取りコマンドを実行するときにshが対話型オプションを使用しないのはなぜですか?

read設定スクリプトをダウンロードし、いくつかの設定パラメータを読み、実行したいと思います。

curl http://example.com/provisioning.sh | sh

問題は、デフォルト値を提供するためにパラメータを使用してreadスクリプトからコマンドを呼び出すことです。-i

read -p "Name: " -i joe name
echo $name

スクリプトをダウンロードして+x権限を設定して実行すると、すべてが正常です。

cat provisioning.sh | sh次のように実行するか、sh provisioning.sh次のように失敗した場合:

read: Illegal option -i

shを介して実行している場合、デフォルト値の読み取りのサポートが提供されないのはなぜですか?

しかし、とにかく削除し-iて残します。

read -p "Name: " name
echo $name

これでスクリプトを実行すると、cat provisioning.sh | sh何も起こりません。なぜそんなことですか?

Ubuntu 14.04。

答え1

の出力をパイプするcurlと、shスクリプトテキストをシェルの標準入力にし、実行するコマンドとして受け取ります。その後は何も残りませんread。試しても端末入力に接続されていないため、端末入力から何も得られません。パイプはshプロセスの標準入力を置き換えました。

次の質問read -iいいえPOSIX sh関数ですが、でサポートする拡張ですbashUbuntuはdash、基本的に最小限の拡張機能を備えた最小限のPOSIX準拠シェルです/bin/sh。これが-iオプションを明示的に拒否する理由です(サポートはしますが-p)。

より強力なシェルを直接使用している場合は、次のことを試すことができます。

bash <(curl http://example.com/provisioning.sh)

bashの出力を読み取るためのパイプを生成し、curlそれをスクリプトファイル引数として提供します。この場合、スクリプトの標準入力はまだターミナルに接続されていてread動作します(ただし、その行の下に重要な警告があります)。


私がまた注目したいのは" curl | sh"はい一般的に言えば チプリン顔 ~上明らかなセキュリティ上の問題ですが、スクリプトの状況はユーザーが最もよく知っています。

答え2

別の移植性のあるアプローチは、別のファイル記述子を作成することです。

exec 3<>/dev/tty
read -u 3 -p "Gimme some stuff: " stuff

ここで私が見つけたもの: https://superuser.com/questions/834502/possible-to-get-a-bash-script-to-accept-input-from-terminal-if-its-stdin-has-bee

私の場合、これがうまくいくようにスクリプトですばやく検索して置き換えました。

exec 3<>/dev/tty
read_cmd="read -u 3"

$read_cmd -p "name: " my_name
$read_cmd -p "email: " my_email
$read_cmd -s -p "password: " my_password

関連情報