Почему не 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

Это форма расширения Brace, выполняемая в оболочке. Идея расширения скобки верна, но то, как она использовалась, здесь неверно. Когда вы хотели сделать:

systemctl\ {restart,status}\ sshd\;

Оболочка интерпретируется systemctl restart sshd;как одна длинная команда и пытается выполнить ее, и она не может найти двоичный файл для ее запуска таким образом. Потому что на этом этапе оболочка пытается токенизировать элементы в командной строке перед созданием полной команды с аргументами - но это еще не произошло.

Для таких известных значений расширения вы можете использовать evalи при этом быть в безопасности, но будьте уверены в том, что вы пытаетесь расширить с помощью него.

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

Но я бы предпочел использовать цикл вместо for, вместо того, чтобы пытаться написать однострочник или использовать eval:

for action in restart status; do
    systemctl "$action" sshd
done
Inian
источник
19

Это называется расширением скобок (как указывает тег).

Что я тут не так сделал? Почему это не работает?

Рассмотрим этапы, связанные с чтением и выполнением командной строки в bash (например):

  1. читает строку
  2. разбирает возможную составную команду на простые компоненты
  3. выполняет различные расширения простых команд (расширение фигурных скобок, разбиение слов, глобирование и т. д.)
  4. затем выполняет простые команды (другие этапы для ясности опущены).

То, что вы пытаетесь сделать, это повлиять на (2) из ​​(3). Разделение на основе ;находится на этапе (2), когда он анализирует составные команды. К тому времени, когда (3) происходит расширение скобки, уже слишком поздно пытаться создать составную команду.

Мур
источник
6

Первая строка

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

расширить как 3 токена

  • эхо
  • systemctl перезапустить sshd;
  • systemctl status sshd;

затем эхо эхо последних двух токенов, и это выглядит хорошо.

аналогично второй строке

systemctl\ {restart,status}\ sshd\;

расширяется как 2 токена

  • systemctl перезапустить sshd;
  • systemctl status sshd;

и bash пытаются найти исполняемый файл, systemctl restart sshd;который он не может найти.

Возможно, вы захотите начать свое путешествие на темной стороне, eval systemctl\ {restart,status}\ sshd\;остерегаясь неожиданного.

Archemar
источник
Таким образом, решение будет разделение слов, верно? Как это может быть сделано?
Somenath Sinha