Bashでは、以下を実行します。
alias myalias='echo foo
echo bar
echo baz'
myalias
返品:
foo
bar
baz
しかし:
ssh localhost "shopt -s expand_aliases &>/dev/null;
alias myalias='echo foo
echo bar
echo baz'
myalias"
返品:
foo
なぜ?
ベストアンサー1
私の考えでは、Bashでバグを見つけたようです。このエラーはオプションによって異なります-c
。
リモートでの実行は、複数行のエイリアスの問題とは関係ありません。ローカルbashで試してみてください。しかし、bashスクリプトやインタラクティブbashではなく、-c
以下のオプションを試してみてください。
bash -c "shopt -s expand_aliases &>/dev/null;
alias myalias='echo foo
echo bar
echo baz'
myalias"
あなたの質問と同じ結果が表示されます。印刷のみ可能ですfoo
。
myalias
正しい(予想)出力を得るためには、@cuonglmが提案したように、その後に少なくとも1行を追加する必要があります。
bash -c "shopt -s expand_aliases &>/dev/null;
alias myalias='echo foo
echo bar
echo baz'
myalias
:"
なぜですか? helpの後に追加の行があるのはなぜですかmyalias
?
私が言うのは、それが言葉にならないということです。 Bashには、この状況を説明または言及する文書はまったくありません。このように行動してはいけません。これは間違いです。コードを読んだ後は、この事実を確実に知ることができます。
問題のある最初のコマンドに戻ります。今回は何も変更する必要はありません。 bashを再コンパイルするだけです。「ONESHOT」が定義されていません。すると、正しい(予想された)出力が得られます。はい、よく聞きました。このコマンドはコンパイル時の設定が異なるため、2 つの異なる動作があります。
定義の有無にかかわらず、ONESHOT
Bashコードは2つの完全に異なるパスを生成します-c "command"
。 ONESHOTが定義されていない場合、-c "command"
対話型コマンドやbashスクリプトなど、ほとんどすべてのbash実行のためのコードパスである通常のコードパスが実行されます。ただし、ONESHOTが定義されている場合は、-c "command"
フォークを回避してパフォーマンスを向上させるように設計された別の特定のパスが実行されます。
この場合、一般的で最も一般的な方法は正しい出力を提供できますが、特定の方法はそうではありません。私は一貫性のない行動がBashの作者が望むものではないと思います。どのような行動が正しいかについては、普段のやり方が正しいと考える傾向があります。
このエラーに関する詳細
次のコードはこのエラーに関連しています。これは buildins/evalstring.c ファイルの parse_and_execute() 関数から来ます。
while (*(bash_input.location.string))
{
...
}
ループwhile
は行単位で実行され、ループ内の1行を処理します。コマンドの最後の読み取り行以降myalias
(上記参照)条件はwhile
falseになります。myalias
3行のエコーに拡張されましたが、今回は1つのエコーのみが処理されます。残りの2つのエコーは次のループで処理されますが...他のループはありません。
myalias
読んだ後に別の行を追加すると、myalias
inの条件はwhile
trueに保たれるため、他の2つのエコーは次のループで実行される機会があります。その後の最後の行は、myalias
すべての拡張エコーが処理された後に処理されます。myalias
修正する
この質問に関連するBashのバージョンは次のとおりです。
GNU bash, version 4.4.12(1)-release (x86_64-pc-linux-gnu)