Perché tar sembra saltare il contenuto del file quando il file di output è / dev / null?


21

Ho una directory con oltre 400 GiB di dati. Volevo verificare che tutti i file possano essere letti senza errori, quindi un modo semplice in cui ho pensato era di tarfarlo /dev/null. Ma invece vedo il seguente comportamento:

$ time tar cf /dev/null .

real    0m4.387s
user    0m3.462s
sys     0m0.185s
$ time tar cf - . > /dev/null

real    0m3.130s
user    0m3.091s
sys     0m0.035s
$ time tar cf - . | cat > /dev/null
^C

real    10m32.985s
user    0m1.942s
sys     0m33.764s

Il terzo comando sopra è stato forzatamente interrotto da Ctrl+ Cdopo essere stato eseguito per un periodo piuttosto lungo. Inoltre, mentre i primi due comandi funzionavano, l'indicatore di attività del dispositivo di memorizzazione contenente .era quasi sempre inattivo. Con il terzo comando l'indicatore è costantemente acceso, il che significa estrema disponibilità.

Quindi sembra che, quando tarè in grado di scoprire che il suo file di output è /dev/null, cioè quando /dev/nullviene aperto direttamente per avere l'handle del file su cui tarscrive, il corpo del file appare saltato. (L'aggiunta vdell'opzione tarstampa tutti i file nella directory essendo tar'rosso.)

Quindi mi chiedo, perché è così? È una sorta di ottimizzazione? Se sì, allora perché tardovrei voler fare un'ottimizzazione così dubbia per un caso così speciale?

Sto usando GNU tar 1.26 con glibc 2.27 su Linux 4.14.105 amd64.


7
Come alternativa pratica, considera qualcosa di simile find . -type f -exec shasum -a256 -b '{}' +. In realtà non solo legge e esegue il checksum di tutti i dati, ma se memorizzi l'output, puoi rieseguirlo in seguito per verificare che il contenuto dei file non sia cambiato.
Ilmari Karonen,

Per misurare le cose è anche possibile utilizzare pv: tar -cf - | pv >/dev/null. Ciò elude il problema e ti fornisce informazioni sullo stato di avanzamento (le varie pvopzioni)
xenoid

Hai colpito una nota funzione miss di GNU tar. Usa gtar -cf /dev/zero ...per ottenere quello che ti piace.
schily

Risposte:


25

Si tratta di un'ottimizzazione documentato :

Quando viene creato l'archivio /dev/null, GNU tar cerca di minimizzare le operazioni di input e output. Il sistema di backup Amanda, quando utilizzato con GNU tar, ha un passaggio di dimensionamento iniziale che utilizza questa funzione.


4
Ah, questo non è stato descritto nella pagina man che avevo installato. Avrei dovuto info tarinvece provare ...
Ruslan,

9
Dovrebbero davvero mantenere sincronizzate le pagine man e info, è praticamente un bug che non lo sono
Xen2050

9
@Ruslan Con la maggior parte dei programmi di utilità GNU, la pagina man contiene solo un breve sommario, praticamente abbastanza buono solo quando ricordi che ha un'opzione per fare qualcosa ma non ricordi il nome dell'opzione. La documentazione completa è in un formato che non si traduce bene in pagine man ed è disponibile con infoo come HTML in un browser.
Gilles 'SO- smetti di essere malvagio' il


8

Questo può accadere con una varietà di programmi, ad esempio, ho avuto quel comportamento una volta mentre lo usavo cp file /dev/null; invece di ottenere una stima della velocità di lettura del mio disco, il comando è tornato dopo alcuni millisecondi.

Per quanto mi ricordo, era su Solaris o AIX, ma il principio si applica a tutti i tipi di sistemi unix-y.

Ai vecchi tempi, quando un programma copiava un file da qualche parte, si alternava tra le readchiamate che ottengono alcuni dati dal disco (o qualunque sia il descrittore di file a cui si riferisce) alla memoria (con la garanzia che tutto è lì quando readritorna) e writechiamate (che prende il pezzo di memoria e invia il contenuto alla destinazione).

Tuttavia, ci sono almeno due modi più recenti per ottenere lo stesso:

  • Linux ha chiamate di sistema copy_file_range(non portabili ad altri unix) e sendfile(piuttosto portabili; originariamente pensava di inviare un file alla rete, ma ora può usare qualsiasi destinazione). Hanno lo scopo di ottimizzare i trasferimenti; se il programma usa uno di questi, è facilmente concepibile che il kernel riconosca la destinazione /dev/nulle trasforma la chiamata di sistema in un no-op

  • I programmi possono usare mmapper ottenere il contenuto del file invece di read, questo in pratica significa "assicurarsi che i dati siano lì quando provo ad accedere a quel pezzo di memoria" invece di "assicurarsi che i dati siano lì quando ritorna la chiamata di sistema". Quindi un programma può mmapil file sorgente, quindi chiamare writequel pezzo di memoria mappata. Tuttavia, poiché la scrittura /dev/nullnon ha bisogno di accedere ai dati scritti, la condizione "assicurati che sia lì" non viene mai attivata, con la conseguenza che il file non viene letto neanche.

Non sono sicuro se gnu tar ne usi uno e con quali di questi due meccanismi quando rilevi che sta scrivendo /dev/null, ma sono la ragione per cui qualsiasi programma, quando usato per controllare la velocità di lettura , dovrebbe essere eseguito | cat > /dev/nullinvece di > /dev/null- e perché | cat > /dev/nulldovrebbe essere evitato in tutti gli altri casi.


Penso che l'implicazione nella tarpagina di informazioni GNU (vedi altra risposta) sia che ha una modalità speciale per questo, che presumibilmente solo i file delle statistiche senza aprirli. In effetti ho appena controllato tar cf /dev/null foo*un paio di file e sì, solo newfstatat(..., AT_SYMLINK_NOFOLLOW)chiamate di sistema, nemmeno un open()che potrebbe aggiornare l'atime. Ma +1 per descrivere i meccanismi in cui ciò può accadere senza doverlo rilevare appositamente.
Peter Cordes,

La spiegazione di mmap dovrebbe leggere "accedi ai dati letti " invece di "accedi ai dati scritti "?
Wayne Conrad,

Vedi anche splice(2)su Linux. In realtà, la sostituzione cat > /dev/nullcon pv -q > /dev/null(che utilizza splice()su Linux) ridurrebbe probabilmente il sovraccarico. O dd bs=65536 skip=9999999999 2> /dev/null, o wc -c > /dev/nullo tail -c1 > /dev/null...
Stéphane Chazelas,
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.