bash, retorno do loop redirecionado, é seguro?

7

Observe que retornamos de um loop, que é redirecionado.

Eu não sei, se eu deveria me preocupar com o buffer de gravação de "arquivo".

function f {
    i=1
    while :
    do
        echo aaaaaaaaaaaaabbbbbbbbbbbbbbbbb
        ((i++))
        if [ $i -gt 3 ]
        then
            return    # return while redirected
        fi
    done >> file    # writing to file
}

f

NOTA: Estou ciente de que essa função pode ser facilmente reescrita, de modo que não retorne de dentro do loop redirecionado. No entanto, este é apenas um exemplo simplificado para o propósito desta questão.

Então, por favor, não tente melhorar este código.

Também não estou interessado em soluções alternativas.

Minha única pergunta é se há algo que eu deveria estar particularmente ciente. Como o descritor de arquivo não está fechado corretamente. Ou, às vezes, posso esperar que apenas metade do buffer (ou seja, "aaaaaa") seja gravada no arquivo.

Gostaria de saber se é uma ideia muito ruim e por quê? Ou talvez funcionasse sem condições de corrida imprevistas ou similares? (mas, novamente, eu não quero respostas como "é ruim porque você deveria usar este e este padrão")

    
por Zoltan K. 15.06.2017 / 23:13

1 resposta

11

Enquanto cada comando pode ter seu próprio buffer de gravação, não há buffer de gravação que seja compartilhado entre os comandos, mesmo embutidos no bash (ou até mesmo duas invocações de um mesmo comando, embutido ou não).

Mesmo o ksh93, que é conhecido por fazer alguma otimização de E / S (por exemplo, ele lerá adiante e compartilhará alguns dados em entrada ( causando alguns bugs )), não faz isso.

Então, será seguro a esse respeito. Depois que um comando é concluído, como o seu echo aaaaaaaaaaaaabbbbbbbbbbbbbbbbb , e desde que ele não bifurque o processo autônomo em execução em segundo plano, você pode ter certeza de que toda a E / S foi concluída.

Algumas notas embora. Em uma função como:

f() {
  {
    echo x
    return
    echo y
  } > file
  echo something else
}

No shell Bourne (e somente no shell Bourne), esse return interromperia a saída do grupo de comandos interno, mas não retornaria da função como no antigo shell, esse grupo de comandos seria executado em um subshell por causa de o redirecionamento (assim você veria o something else ).

Isso não acontece mais em shells modernos como bash , mas você teria o mesmo problema no bash se você escrevesse:

f() {
  (
    echo x
    return
    echo y
  ) > file
  echo something else
}

ou

f() {
  {
    echo x
    return
    echo y
  } | tr xy ab
  echo something else
}

Cuidado, há casos em que alguns comandos não são esperados. Em:

f() {
  {
    echo >(sleep 1; echo x)
    return
  } > file
}
f; cat file

Você pode descobrir que x não aparece porque cat é executado antes de echo x .

Alguns shells (embora não bash ) têm problemas potenciais similares com componentes de pipeline que não são os mais adequados à direita.

    
por 15.06.2017 / 23:40