Estou atingindo uma condição de corrida no bash?

3

Eu tenho um script que compara a saída de um comando com a saída do mesmo comando que foi executado anteriormente, ele funciona mais do tempo, mas de vez em quando ele não funciona trabalhe como esperado.

Eu consegui reproduzir o problema em uma linha de teste. Eu sei que poderia facilmente dividir isso em comparar dois arquivos separados e o problema desapareceria, mas eu gostaria de entender o que realmente está acontecendo aqui e se há uma maneira de alcançar o que eu estou tentando alcançar da maneira que eu Estou tentando alcançá-lo.

Abaixo está a saída do meu comando executado várias vezes, você pode ver o que ecoa "teste" em um dos casos, mas na maioria das vezes funciona como esperado.

root@dev:~# comm -13 /tmp/test <(echo '"test"' | cut -d'"' -f2 | sort -u | tee /tmp/test)
root@dev:~# comm -13 /tmp/test <(echo '"test"' | cut -d'"' -f2 | sort -u | tee /tmp/test)
root@dev:~# comm -13 /tmp/test <(echo '"test"' | cut -d'"' -f2 | sort -u | tee /tmp/test)
root@dev:~# comm -13 /tmp/test <(echo '"test"' | cut -d'"' -f2 | sort -u | tee /tmp/test)
root@dev:~# comm -13 /tmp/test <(echo '"test"' | cut -d'"' -f2 | sort -u | tee /tmp/test)
test
root@dev:~# comm -13 /tmp/test <(echo '"test"' | cut -d'"' -f2 | sort -u | tee /tmp/test)
root@dev:~# comm -13 /tmp/test <(echo '"test"' | cut -d'"' -f2 | sort -u | tee /tmp/test)
root@dev:~# comm -13 /tmp/test <(echo '"test"' | cut -d'"' -f2 | sort -u | tee /tmp/test)

Estou executando Ubuntu 10.04 , bash 4.1-2ubuntu3.5 e coreutils 7.4-2ubuntu3

    
por Nathan 18.12.2014 / 05:02

2 respostas

5

Sim, essa é uma condição de corrida.

O problema é que o shell inicia todos os processos no pipeline ao mesmo tempo e tee trunca o arquivo de saída na inicialização. Se tee for mais rápido, então comm o arquivo está vazio para a comunicação, caso contrário não é.

O comportamento do pipeline pode ser visto se você executar isso várias vezes (mabe em um loop):

date '+first:  %T'|(cat>&2;sleep 5)|date '+second: %T'
    
por 18.12.2014 / 06:05
1

Sua linha me confundiu um pouco, pois não estava claro o que ambas as ocorrências de "teste" deveriam ser. - Portanto, eu realmente entendo que sua concha também está confusa. ;)

Se eu entendi corretamente, o primeiro "/ tmp / test" deve corresponder à saída antiga do comando e a segunda corresponde à nova saída.

Você pode ter certeza de que stdin conterá a nova saída, mas o conteúdo do arquivo é indefinido: No ponto comm lê esse arquivo, tee talvez ainda não tenha sido iniciado. Nesse caso, ele ainda conterá a antiga linha de "teste" da última execução. Ou tee pode já ter terminado. Nesse caso, ele conterá a linha "test" da execução atual. Ou tee acabou de começar, já limpou o arquivo e está prestes a escrever o novo conteúdo. Se isso acontecer, você irá comparar o "teste" de stdin com o arquivo vazio e você verá sua saída.

Você tem duas saídas diferentes que deseja comparar. Eu não vejo uma maneira de fazer isso sem ter dois arquivos diferentes. Ter dois arquivos diferentes (nomeados corretamente) também torna a linha muito mais legível e resolve a confusão no início. ;)

    
por 18.12.2014 / 08:47