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:
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):
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:
probe() ( ping -qnc2 www.google.com | grep rtt & date +"OK %D %T" )
- 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:
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:
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.
Via itsfoss.com. Você pode conferir o post original em inglês:
[Bash Challenge 9] Can You Solve This Bash Script Puzzle?Última atualização deste artigo: 23 de july de 2017