Eu tenho o seguinte script simples em que estou executando um loop e quero manter um COUNTER
. Não consigo descobrir por que o contador não está atualizando. É devido ao subshell que está sendo criado? Como posso corrigir isso potencialmente?
#!/bin/bash
WFY_PATH=/var/log/nginx
WFY_FILE=error.log
COUNTER=0
grep 'GET /log_' $WFY_PATH/$WFY_FILE | grep 'upstream timed out' | awk -F ', ' '{print $2,$4,$0}' | awk '{print "http://domain.com"$5"&ip="$2"&date="$7"&time="$8"&end=1"}' | awk -F '&end=1' '{print $1"&end=1"}' |
(
while read WFY_URL
do
echo $WFY_URL #Some more action
COUNTER=$((COUNTER+1))
done
)
echo $COUNTER # output = 0
Respostas:
Primeiro, você não está aumentando o contador. Mudar
COUNTER=$((COUNTER))
paraCOUNTER=$((COUNTER + 1))
ouCOUNTER=$[COUNTER + 1]
aumentará.Segundo, é mais difícil propagar novamente as variáveis do subshell para o receptor conforme você supõe. Variáveis em um subshell não estão disponíveis fora do subshell. Essas são variáveis locais para o processo filho.
Uma maneira de resolvê-lo é usar um arquivo temporário para armazenar o valor intermediário:
fonte
$[...]
estar obsoleta? Existe uma solução alternativa?$[...]
foi usado porbash
antes$((...))
foi adotado pelo shell POSIX. Não tenho certeza de que alguma vez foi formalmente reprovado, mas não encontro menção a isso nabash
página de manual e parece ser suportado apenas para compatibilidade com versões anteriores....
FESTA TESTADA: Centos, SuSE, RH
fonte
$[ ]
sintaxe foi preterida. stackoverflow.com/questions/10515964/…é uma construção bastante desajeitada na programação moderna.
parece mais "moderno". Você também pode usar
se você acha que melhora a legibilidade. Às vezes, Bash oferece muitas maneiras de fazer as coisas - filosofia Perl, suponho - quando talvez o Python "só existe uma maneira correta de fazer isso" possa ser mais apropriado. Essa é uma afirmação discutível, se é que houve alguma! De qualquer forma, eu sugeriria que o objetivo (neste caso) não é apenas incrementar uma variável, mas (regra geral) também escrever código que outra pessoa possa entender e apoiar. A conformidade contribui muito para conseguir isso.
HTH
fonte
Tente usar
ao invés de
fonte
let "COUNTER++"
(( COUNTER++ ))
(sem cifrão)(( COUNTER++ ))
mas quando mudei paraCOUNTER=$((COUNTER + 1))
ele funcionou.GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
Acho que essa chamada única do awk é equivalente ao seu
grep|grep|awk|awk
pipeline: teste-a. Seu último comando awk parece não mudar nada.O problema com o COUNTER é que o loop while está sendo executado em um subshell, portanto, quaisquer alterações na variável desaparecem quando o subshell sai. Você precisa acessar o valor de COUNTER no mesmo subshell. Ou siga o conselho de @ DennisWilliamson, use uma substituição de processo e evite completamente o subshell.
fonte
fonte
Em vez de usar um arquivo temporário, você pode evitar a criação de um subshell ao redor do
while
loop usando a substituição do processo.A propósito, você deve conseguir transformar tudo isso
grep, grep, awk, awk, awk
em um únicoawk
.Começando com o Bash 4.2, existe uma
lastpipe
opção quefonte
lastpipe
. A propósito, você provavelmente deve usar"${PIPESTATUS[@]}"
(em vez de asterisco).minimalista
fonte
É tudo o que você precisa fazer:
Aqui está um trecho de Learning the bash Shell , 3a edição, pp. 147, 148:
..........................
Consulte http://www.safaribooksonline.com/a/learning-the-bash/7572399/
fonte
if
declaração:if [[ $((needsComma++)) -gt 0 ]]; then printf ',\n'; fi
Certo ou errado, esta é a única versão que funcionou de maneira confiável.i=1; while true; do echo $((i++)); sleep .1; done
if (( needsComma++ > 0 )); then
ouif (( needsComma++ )); then
Este é um exemplo simples
fonte
Parece que você não atualizou
counter
o script, usecounter++
fonte
Houve duas condições que causaram uma
((var++))
falha na expressão :Se eu definir o bash no modo estrito (
set -euo pipefail
) e se eu iniciar o incremento em zero (0).Iniciar um (1) é bom, mas zero faz com que o incremento retorne "1" ao avaliar "++", que é uma falha de código de retorno diferente de zero no modo estrito.
Eu posso usar
((var+=1))
ouvar=$((var+1))
escapar desse comportamentofonte
O script de origem tem algum problema com o subshell. Primeiro exemplo, você provavelmente não precisa do subshell. Mas não sabemos o que está oculto em "Um pouco mais de ação". A resposta mais popular tem bug oculto, que aumentará a E / S e não funcionará com subshell, porque restaura o loop interno do couter.
Não adicione o sinal '\', ele informará o intérprete do bash sobre a continuação da linha. Espero que ajude você ou qualquer um. Mas, na minha opinião, esse script deve ser totalmente convertido em script AWK, ou reescrito em python usando regexp ou perl, mas a popularidade do perl ao longo dos anos é degradada. Melhor fazê-lo com python.
Versão corrigida sem subcamada:
Versão com subshell se for realmente necessário
fonte