Tengo un directorio con más de 400 GiB de datos. Quería comprobar que todos los archivos se pueden leer sin errores, por lo que una forma sencilla que pensé fue que tar
en /dev/null
. Pero en cambio veo el siguiente comportamiento:
$ 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
El tercer comando anterior fue detenido a la fuerza por Ctrl+ Cdespués de haberlo ejecutado durante bastante tiempo. Además, mientras los dos primeros comandos estaban funcionando, el indicador de actividad del dispositivo de almacenamiento que contenía .
casi siempre estaba inactivo. Con el tercer comando, el indicador se ilumina constantemente, lo que significa ocupado extremo.
Por lo tanto, parece que, cuando tar
puede descubrir que su archivo de salida es /dev/null
, es decir, cuando /dev/null
se abre directamente para tener el identificador de archivo en el que tar
escribe, el cuerpo del archivo parece omitido. (Agregar v
opción a tar
imprime todos los archivos en el directorio siendo tar
'rojo').
Entonces me pregunto, ¿por qué es así? ¿Es algún tipo de optimización? En caso afirmativo, ¿por qué tar
querría hacer una optimización tan dudosa para un caso tan especial?
Estoy usando GNU tar 1.26 con glibc 2.27 en Linux 4.14.105 amd64.
find . -type f -exec shasum -a256 -b '{}' +
. No sólo hecho de leer y suma de comprobación de todos los datos, pero si almacena la salida, se puede volver a ejecutarlo más tarde para comprobar que el contenido de los archivos no ha cambiado.pv
:tar -cf - | pv >/dev/null
. Eso evita el problema y le brinda información sobre el progreso (las diversaspv
opciones)gtar -cf /dev/zero ...
para obtener lo que le gusta.Respuestas:
Que es una optimización documentado :
fuente
info tar
lugar ...info
o como HTML en un navegador.Esto puede suceder con una variedad de programas, por ejemplo, tuve ese comportamiento una vez cuando estaba usando
cp file /dev/null
; en lugar de obtener una estimación de la velocidad de lectura de mi disco, el comando regresó después de unos pocos milisegundos.Hasta donde recuerdo, eso fue en Solaris o AIX, pero el principio se aplica a todo tipo de sistemas unix-y.
En los viejos tiempos, cuando un programa copiaba un archivo en algún lugar, alternaba entre
read
llamadas que obtenían algunos datos del disco (o lo que sea que se refiere el descriptor de archivo) a la memoria (con una garantía de que todo está allí cuandoread
regresa) ywrite
llamadas (que toma la mayor parte de la memoria y envía el contenido al destino)Sin embargo, hay al menos dos nuevas formas de lograr lo mismo:
Linux tiene llamadas al sistema
copy_file_range
(no es portátil a otros unixes) ysendfile
(algo portátil; originalmente estaba destinado a enviar un archivo a la red, pero ahora puede usar cualquier destino). Están destinados a optimizar las transferencias; si el programa usa uno de esos, es fácilmente concebible que el núcleo reconozca el objetivo/dev/null
y convierta la llamada del sistema en un no-opLos programas pueden usar
mmap
para obtener el contenido del archivo en lugar deread
, esto básicamente significa "asegurarme de que los datos estén allí cuando intento acceder a esa porción de memoria" en lugar de "asegurarme de que los datos estén allí cuando vuelva la llamada del sistema". Entonces, un programa puedemmap
enviar el archivo fuente y luego invocarwrite
ese trozo de memoria asignada. Sin embargo, como la escritura/dev/null
no necesita acceder a los datos escritos, la condición "asegúrese de que esté allí" nunca se activa, lo que hace que el archivo tampoco se lea.No estoy seguro de si gnu tar usa alguno y cuál de estos dos mecanismos cuando detecta que está escribiendo
/dev/null
, pero son la razón por la cual cualquier programa, cuando se usa para verificar las velocidades de lectura , debe ejecutarse en| cat > /dev/null
lugar de> /dev/null
, y por qué| cat > /dev/null
debería ser evitado en todos los demás casos.fuente
tar
página de información de GNU (ver otra respuesta) es que tiene un modo especial para esto, que presumiblemente solo envía archivos de estadísticas sin abrirlos. De hecho, solo verifiquétar cf /dev/null foo*
un par de archivos y sí, solonewfstatat(..., AT_SYMLINK_NOFOLLOW)
llamadas al sistema, ni siquiera unaopen()
que pueda actualizar el atime. Pero +1 para describir los mecanismos donde esto puede suceder sin tener que detectarlo especialmente.splice(2)
en Linux. En realidad, reemplazarcat > /dev/null
conpv -q > /dev/null
(que se usasplice()
en Linux) probablemente reduciría la sobrecarga. Odd bs=65536 skip=9999999999 2> /dev/null
, owc -c > /dev/null
otail -c1 > /dev/null
...