Por lo general, cat /dev/null > [something]
cuando desea borrar el contenido del archivo y al mismo tiempo asegurarse de que no hay absolutamente ningún riesgo de interrupción del estado real del archivo. El contenido del archivo será claramente borrado por el cat /dev/null
archivo, pero tal como existe y es conocido por el sistema de archivos en el que reside, seguirá estando allí con el mismo número de inodo, propiedad y permisos.
En el caso de un archivo de registro, podría ser que el propio archivo de registro esté marcado como "en uso" por otro proceso. Hacerlo, por ejemplo, rm /var/log/messages && touch /var/log/messages
sería perjudicial para otros procesos y podría provocar que los procesos en ejecución se ahoguen. Es decir, un proceso que de alguna manera está bloqueado a un número de inodo específico conectado al archivo /var/log/messages
podría de repente entrar en pánico y decir: "¡Hey! ¡Qué pasó /var/log/messages
! ”Incluso si el archivo todavía está allí. Sin mencionar posibles problemas con la propiedad y los permisos que se recrean incorrectamente.
Debido a esta incertidumbre en el uso / estado de un archivo, el uso de cat /dev/null > [something]
es preferido por los administradores del sistema que desean borrar un registro pero no quieren interferir potencialmente con la operación de procesos ya existentes.
Además, en el contexto de la página que vincula al autor, se indica lo siguiente:
Aquí no hay nada inusual, solo un conjunto de comandos que podrían haberse invocado fácilmente uno por uno desde la línea de comandos en la consola o en una ventana de terminal. Las ventajas de colocar los comandos en un script van mucho más allá de no tener que volver a escribirlos una y otra vez.
Entonces, "nada inusual" que el autor menciona es con respecto al concepto completo de lo que es ese script bash específico: es solo un conjunto de comandos simples que se pueden ejecutar fácilmente desde la línea de comandos pero se colocan en un archivo de texto para evite tener que volver a escribirlos una y otra vez.
truncate -s 0
haría lo mismo y sería menos idiomático. Sin embargo, los programadores de shell son un grupo conservador y uno puede encontrar sistemas lo suficientemente antiguos o locos como para carecer de ese comando.cat /dev/null > /foo/bar
trunca el archivo;echo "" > /foo/bar
lo trunca y luego escribe un solo carácter de nueva línea.Hará eso para truncar el contenido de un archivo mientras mantiene el inodo intacto. Todos los programas que tienen ese archivo abierto para leer o escribir no se verían afectados fuera del hecho de que el tamaño del archivo se restablecería a cero.
Una alternativa falsa que a menudo se encuentra es eliminar el archivo y luego volver a crearlo:
o similar:
El problema es que estos métodos no evitan que el archivo antiguo se mantenga escrito por cualquier proceso que tenga el archivo eliminado abierto en el momento de la eliminación. La razón por la cual está bajo los sistemas de archivos Unix, cuando elimina un archivo, solo desvincula su nombre (ruta) de su contenido (inodo). El inodo se mantiene vivo siempre que haya procesos que lo tengan abierto para leer o escribir.
Esto lleva a varios efectos negativos: los registros escritos después de la eliminación del archivo se pierden, ya que no hay una forma directa / portátil de abrir un archivo eliminado. Mientras un proceso escriba en el archivo eliminado, su contenido seguirá utilizando espacio en el sistema de archivos. Eso significa que si elimina / crea el archivo porque estaba llenando su disco, el disco permanece lleno. Una forma de solucionar este último problema es reiniciar los procesos del registrador, pero es posible que no desee hacerlo para los servicios críticos y los registros intermedios se perderían definitivamente. También hay efectos secundarios debido al hecho de que el archivo que cree podría no tener los mismos permisos, propietario y grupo que el original. Esto, por ejemplo, podría evitar que un analizador de registros lea el archivo recién creado o, lo que es peor, evitar que el proceso de registro escriba sus propios registros.
El primer método,
cat /dev/null > file
lograr el objetivo correctamente , sin embargo, a pesar de una tenaz leyenda urbana, sucat /dev/null
parte no hace absolutamente nada útil. Abre un pseudo archivo que está vacío por diseño, no puede leer nada de él y finalmente se cierra. El uso de este comando es un desperdicio de pulsaciones de teclas, bytes, llamadas al sistema y ciclos de la CPU, y puede ser reemplazado sin ningún cambio funcional por el comando no-operablemente más rápido:
o incluso, con la mayoría de los shells, por ningún comando.Déjame probar una metáfora para explicar lo inútil que
cat /dev/null
es. Digamos que su objetivo es vaciar un vaso.Primero eliminas cualquier líquido de él. Eso es suficiente y es precisamente lo que hace (
> file
) dado el hecho de que las redirecciones siempre se procesan primero.Luego, elige una botella vacía (
/dev/null
) y la vierte en el vaso vacío (cat
). Este es el paso inútil ...Si lee su documento vinculado hasta el final, puede notar los comentarios en esta línea de la versión mejorada del script:
Tienen de hecho; lástima
cat /dev/null
se mantuvo en el código.Eso significa que el siguiente código funcionará con todos los shells comunes (ambos
csh
ysh
familias):y esto va a trabajar con todas las conchas utilizando la sintaxis Bourne, como
ash
,bash
,ksh
,zsh
y los gustos:Sin embargo, tenga en cuenta que con los antiguos shells Bourne anteriores a POSIX, cualquiera de estos comandos, incluido el
cat /dev/null
truncado, no truncará un archivo si luego lo escribe un script de shell que aún se está ejecutando. En lugar de un archivo de cero bytes, sería un archivo disperso con su tamaño sin cambios. Lo mismo sucedería si el archivo está escrito por un proceso que busca la posición que cree que es la actual antes de escribir.Tenga en cuenta también que algunas soluciones alternativas a menudo sugeridas para truncar un archivo tienen fallas.
Los dos siguientes simplemente no hacen el trabajo. El archivo resultante no está vacío, pero contiene una línea vacía. Esto rompería los archivos de registro como
wtmp
ese que almacenan registros de ancho fijo.El siguiente basado en una
sh
opción BSD no es portátil, POSIX no especifica ninguna opción permitida para echo, por lo que puede terminar con un archivo que contiene una línea con "-n
":Ese tampoco es portátil usando una
sh
secuencia de escape del Sistema V. Algunos shells crearán un archivo que contiene una línea con "\c
":Ese usa un comando diseñado para hacer el trabajo. El problema que está utilizando
truncate
no es portátil porque este comando, que no está especificado por POSIX, puede faltar en un sistema Unix / Linux.Finalmente, aquí hay un par de alternativas que son portátiles y que harán el trabajo correctamente:
Imprimir explícitamente una cadena vacía en el archivo:
Usando el
true
comando que es estrictamente equivalente al no operativo,:
aunque más legible:fuente
csh
implementaciones actuales , aunque no está necesariamente documentado. De lacsh
página del manual de Solaris: Null command. This command is interpreted, but performs no action.
. No encontré ninguna mención de lo mismo ni en latcsh
página del manual ni en las BSD originalescsh
, pero esta sintaxis podría haber funcionado siempre.cat /dev/null
es hacer explícitas tus intenciones./dev/null
ser una manera eficiente de inyectar cero bytes, de todos modos una más confiable que usar:
o nada. En esta misma página, la respuesta de Cyrus, que era conciso pero directo al grano, tenía cero votos, mientras que la de JakeGould que cuestionaba el hechocat /dev/null
era un no operativo (ver nuestros comentarios) ya tenía al menos cuatro votos.>
o:
no está claro. Estoy de acuerdo en que es una pena que los mitos se hayan propagado debido a su uso.printf "" > file
que sea portátil (POSIX) y liviano, tan a menudo implementado como un shell incorporado.Es una forma engorrosa de llevar el archivo a tamaño cero.
fuente
csh
.: > messages
También funciona.:
otrue
son las opciones más obvias para los comandos que no imprimen nada y devuelven verdadero.Para truncar un archivo abierto. Esto es equivalente y más comprensible:
(Agregado -n para evitar la nueva línea)
fuente
wtmp
caso. Ver mi respuesta actualizada.bash
, de-n
lo contrario no se garantiza que funcione en todos los shells Bourne.