Bash apre i file in O_APPEND quando si usa “>>” su Linux?


38

Se usiamo, la echo 1234 >> some-filedocumentazione dice che l'output è stato aggiunto.

La mia ipotesi è che, se un file non esiste, O_CREAT creerà un nuovo file. Se è >stato utilizzato, O_TRUNC troncherà il file esistente.

In caso di >>: Il file verrà aperto come O_WRONLY (o O_RDWR) e cercherà di terminare e l'operazione di scrittura è stata eseguita, simulando O_APPEND? O il file verrà aperto come O_APPEND, lasciandolo al kernel per assicurarsi che accada l'aggiunta?

Lo sto chiedendo perché un processo di conservazione sta sovrascrivendo alcuni marcatori inseriti da eco, quando il file di output proviene dal punto di montaggio NFS e la documentazione NFS dice che O_APPEND non è supportato sul server, quindi il kernel client dovrà gestirlo. Immagino che il processo del conservatore stia usando O_APPEND, ma non sono sicuro di bash >>su Linux, quindi ponendo la domanda qui.


12
Il problema su NFS non O_APPENDè che non è supportato; il problema è che è emulato. Su un file system locale, diversi processi che scrivono nello stesso file aperto con O_APPEND non si sovrascriveranno mai reciprocamente i dati; su NFS, O_APPENDviene emulato cercando fino alla fine prima di scrivere, il che lascia la possibilità di condizioni di gara. Non c'è modo di aggirare questo su NFS; ogni scrittore parallelo deve scrivere il proprio file. L'unico modo per aggirare questo problema è impostare un processo server sul server NFS, fare in modo che i logger accedano |nc server porte fare in modo che il server acceda i dati in entrata al registro.
Guntram Blohm sostiene Monica

@GuntramBlohm, +1, grazie per la conferma. Fondamentalmente, il tuo suggerimento è di utilizzare solo un processo di scrittura nel file e tutti gli altri processi di scrittura passeranno attraverso questo processo.
Prem

Così tante buone risposte, non sono sicuro di quale risposta dovrei accettare. In primo luogo Bruce Ediger ha dimostrato che viene utilizzato O_APPEND. Next Random832 ha mostrato che questo è indicato negli standard. Alla fine, Eric Renouf ha mostrato il codice sorgente con la stessa risposta. Tutte e tre le prospettive si aggiungono al quadro completo finale.
Prem

6
In breve, NFS è un carico di bug e non dovrebbe essere usato.
R ..

2
Sì, ma abbiamo già imparato così quando è stato inventato O_EXCL.
Kevin,

Risposte:


60

Ho corso questo: strace -o spork.out bash -c "echo 1234 >> some-file"per capire la tua domanda. Questo è quello che ho trovato:

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

Nessun file denominato "some-file" esisteva nella directory in cui ho eseguito il echocomando.


50

Questo non è fatto solo in Bash, è richiesto dallo standard.

Dalla specifica Unix singola :

Il reindirizzamento dell'output aggiunto causa l'apertura del file il cui nome deriva dall'espansione della parola per l'output sul descrittore di file designato. Il file viene aperto come se la funzione open () come definita nel volume Interfacce di sistema di POSIX.1-2008 fosse richiamata con il flag O_APPEND. Se il file non esiste, deve essere creato.

Qualsiasi shell conforme a POSIX quindi deve farlo. Su alcuni sistemi Unix, /bin/shpuò essere una shell Bourne non POSIX (la shell Bourne è stata originariamente scritta prima che O_APPENDfosse inventata), e la shell POSIX disponibile sarà in genere ksh, che sarà disponibile come shin un percorso diverso come quello di Solaris /usr/xpg4/bin.


2
È interessante notare che una shell che non lo fa è la shell Bourne. La shell Bourne si apre senza O_TRUNC e lseek () s fino alla fine. Ciò sarebbe dovuto al fatto che era stato scritto prima dell'aggiunta del flag O_APPEND open(). >>stesso fu introdotto dal suo predecessore Thomson shell.
Stéphane Chazelas,

1
@ StéphaneChazelas Inoltre, ho cercato l'origine della shell C per varie versioni e il flag O_APPEND non è stato introdotto fino a 4.3BSD-Reno.
Casuale 832,

Dice "come se", quindi non potrebbe essere implementato diversamente (ma producendo lo stesso effetto osservabile)? Non sembra che lo standard richieda l'uso di O_APPEND, solo qualcosa che si comporta "come se".
Thomas,

1
@Thomas Significa che avrai tutto il comportamento documentato per O_APPEND, il che significa riposizionare alla fine di ogni scrittura. Il "come se" è solo un linguaggio standard che ha lo scopo di consentire, ad esempio, di essere aperto in qualche modo diverso dal chiamare effettivamente la funzione open () su piattaforme Unix non tradizionali.
Casuale 832,

+1, per dimostrare che questo comportamento è conforme agli standard.
Prem

32

Guardando nella fonte, usa O_APPEND. Per bash 4.3.30 nella make_cmd.criga 710-713 leggi:

case r_appending_to:                /* >>foo */
case r_append_err_and_out:          /* &>> filename */
  temp->flags = O_APPEND | O_WRONLY | O_CREAT;
  break;

+1, per mostrare la risposta dal punto di vista del codice sorgente.
Prem

19

Analizziamo che usando stracesu un filesystem locale (non 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

Altre shell, vale a dire dash, dash, shdi busybox' e mkshsi comportano allo stesso modo.

L'opzione -e opensignifica -e trace=opentracciare solo la open()chiamata di sistema.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.