Dlaczego systemctl \ {restart, status} \ sshd \; praca?

14

Wyjście powyższego polecenia po przejściu przez echo to:

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

Nawet jeśli wkleję dane wyjściowe do terminala, polecenie działa. Ale kiedy próbuję bezpośrednio uruchomić polecenie, otrzymuję:

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

Mam dwa pytania..

  1. Jak dokładnie nazywa się ta metoda substytucji i ekspansji? (Aby móc go zbadać i dowiedzieć się więcej na ten temat oraz jak go prawidłowo używać).
  2. Co tutaj zrobiłem źle? Dlaczego to nie działa?
Somenath Sinha
źródło

Odpowiedzi:

26

Jest to forma rozszerzenia Brace wykonywanego w powłoce. Pomysł rozszerzenia nawiasów klamrowych jest słuszny, ale sposób jego użycia jest tutaj niepoprawny. Kiedy chciałeś zrobić:

systemctl\ {restart,status}\ sshd\;

Powłoka interpretuje systemctl restart sshd;jako jedno długie polecenie i próbuje je uruchomić, i nie może znaleźć pliku binarnego, aby uruchomić go w ten sposób. Ponieważ na tym etapie powłoka próbuje tokenizować elementy w wierszu poleceń przed zbudowaniem pełnego polecenia z argumentami - ale to się jeszcze nie zdarzyło.

W przypadku takich znanych wartości rozszerzeń możesz użyć evali nadal być bezpieczny, ale upewnij się, co próbujesz rozszerzyć za jego pomocą.

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

Ale wolałbym zamiast tego użyć pętli for, zamiast próbować napisać jedną linijkę lub użyć eval:

for action in restart status; do
    systemctl "$action" sshd
done
Inian
źródło
19

Nazywa się to rozszerzaniem nawiasów klamrowych (jak wskazuje znacznik).

Co tutaj zrobiłem źle? Dlaczego to nie działa?

Rozważ etapy związane z czytaniem i wykonywaniem linii poleceń w bash (na przykład):

  1. czyta linię
  2. analizuje ewentualnie złożone polecenie w proste polecenia składowe
  3. wykonuje różne rozszerzenia prostych poleceń (rozwijanie nawiasów, dzielenie słów, globowanie itp.)
  4. następnie wykonuje proste polecenia (z innymi etapami pominiętymi dla zachowania przejrzystości).

To, co próbujesz zrobić, wpływa na (2) z (3). Dzielenie oparte ;jest na etapie (2), kiedy analizuje złożone polecenia. Do czasu (3) rozszerzenia nawiasów klamrowych jest już za późno, aby spróbować utworzyć polecenie złożone.

muru
źródło
6

Pierwsza linia

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

rozwiń jako 3 żeton

  • Echo
  • systemctl restart sshd;
  • systemctl status sshd;

następnie powtórz echo dwa ostatnie token i wygląda OK.

podobnie druga linia

systemctl\ {restart,status}\ sshd\;

rozwija się jako 2 żetony

  • systemctl restart sshd;
  • systemctl status sshd;

i bash próbuje poszukać pliku wykonywalnego, systemctl restart sshd;którego nie może znaleźć.

Możesz zacząć podróż po ciemnej stronie, eval systemctl\ {restart,status}\ sshd\;strzeż się nieoczekiwanego.

Archemar
źródło
więc rozwiązaniem byłoby dzielenie słów, prawda? Jak można to zrobić?
Somenath Sinha