Tại sao systemctl \ {restart, status} \ sshd \; công việc?


14

Đầu ra của lệnh trên khi truyền qua echo là:

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

Ngay cả khi tôi dán đầu ra vào thiết bị đầu cuối, lệnh vẫn hoạt động. Nhưng khi tôi cố gắng trực tiếp chạy lệnh, tôi nhận được:

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

Tôi có hai câu hỏi..

  1. Chính xác thì phương pháp thay thế và mở rộng này được gọi là gì? (Để tôi có thể nghiên cứu nó và tìm hiểu thêm về nó và cách sử dụng nó đúng cách).
  2. Tôi đã làm gì sai ở đây? Tại sao nó không hoạt động?

Câu trả lời:


26

Nó là một hình thức mở rộng Brace được thực hiện trong vỏ. Ý tưởng mở rộng cú đúp là đúng, nhưng cách nó được sử dụng là không chính xác ở đây. Khi bạn có ý định làm:

systemctl\ {restart,status}\ sshd\;

Shell diễn giải systemctl restart sshd;như một lệnh dài và cố gắng chạy nó, và nó không thể xác định vị trí nhị phân để chạy theo cách đó. Bởi vì ở giai đoạn này, shell cố gắng mã hóa các mục trong dòng lệnh trước khi xây dựng lệnh hoàn chỉnh bằng các đối số - nhưng nó chưa xảy ra.

Đối với các giá trị mở rộng đã biết như vậy, bạn có thể sử dụng evalvà vẫn an toàn, nhưng hãy chắc chắn về những gì bạn đang cố gắng mở rộng với nó.

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

Nhưng tôi thà sử dụng một vòng lặp thay vì for, thay vì cố gắng viết một lớp lót hoặc sử dụng eval:

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

19

Điều này được gọi là mở rộng cú đúp (như thẻ chỉ ra).

Tôi đã làm gì sai ở đây? Tại sao nó không hoạt động?

Hãy xem xét các giai đoạn liên quan đến việc đọc và thực thi một dòng lệnh trong bash (ví dụ):

  1. đọc một dòng
  2. phân tích một lệnh ghép có thể thành các lệnh đơn giản thành phần
  3. thực hiện các mở rộng khác nhau trên các lệnh đơn giản (mở rộng dấu ngoặc, tách từ, nối tiếp, v.v.)
  4. sau đó thực thi các lệnh đơn giản (với các giai đoạn khác được bỏ qua cho rõ ràng).

Những gì bạn đang cố gắng làm là ảnh hưởng đến (2) từ (3). Việc phân tách dựa trên ;là trong giai đoạn (2), khi nó phân tích cú pháp các lệnh ghép. Vào thời điểm (3) đang diễn ra để mở rộng cú đúp, đã quá muộn để thử và tạo một lệnh ghép.


6

Dòng đầu tiên

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

mở rộng dưới dạng 3 mã thông báo

  • tiếng vang
  • khởi động lại hệ thống sshd;
  • trạng thái systemctl sshd;

sau đó lặp lại echo hai mã thông báo cuối cùng và có vẻ ổn.

tương tự dòng thứ hai

systemctl\ {restart,status}\ sshd\;

mở rộng thành 2 mã thông báo

  • khởi động lại hệ thống sshd;
  • trạng thái systemctl sshd;

và bash cố gắng tìm kiếm một thực thi systemctl restart sshd; mà nó không thể tìm thấy.

Bạn có thể muốn bắt đầu cuộc hành trình của mình trên mặt tối bằng cách sử dụng eval systemctl\ {restart,status}\ sshd\;những điều không mong muốn.


Vì vậy, giải pháp sẽ là tách từ, phải không? Điều này có thể giải quyết như thế nào?
Somenath Sinha 27/03/18
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.