私はしばしばGitHubでリモートBashスクリプトのrawバージョンを実行するために次のパターンを使用します。
wget -O - https://raw.githubusercontent.com/<username>/<project>/<branch>/<path>/<file> | bash
通常は問題なく実行できますが、特定のスクリプトに次のコードを追加したため、無限ループが発生しました。echo
(GitHubから端末にコピーして貼り付けて直接実行した場合でも頻繁に発生します。):
while true; do
read -p "Example question: Do you wish to edit the PHP file now?" yn
case $yn in
[Yy]* ) nano PROJECT/PHP_FILE; break;;
[Nn]* ) break;;
* ) echo "Please answer yes or no.";;
esac
done
次のことで、問題を少なくとも部分的に解決できました。
cd ACTION_DIRECTORY
wget https://raw.githubusercontent.com/<username>/<project>/<branch>/<path>/<file> &&
source FILENAME &&
rm FILENAME
これは| bash
、パイプラインが少なくとも問題を悪化させていることを示唆しています。いつも後ろに来てください。
なぜecho "Please answer yes or no."
「無限に」起こるか。 (CTRLC+で停止しましたC。)
1行および/またはでコマンドを実行できませんでしたかwhile true; do case esac done
?
答え1
なぜ
echo …
「無限に」起こるか。
標準入力と一緒に。は同じ標準入力から読み取られますwget … | bash
。wget
bash
bash
wget
read
通常、read
スクリプトソースから読み取ると、スクリプトの一部が消費される可能性があります。あなたの場合は、完全なbash
部分while … done
を読む必要があります(例while … done <whatever
:)。働く時はread
読むことがありません。最初もread
失敗しました。
問題のスクリプトはread
失敗を確認しません。
また、read -p
プロンプトを標準入力として印刷するため、プロンプトは表示されません。
スクリプトが存在する</dev/tty read …
かstdinで読み取られwhile … done </dev/tty
ない場合は、コンソールから読み込みます。この方法は機能しますが、この方法を使用するにはスクリプト自体を変更する必要があります。一般的に言えば、別の方法でスクリプトを実行し、スクリプト全体のstdinから読み取る必要がある場合(これは。read
bash
read
/dev/tty
ただし、nano
(あなたが答える場合y
)、標準入力について文句を言うかもしれません。修正があると、標準入力が(すでに破損している)パイプから出るため、対応する修正が</dev/tty read …
生成nano
されます。修正があれば動作します。Too many errors from stdin
wget
while … done </dev/tty
より大きなスクリプトの場合、この方法で「修正」できる場所が多い場合があります。正しい一般的な解決策は、標準入力をまったく傍受しないことです。
一般的な回避策は、次のいずれかを実行することです。
bash <(wget -O - …)
. <(wget -O - …)
スクリプトを別のシェルbash
(試行のようにwget … | bash …
)で実行するのか、現在のシェルで(source FILENAME
ソリューションのように)実行するのかによって異なります。
これで、標準入力を独立してリダイレクトできます。たとえば、次のようになります。
yes | bash <(wget -O - …)
文法<(some_command …)
と呼ばれますプロセスの交換。効果がある大きな打撃を受けた状態でそしていくつかの他の殻(純粋な殻ではないsh
)バシズム)。以下はいくつかの興味深い観察です。プロセス置換とパイプ(「STDINを保持」セクションこの回答つまり、これはあなたの問題です。)