Pourquoi systemctl \ {restart, status} \ sshd \; travail?

14

Le résultat de la commande ci-dessus lorsqu'elle est passée par écho est:

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

Même si je colle la sortie sur le terminal, la commande fonctionne. Mais lorsque j'essaie d'exécuter directement la commande, j'obtiens:

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

J'ai deux questions..

  1. Comment s'appelle exactement cette méthode de substitution et d'expansion? (Pour que je puisse le rechercher et en savoir plus à ce sujet et comment l'utiliser correctement).
  2. Qu'est-ce que j'ai fait de mal ici? Pourquoi ça ne marche pas?
Somenath Sinha
la source

Réponses:

26

C'est une forme d' expansion de Brace réalisée dans la coque. L'idée de l'accolade est correcte, mais la façon dont elle a été utilisée est incorrecte ici. Quand vous vouliez faire:

systemctl\ {restart,status}\ sshd\;

Le shell interprète systemctl restart sshd;comme une seule commande longue et essaie de l'exécuter, et il n'a pas pu localiser un binaire pour l'exécuter de cette façon. Parce qu'à ce stade, le shell essaie de symboliser les éléments de la ligne de commande avant de générer la commande complète avec des arguments - mais cela ne s'est pas encore produit.

Pour de telles valeurs d'expansion connues, vous pouvez utiliser evalet toujours être sûr, mais assurez-vous de ce que vous essayez d'étendre avec.

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

Mais je préfère utiliser une boucle à la place avec for, au lieu d'essayer d'écrire une ligne ou d'utiliser eval:

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

C'est ce qu'on appelle l' expansion de l'accolade (comme l'indique la balise).

Qu'est-ce que j'ai fait de mal ici? Pourquoi ça ne marche pas?

Considérez les étapes impliquées dans la lecture et l'exécution d'une ligne de commande dans bash (par exemple):

  1. lit une ligne
  2. analyse une commande éventuellement composée en commandes simples de composants
  3. fait diverses extensions sur les commandes simples (expansion d'accolade, fractionnement de mots, globbing, etc.)
  4. exécute ensuite les commandes simples (avec d'autres étapes omises pour plus de clarté).

Ce que vous essayez de faire, c'est affecter (2) de (3). Le fractionnement basé sur ;est à l'étape (2), lorsqu'il analyse les commandes composées. Au moment où (3) se produit pour l'expansion de l'accolade, il est déjà trop tard pour essayer de créer une commande composée.

muru
la source
6

La première ligne

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

développer en 3 jetons

  • écho
  • systemctl restart sshd;
  • systemctl status sshd;

puis echo echo les deux derniers jetons, et ça a l'air OK.

de même la deuxième ligne

systemctl\ {restart,status}\ sshd\;

se développe en 2 jetons

  • systemctl restart sshd;
  • systemctl status sshd;

et bash essaie de chercher un exécutable systemctl restart sshd;qu'il n'a pas pu trouver.

Vous voudrez peut-être commencer votre voyage du côté obscur en eval systemctl\ {restart,status}\ sshd\;prenant garde à l'inattendu.

Archemar
la source
donc, la solution serait de séparer les mots, non? Comment cela peut-il être fait?
Somenath Sinha