Suponha que eu leia (cat) um arquivo enquanto outro processo reescreve seu conteúdo. A saída é previsível? O que aconteceria?
Responder1
Isso depende do que o escritor faz.
Se o escritor substituir o arquivo existente, o leitor verá o novo conteúdo quando o escritor ultrapassar o leitor, se isso acontecer. Se o escritor e o leitor prosseguirem em velocidades variáveis, o leitor poderá ver alternativamente conteúdo antigo e novo.
Se o gravador truncar o arquivo antes de começar a gravar, o leitor será executado no final do arquivo nesse ponto.
Se o gravador criar um novo arquivo e depois mover o novo arquivo para o nome antigo, o leitor continuará lendo o arquivo antigo. Se um arquivo aberto for movido ou removido, os processos que possuem o arquivo aberto continuarão lendo esse mesmo arquivo. Se o arquivo for removido, ele permanecerá no disco (mas não será possível abri-lo novamente) até que o último processo o feche.
Os sistemas Unix tendem a não ter obrigatoriedadefechaduras. Se um aplicativo quiser garantir que seu componente gravador e seu componente leitor não se atrapalhem, cabe ao desenvolvedor usar o bloqueio adequado. Existem algumas exceções em que um arquivo aberto pelo kernel pode ser protegido contra gravação por aplicativos de usuário, por exemplo, umlaçoimagem do sistema de arquivos montada ou um executável que está sendo executado em algumas variantes do Unix.
Responder2
É uma condição de corrida clássica, portanto o resultado é imprevisível por definição.
Entre outros, depende
fopen(3)
ouopen(2)
modos de gravação,- como/se o gravador está armazenando em buffer sua saída,
- como o leitor está lendo o arquivo,
- a diferença de velocidade entre o leitor e o escritor,
- a diferença de tempo entre o início da leitura e do escritor.
- E, claro, em máquinas multi-core modernas, as coisas são ainda mais complicadas por outros fatores mais abaixo (por exemplo, agendamento de processos).
Se você precisar ler um arquivo enquanto ele está sendo reescrito, poderá fazer com que o gravador faça uma cópia transitória do arquivo, modifique-o e copie-o de volta para o arquivo original. É assim que rsync
faz isso, por exemplo. Existem várias maneiras de implementar isso, mas não há almoço grátis. Cada método tem suas próprias deficiências e repercussões.
Responder3
Os respondentes anteriores têm explicações mais abrangentes do que isso, mas aqui está um truque que definitivamente também funciona, fazendo exatamente o que ele quer:
$ tail -f <filename>
Mostrará o final do arquivo enquanto ele está sendo escrito. Útil se você deseja canalizar STDERR para um arquivo, mas ainda vê-lo em outra janela de terminal, por exemplo.