systemctl\{restart,status}\sshd\; が機能しないのはなぜですか?

systemctl\{restart,status}\sshd\; が機能しないのはなぜですか?

echo以降、上記のコマンドの出力は次のようになります。

# 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. 私がここで何を間違っているのか?なぜ動作しないのですか?

答え1

それは形ですサポート拡張シェルで完了しました。支柱の拡張という概念は正しいですが、ここで使用されている方法は正しくありません。これを行うとき:

systemctl\ {restart,status}\ sshd\;

シェルはこれをsystemctl restart sshd;長いコマンドとして解釈して実行しようとしますが、この方法で実行するバイナリを見つけることができません。この段階では、シェルは引数を使用して完全なコマンドを作成する前に、コマンドラインのエントリにタグを付けようとしましたが、まだそのようなことは発生していません。

これらの既知の拡張値の場合は使用できますevalが、それでも安全ですが、それを使用して拡張したいものが何であるかを確認してください。

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

forしかし、私は行を書いたり、次を使うよりもループを使いたいと思いますeval

for action in restart status; do
    systemctl "$action" sshd
done

答え2

これは…支柱の拡張(ラベルに示すように)。

私がここで何を間違っているのか?なぜ動作しないのですか?

たとえば、Bashでコマンドラインを読み取って実行する手順を考えてみましょう。

  1. 一行を読む
  2. 可能な複合コマンドをコンポーネント単純コマンドに解析
  3. 簡単なコマンドに対するさまざまな拡張(中括弧拡張、ワードセパレータ、ワイルドカードなど)
  4. その後、単純なコマンドが実行されます(明確にするために他の手順は省略されています)。

あなたがしたいことは(3)の(2)に影響を与えることです。分割は、;複合コマンドを解析するステップ(2)に基づいています。中かっこ拡張が発生したとき(3)は、複合コマンドを生成するにはすでに遅すぎました。

答え3

最初の行

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

トークンを3つに拡張

  • エコ
  • systemctl restart sshd;
  • systemctlステータスsshd;

その後、最後の2つのマーカーをエコエコーするとよさそうです。

同じ2行目

systemctl\ {restart,status}\ sshd\;

トークンを2つに拡張

  • systemctl restart sshd;
  • systemctlステータスsshd;

systemctl restart sshd;bashは見つからない実行可能ファイルを見つけようとします。

あなたは暗い面で旅行を始め、eval systemctl\ {restart,status}\ sshd\;予期しないことに気をつけたいかもしれません。

関連情報