O bash abre arquivos no O_APPEND ao usar ">>" no linux?

38

Se usarmos echo 1234 >> some-file, a Documentação diz que a saída é anexada.

Meu palpite é que, se algum arquivo não existir, o O_CREAT criará um novo arquivo. Se >foi usado, o O_TRUNC truncará o arquivo existente.

No caso de >>: O arquivo será aberto como O_WRONLY (ou O_RDWR) e será solicitado que a operação de finalização e gravação seja concluída, simulando O_APPEND? Ou o arquivo será aberto como O_APPEND, deixando-o no kernel para garantir que os anexos ocorram?

Estou perguntando isso, porque um processo de servidor de servidor substitui alguns marcadores inseridos por eco, quando o arquivo de saída é do ponto de montagem do NFS, e a Documentação do NFS diz que O_APPEND não é suportado no servidor, portanto o kernel do cliente terá que lidar com isso. Eu acho que o processo do conservador está usando O_APPEND, mas não tenho certeza do bash >>no linux, fazendo a pergunta aqui.

Prem
fonte
12
O problema no NFS não O_APPENDé que não é suportado; o problema é que ele é emulado. Em um sistema de arquivos local, vários processos de gravação no mesmo arquivo aberto O_APPEND nunca substituem os dados um do outro; no NFS, O_APPENDé emulado buscando o final antes de escrever, o que deixa a possibilidade de condições de corrida. Não há como contornar isso no NFS; cada gravador paralelo precisa gravar seu próprio arquivo. A única maneira de contornar isso é configurar um processo do servidor no servidor NFS, fazer com que os registradores façam logon |nc server porte que o servidor anexe os dados recebidos ao log.
Guntram Blohm apoia Monica
@GuntramBlohm, +1, obrigado pela confirmação. Basicamente, sua sugestão é usar apenas um processo de gravação no arquivo, e todos os outros processos de gravação passarão por esse processo.
Prem
Tantas boas respostas, Não tenho certeza de qual resposta devo aceitar. Primeiro, Bruce Ediger mostrou que O_APPEND é usado. O próximo Random832 mostrou que isso é dado nos padrões. Finalmente, Eric Renouf mostrou o código fonte com a mesma resposta. Todas as três perspectivas são adicionadas à imagem final final.
Prem
6
Em resumo, o NFS é uma carga de bugs e não deve ser usado.
R. ..
2
Sim, mas já aprendemos isso quando o O_EXCL foi inventado.
22415 Kevin

Respostas:

60

Eu executei o seguinte: strace -o spork.out bash -c "echo 1234 >> some-file"para descobrir sua pergunta. Isto é o que eu encontrei:

open("some-file", O_WRONLY|O_CREAT|O_APPEND, 0666) = 3

Nenhum arquivo chamado "some-file" existia no diretório em que eu executei o echocomando.

Bruce Ediger
fonte
50

Isso não é feito apenas no Bash, é exigido pelo padrão.

Na especificação Single Unix :

O redirecionamento de saída anexado fará com que o arquivo cujo nome resulta da expansão da palavra seja aberto para saída no descritor de arquivo designado. O arquivo é aberto como se a função open () , conforme definida no volume System Interfaces do POSIX.1-2008, fosse chamada com o sinalizador O_APPEND. Se o arquivo não existir, ele deverá ser criado.

Qualquer shell compatível com POSIX, portanto, deve fazê-lo. Em alguns sistemas Unix, /bin/shpode ser um shell Bourne não POSIX (o shell Bourne foi originalmente escrito antes de ter O_APPENDsido inventado) e o shell POSIX disponível normalmente será ksh, o que estará disponível shem um local de caminho diferente, como o Solaris /usr/xpg4/bin.

Random832
fonte
2
Curiosamente, um shell que não faz isso é o shell Bourne. O shell Bourne é aberto sem O_TRUNC e lseek () s até o fim. Isso seria porque foi escrito antes da adição do sinalizador O_APPEND open(). >>foi introduzido por seu antecessor, o shell Thomson.
Stéphane Chazelas
1
@ StéphaneChazelas Além disso, procurei na fonte do shell C várias versões, e o sinalizador O_APPEND não foi introduzido até o 4.3BSD-Reno.
#Registrado em
Diz "como se", então não poderia ser implementado de maneira diferente (mas produzindo o mesmo efeito observável)? Não parece que o padrão exija o uso de O_APPEND, apenas algo que se comporta "como se".
Thomas
1
@ Thomas: significa que você terá todo o comportamento documentado para O_APPEND, o que significa reposicionar no final de cada gravação. O "como se" é apenas verborragia de padrões que visa permitir, por exemplo, que seja aberto por alguns meios que não sejam a chamada da função open () em plataformas Unix não tradicionais.
#Registrado em
+1, por mostrar que esse comportamento está dentro dos padrões.
Prem
32

Procurando na fonte, ele usa O_APPEND. Para o bash 4.3.30 na make_cmd.clinha 710-713, leia:

case r_appending_to:                /* >>foo */
case r_append_err_and_out:          /* &>> filename */
  temp->flags = O_APPEND | O_WRONLY | O_CREAT;
  break;
Eric Renouf
fonte
+1, para mostrar a resposta da perspectiva do código-fonte.
Prem
19

Vamos investigar isso usando straceem um sistema de arquivos local (não NFS):

$ strace -eopen -- bash -c "echo foo >> /tmp/testfile000" 2>&1 | grep /tmp/testfile000
open("/tmp/testfile000", O_WRONLY|O_CREAT|O_APPEND, 0666) = 3

$ strace -eopen -- bash -c "echo foo > /tmp/testfile000" 2>&1 | grep /tmp/testfile000
open("/tmp/testfile000", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3

Outros conchas, ou seja dash, dash, shde busybox' e mkshse comportam da mesma maneira.

A opção -e opensignifica -e trace=openrastrear apenas a open()chamada do sistema.

Franklin Piat
fonte