Por que não systemctl \ {restart, status} \ sshd \; trabalhos?

13

A saída do comando acima quando passada pelo eco é:

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

Mesmo se eu colar a saída no terminal, o comando funcionará. Mas quando tento executar diretamente o comando, recebo:

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

Eu tenho duas perguntas ..

  1. O que exatamente é esse método de substituição e expansão chamado? (Para que eu possa pesquisar e aprender mais sobre isso e como usá-lo corretamente).
  2. O que fiz de errado aqui? Por que isso não funciona?
por Somenath Sinha 27.03.2018 / 11:01

3 respostas

25

É uma forma de Expansão de órtese feita no shell. A ideia de expansão de brace está certa, mas a forma como foi usada está incorreta aqui. Quando você pretendia fazer:

systemctl\ {restart,status}\ sshd\;

O shell interpreta systemctl restart sshd; como um comando longo e tenta executá-lo, e não foi possível localizar um binário para executá-lo dessa maneira. Porque neste estágio, o shell tenta tokenizar os itens na linha de comando antes de construir o comando complete com argumentos - mas isso ainda não aconteceu.

Para esses valores de expansão conhecidos, você pode usar eval e ainda ser seguro, mas tenha certeza do que está tentando expandir com ele.

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

Mas eu prefiro usar um loop com for , em vez de tentar escrever um one-liner ou usar eval :

for action in restart status; do
    systemctl "$action" sshd
done
    
por 27.03.2018 / 11:11
19

Isso é chamado de expansão de chave (como a tag indica).

What did I do wrong here? Why doesn't it work?

Considere os estágios envolvidos na leitura e execução de uma linha de comando no bash (por exemplo):

  1. lê uma linha
  2. analisa um comando possivelmente composto em comandos simples de componentes
  3. faz várias expansões nos comandos simples (expansão de chave, divisão de palavras, globbing, etc.)
  4. , em seguida, executa os comandos simples (com outros estágios omitidos para maior clareza).

O que você está tentando fazer é afetar (2) de (3). A divisão baseada em ; está no estágio (2), quando está analisando comandos compostos. Quando o tempo (3) está acontecendo para a expansão de chaves, já é tarde demais para tentar criar um comando composto.

    
por 27.03.2018 / 11:13
6

A primeira linha

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

expanda como 3 token

  • echo
  • systemctl reinicia o sshd;
  • systemctl status sshd;

echo echo os dois últimos token e parece OK.

da mesma forma a segunda linha

systemctl\ {restart,status}\ sshd\;

se expande como 2 tokens

  • systemctl reinicia o sshd;
  • systemctl status sshd;

e o bash tentam procurar por um executável systemctl restart sshd; que não foi encontrado.

Você pode desejar começar sua jornada no lado sombrio usando eval systemctl\ {restart,status}\ sshd\; , cuidado com o inesperado.

    
por 27.03.2018 / 11:10