systemctl \ {restart、status} \ sshd \;が実行されない理由 作業?


14

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

# 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. ここで何を間違えましたか?なぜ機能しないのですか?

回答:


26

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

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

19

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

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

(たとえば)bashでコマンドラインを読み取って実行する段階を検討します。

  1. 行を読む
  2. おそらく複合コマンドをコンポーネントの単純なコマンドに解析します
  3. 単純なコマンドでさまざまな展開を行います(ブレース展開、単語分割、グロビングなど)
  4. 次に、単純なコマンドを実行します(明確にするために他の段階は省略します)。

あなたがやろうとしているのは、(3)から(2)に影響することです。に基づく分割;は、複合コマンドを解析する段階(2)にあります。ブレースの展開で(3)が発生する頃には、複合コマンドを作成しようとするのはもう手遅れです。


6

最初の行

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

3トークンとして展開

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

その後、最後の2つのトークンをエコーすると、OKに見えます。

同様に2行目

systemctl\ {restart,status}\ sshd\;

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

  • systemctl restart sshd;
  • systemctl status sshd;

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

eval systemctl\ {restart,status}\ sshd\;予期せぬことに注意して、ダークサイドで旅を始めたいと思うかもしれません。


そのため、解決策は単語分割です。これをどのように行うことができますか?
Somenathシンハ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.