web-dev-qa-db-ja.com

systemctl \ {restart、status} \ sshd \;を実行しないのはなぜですか。作業?

エコーを通過したときの上記のコマンドの出力は次のとおりです。

# echo systemctl\ {restart,status}\ sshd\;
systemctl restart sshd; systemctl status sshd;

出力をターミナルに貼り付けても、コマンドは機能します。しかし、コマンドを直接実行しようとすると、次のようになります。

# systemctl\ {restart,status}\ sshd\;
bash: systemctl restart sshd;: command not found...

2つの質問があります。

  1. この置換と拡張の方法は正確には何と呼ばれていますか? (私はそれを研究し、それについて、そしてそれを適切に使用する方法を学ぶことができるように)。
  2. ここで何を間違えたのですか?なぜ機能しないのですか?
14
Somenath Sinha

シェルで行われる ブレース展開 の形式です。ブレース展開のアイデアは正しいですが、使用方法はここでは正しくありません。あなたがするつもりだったとき:

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
26
Inian

これは ブレース展開 と呼ばれます(タグが示すとおり)。

ここで何を間違えたのですか?なぜ機能しないのですか?

Bashでのコマンドラインの読み取りと実行に関連するステージを検討してください(例):

  1. 行を読みます
  2. 複合コマンドを解析して、コンポーネントの単純なコマンドに変換します
  3. 単純なコマンドでさまざまな拡張を行います(中括弧拡張、ワード分割、グロビングなど)。
  4. 次に、単純なコマンドを実行します(明確にするために他のステージは省略されています)。

あなたがしようとしているのは、(3)から(2)に影響を与えることです。 ;に基づく分割は、複合コマンドを解析する段階(2)にあります。ブレース拡張のために(3)が発生するまでに、複合コマンドを作成して作成するのはすでに遅すぎます。

19
muru

最初の行

echo systemctl\ {restart,status}\ sshd\;

3トークンとして展開

  • エコー
  • systemctl restart sshd;
  • systemctl status sshd;

次に、echoは最後の2つのトークンをエコーし​​ます。

同様に2行目

systemctl\ {restart,status}\ sshd\;

2つのトークンとして展開

  • systemctl restart sshd;
  • systemctl status sshd;

そしてbashは見つけられなかった実行可能ファイルsystemctl restart sshd;を探します。

予期せぬことに注意して、eval systemctl\ {restart,status}\ sshd\;を使用してダークサイドから旅を始めることもできます。

6
Archemar