Mengapa systemctl \ {restart, status} \ sshd \; kerja?

14

Output dari perintah di atas ketika melewati echo adalah:

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

Bahkan jika saya menempelkan output ke terminal, perintah itu berfungsi. Tetapi ketika saya mencoba menjalankan perintah secara langsung, saya mendapatkan:

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

Saya punya dua pertanyaan ..

  1. Apa sebenarnya yang disebut metode substitusi dan ekspansi ini? (Sehingga saya bisa meneliti dan belajar lebih banyak tentang itu dan bagaimana menggunakannya dengan benar).
  2. Apa yang saya lakukan salah di sini? Mengapa itu tidak berhasil?
Somenath Sinha
sumber

Jawaban:

26

Ini adalah bentuk ekspansi Brace yang dilakukan di shell. Gagasan brace-ekspansi benar, tetapi cara itu digunakan tidak benar di sini. Ketika Anda bermaksud melakukan:

systemctl\ {restart,status}\ sshd\;

Shell mengartikan systemctl restart sshd;sebagai satu perintah panjang dan mencoba menjalankannya, dan ia tidak dapat menemukan biner untuk menjalankannya seperti itu. Karena pada tahap ini, shell mencoba tokenize item di baris perintah sebelum membangun perintah lengkap dengan argumen - tetapi belum terjadi.

Untuk nilai ekspansi yang diketahui seperti itu, Anda bisa menggunakan evaldan masih aman, tetapi pastikan apa yang Anda coba kembangkan dengan itu.

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

Tapi saya lebih suka menggunakan loop sebagai gantinya for, daripada mencoba menulis one-liner atau menggunakan eval:

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

Ini disebut brace expansion (seperti yang ditunjukkan oleh tag).

Apa yang saya lakukan salah di sini? Mengapa itu tidak berhasil?

Pertimbangkan tahapan yang terlibat dalam membaca dan mengeksekusi baris perintah di bash (misalnya):

  1. membaca garis
  2. mem-parsing perintah yang mungkin majemuk menjadi perintah sederhana komponen
  3. melakukan berbagai ekspansi pada perintah sederhana (brace expansion, word splitting, globbing, dll.)
  4. kemudian jalankan perintah sederhana (dengan tahapan lain dihilangkan untuk kejelasan).

Apa yang Anda coba lakukan adalah memengaruhi (2) dari (3). Pemisahan berdasarkan pada ;tahap (2), ketika itu menguraikan perintah majemuk. Pada saat (3) terjadi untuk ekspansi brace, sudah terlambat untuk mencoba dan membuat perintah gabungan.

muru
sumber
6

Baris pertama

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

perluas 3 token

  • gema
  • systemctl restart sshd;
  • status sistemctl sshd;

kemudian gema gema dua token terakhir, dan itu terlihat OK.

juga baris kedua

systemctl\ {restart,status}\ sshd\;

diperluas sebagai 2 token

  • systemctl restart sshd;
  • status sistemctl sshd;

dan bash mencoba mencari executable systemctl restart sshd;yang tidak dapat ditemukannya.

Anda mungkin ingin memulai perjalanan Anda di sisi gelap menggunakan eval systemctl\ {restart,status}\ sshd\;waspada terhadap yang tak terduga.

Archemar
sumber
jadi, solusinya adalah pemisahan kata, bukan? Bagaimana ini bisa dilakukan?
Somenath Sinha