[Bash Challenge 9] Você consegue resolver este quebra-cabeça do Bash Script?

23 de julho de 2017

Bem-vindo ao Bash Challenge # 9 de Yes I Know IT e It's FOSS. Neste desafio semanal mostraremos uma tela do terminal e contaremos com você para nos ajudar a obter o resultado que desejamos. Pode haver muitas soluções, e ser criativo é a parte mais divertida do desafio.

Se você ainda não fez isso, dê uma olhada nos desafios anteriores:

Você também pode comprar esses desafios (com desafios não publicados) na forma de livro e nos apoiar:

Pronto para jogar? Então, aqui está o desafio desta semana:

Minhas saídas de comando estão na ordem errada!

Esta semana, quero que uma função shell registre o tempo de ida e volta ( rtt ) em um servidor. Somente se o comando ping foi bem-sucedido, desejo registrar a data da medida na linha abaixo do rtt . Dados esses requisitos, acabo com a solução:

Comandos para usar no terminal

probe() ( ping -qnc2 www.google.com | grep rtt & date +"OK %D %T" ) rm -f log probe >> log probe >> log cat log

Mas, por algum motivo, as linhas date e rtt são trocadas no arquivo de log?!? Por quê? Você poderia consertar isso? Existe uma maneira mais limpa de atingir meu objetivo?

Responder a essas perguntas é o seu desafio.

Alguns detalhes

Para criar este desafio, usei:

  • GNU Bash, versão 4.4.5 (x86_64-pc-linux-gnu)
  • Debian 4.8.7-1 (amd64)
  • Todos os comandos são fornecidos com uma distribuição Debian padrão
  • Nenhum comando recebeu alias

A solução

Como reproduzir

Aqui está o código bruto que usamos para produzir este desafio. Se você executá-lo em um terminal, poderá reproduzir exatamente o mesmo resultado exibido na ilustração do desafio (presumindo que você esteja usando a mesma versão de software que eu):

Comandos para usar no terminal

rm -rf ItsFOSS mkdir -p ItsFOSS cd ItsFOSS clear probe() ( ping -qnc2 www.google.com | grep rtt & date +"OK %D %T" ) rm -f log probe >> log probe >> log cat log

Qual era o problema?

Eu simplesmente cometi um erro de digitação: eu confundi & com && - talvez eu tenha ficado confuso com o símbolo de barra vertical (|) acima? Na verdade, todos os operadores |, & e && podem ser usados para unir dois comandos de shell. Mas eles têm significados completamente diferentes:

cmd1 | cmd2 O cano

Execute os dois comandos em paralelo em um sub-shell, usando a saída de cmd1 como entrada para cmd2. O pipe é uma forma muito comum de combinar vários comandos básicos para realizar tarefas complexas.

cmd1 e cmd2 O e comercial

Execute cmd1 como um processo em segundo plano e em paralelo , para executar cmd2 em primeiro plano. Os dois comandos não são conectados de forma alguma usando esse operador.

cmd1 || cmd2 O curto-circuito lógico OU

Execute cmd2 apenas se cmd1 falhou . Como consequência, cmd1 deve ser concluído antes que cmd2 seja executado. Em outras palavras, os comandos são executados sequencialmente .

cmd1 && cmd2 O E lógico de curto-circuito

Execute cmd2 apenas se cmd1 foi bem-sucedido . Como consequência, cmd1 deve ser concluído antes que cmd2 seja executado. Em outras palavras, os comandos são executados sequencialmente .

Munidos desse conhecimento, vamos agora revisar meu código original:

Comandos para usar no terminal

probe() ( ping -qnc2 www.google.com | grep rtt & date +"OK %D %T" )

  1. Desejo executar o comando ping e enviar sua saída para o comando grep . O tubo é o operador certo. 2. Mas depois disso, eu queria escrever a data apenas se o pipe fosse bem-sucedido . Aqui, eu precisava do operador lógico AND ( && ). Mas em vez disso, usei o operador & , que basicamente executa ping | grep em segundo plano - sempre. E data em primeiro plano - sempre. Há uma condição de corrida, pois os dois processos agora estão executando em paralelo e competem para escrever no stdout. Não é novidade que, naquele exemplo específico, o comando date venceu todas as vezes sobre o comando ping . Portanto, a sintaxe correta seria:

Comandos para usar no terminal

probe() ( ping -qnc2 www.google.com | grep rtt && date +"OK %D %T" )

No meu caso, o problema foi imediatamente visível porque, obviamente, o comando ping leva mais tempo para ser concluído do que o comando date . Mas como é frequentemente o caso com condições de corrida, tais erros podem facilmente permanecer ocultos por muito tempo. Por exemplo, o exemplo a seguir é muito menos determinístico:

Comandos para usar no terminal

probe() ( ping -qnc2 itsfoss.com | sed 1q & ping -qnc2 kernel.org | sed 1q )

De minha localização na França, em 2.000 execuções, o primeiro ping perdeu apenas 3 vezes. Isso significa que o bug era visível apenas em 0,15% dos casos. Da próxima vez que você relatar alguma falha de software ocasional - seja gentil com seus desenvolvedores FOSS favoritos e lembre-se de que mesmo causado por erros aparentemente menores, as condições de corrida são difíceis de reproduzir e ainda mais difíceis de rastrear!

Mas talvez você conheça algumas ferramentas de teste que podem ajudar a identificar erros de digitação em scripts Bash? Se for esse o caso, não hesite em compartilhar conosco usando a seção de comentários abaixo!

E não se esqueça de ficar ligado para mais diversão.

Confira também a versão original desse post em inglês
Esse post foi originalmente escrito por Sylvain Leroux e publicado no site itsfoss.com. Tradução sujeita a revisão.

[Bash Challenge 9] Can You Solve This Bash Script Puzzle?

Propaganda
Blog Comments powered by Disqus.
Propaganda