ทำไม systemctl \ {restart, status} \ sshd \; งาน?


14

เอาต์พุตของคำสั่งด้านบนเมื่อส่งผ่าน echo คือ:

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

แม้ว่าฉันจะวางเอาต์พุตไปที่เทอร์มินัลก็ตาม แต่เมื่อฉันพยายามเรียกใช้คำสั่งโดยตรงฉันจะได้รับ:

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

ฉันมีสองคำถาม ..

  1. วิธีการทดแทนและการขยายตัวนี้เรียกว่าอะไรกันแน่? (เพื่อให้ฉันสามารถค้นคว้าและเรียนรู้เพิ่มเติมเกี่ยวกับมันและวิธีการใช้อย่างถูกต้อง)
  2. ฉันทำอะไรผิดที่นี่ ทำไมมันไม่ทำงาน

คำตอบ:


26

มันเป็นรูปแบบของการขยายตัวรั้งทำในเปลือก แนวคิดการขยายรั้งนั้นถูกต้อง แต่วิธีการใช้งานนั้นไม่ถูกต้องที่นี่ เมื่อคุณตั้งใจจะทำ:

systemctl\ {restart,status}\ sshd\;

เชลล์ตีความsystemctl restart sshd;เป็นคำสั่งยาว ๆ และพยายามเรียกใช้และไม่สามารถหาไบนารีเพื่อให้ทำงานได้ เพราะในขั้นตอนนี้เชลล์พยายามที่จะทำเครื่องหมายรายการในบรรทัดคำสั่งก่อนสร้างคำสั่งทั้งหมดด้วยอาร์กิวเมนต์ - แต่มันยังไม่เกิดขึ้น

สำหรับค่าส่วนขยายที่ทราบดังกล่าวคุณสามารถใช้evalและยังปลอดภัย แต่ต้องแน่ใจว่าคุณกำลังพยายามขยายด้วย

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

แต่ฉันอยากจะใช้ loop แทนforแทนที่จะพยายามเขียน one-liner หรือใช้eval:

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

19

สิ่งนี้เรียกว่าการขยายรั้ง (ตามที่แท็กระบุ)

ฉันทำอะไรผิดที่นี่ ทำไมมันไม่ทำงาน

พิจารณาขั้นตอนที่เกี่ยวข้องกับการอ่านและการดำเนินการบรรทัดคำสั่งใน bash (ตัวอย่าง):

  1. อ่านบรรทัด
  2. วิเคราะห์คำสั่งผสมที่อาจเป็นคำสั่งง่าย ๆ
  3. ทำการขยายคำสั่งต่าง ๆ อย่างง่าย (การขยายรั้ง, การแยกคำ, การวนซ้ำ ฯลฯ )
  4. จากนั้นเรียกใช้งานคำสั่งง่าย ๆ (โดยมีขั้นตอนอื่นที่ละเว้นเพื่อความชัดเจน)

สิ่งที่คุณพยายามทำมีผลกับ (2) จาก (3) การแยกที่;อยู่ในขั้นตอนที่ (2) เมื่อแยกวิเคราะห์คำสั่งผสม เมื่อถึงเวลา (3) เกิดขึ้นสำหรับการขยายรั้งมันสายเกินไปที่จะลองและสร้างคำสั่งผสม


6

บรรทัดแรก

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

ขยายเป็น 3 โทเค็น

  • เสียงสะท้อน
  • systemctl รีสตาร์ท sshd;
  • สถานะ systemctl sshd;

จากนั้น echo echo สองโทเค็นสุดท้ายและดูเหมือนว่าตกลง

เช่นเดียวกันกับบรรทัดที่สอง

systemctl\ {restart,status}\ sshd\;

ขยายเป็น 2 โทเค็น

  • systemctl รีสตาร์ท sshd;
  • สถานะ systemctl sshd;

และ bash พยายามค้นหาไฟล์systemctl restart sshd;ที่เรียกใช้ซึ่งหาไม่ได้

คุณอาจต้องการเริ่มต้นการเดินทางของคุณในด้านมืดโดยใช้eval systemctl\ {restart,status}\ sshd\;สิ่งที่ไม่คาดคิด


ดังนั้นวิธีแก้ก็คือการแยกคำใช่ไหม? สิ่งนี้สามารถทำได้?
Somenath Sinha
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.