エコーを通過したときの上記のコマンドの出力は次のとおりです。
# echo systemctl\ {restart,status}\ sshd\;
systemctl restart sshd; systemctl status sshd;
出力をターミナルに貼り付けても、コマンドは機能します。しかし、コマンドを直接実行しようとすると、次のようになります。
# systemctl\ {restart,status}\ sshd\;
bash: systemctl restart sshd;: command not found...
2つの質問があります。
シェルで行われる ブレース展開 の形式です。ブレース展開のアイデアは正しいですが、使用方法はここでは正しくありません。あなたがするつもりだったとき:
systemctl\ {restart,status}\ sshd\;
シェルはsystemctl restart sshd;
を1つの長いコマンドとして解釈して実行しようとしましたが、バイナリを見つけられなかったため、そのように実行できませんでした。この段階では、シェルはコマンドライン内のアイテムをトークン化してから、引数付きの完全なコマンドを作成しようとしますが、まだ行われていません。
そのような既知の展開値の場合、eval
を使用しても安全ですが、それを使用して展開しようとしているものを確認してください。
eval systemctl\ {restart,status}\ sshd\;
ただし、ワンライナーを作成したりfor
を使用したりする代わりに、eval
でループを使用する方がよいでしょう。
for action in restart status; do
systemctl "$action" sshd
done
これは ブレース展開 と呼ばれます(タグが示すとおり)。
ここで何を間違えたのですか?なぜ機能しないのですか?
Bashでのコマンドラインの読み取りと実行に関連するステージを検討してください(例):
あなたがしようとしているのは、(3)から(2)に影響を与えることです。 ;
に基づく分割は、複合コマンドを解析する段階(2)にあります。ブレース拡張のために(3)が発生するまでに、複合コマンドを作成して作成するのはすでに遅すぎます。
最初の行
echo systemctl\ {restart,status}\ sshd\;
3トークンとして展開
次に、echoは最後の2つのトークンをエコーします。
同様に2行目
systemctl\ {restart,status}\ sshd\;
2つのトークンとして展開
そしてbashは見つけられなかった実行可能ファイルsystemctl restart sshd;
を探します。
予期せぬことに注意して、eval systemctl\ {restart,status}\ sshd\;
を使用してダークサイドから旅を始めることもできます。