TL; DR
Abra su archivo de registro en modo agregar :
cmd >> log
Luego, puede truncarlo con seguridad con:
: > log
Detalles
Con un shell tipo Bourne, hay 3 formas principales en que un archivo se puede abrir para escribir. En modo de solo escritura ( >), lectura + escritura ( <>) o anexar (y solo de escritura >>).
En los primeros dos, el kernel recuerda la posición actual en la que usted (quiero decir, la descripción del archivo abierto , compartida por todos los descriptores de archivo que lo han duplicado o heredado al bifurcar desde el que abrió el archivo) está en archivo.
Cuando tu lo hagas:
cmd > log
logestá abierto en modo de solo escritura por el shell para el stdout de cmd.
cmd(su proceso inicial generado por el shell y todos los hijos posibles) al escribir en su stdout, escriba en la posición actual del cursor que mantiene la descripción del archivo abierto que comparten en ese archivo.
Por ejemplo, si cmdinicialmente escribe zzz, la posición estará en el byte offset 4 en el archivo, y la próxima vez que cmdsus hijos escriban en el archivo, allí es donde se escribirán los datos independientemente de si el archivo ha crecido o disminuido en el intervalo .
Si el archivo se ha reducido, por ejemplo, si se ha truncado con un
: > log
y cmdescribe xx, esos xxse escribirán en offset 4, y los primeros 3 caracteres serán reemplazados por caracteres NUL.
$ exec 3> log # open file on fd 3.
$ printf zzz >&3
$ od -c log
0000000 z z z
0000003
$ printf aaaa >> log # other open file description -> different cursor
$ od -c log
0000000 z z z a a a a
0000007
$ printf bb >&3 # still write at the original position
$ od -c log
0000000 z z z b b a a
0000007
$ : > log
$ wc log
0 0 0 log
$ printf x >&3
$ od -c log
0000000 \0 \0 \0 \0 \0 x
0000006
Eso significa que no puede truncar un archivo que se ha abierto en modo de solo escritura (y eso es lo mismo para leer + escribir ) como si lo hiciera, los procesos que tenían descriptores de archivo abiertos en el archivo, dejarán caracteres NUL al comienzo del archivo (aquellos, excepto en OS / X, generalmente no ocupan espacio en el disco, se convierten en archivos dispersos).
En cambio (y notará que la mayoría de las aplicaciones lo hacen cuando escriben en archivos de registro), debe abrir el archivo en modo de adición :
cmd >> log
o
: > log && cmd >> log
si quieres comenzar en un archivo vacío.
En el modo de agregar, todas las escrituras se realizan al final del archivo, independientemente de dónde fue la última escritura:
$ exec 4>> log
$ printf aa >&4
$ printf x >> log
$ printf bb >&4
$ od -c log
0000000 a a x b b
0000005
$ : > log
$ printf cc >&4
$ od -c log
0000000 c c
0000002
Eso también es más seguro, ya que si dos procesos han abierto (de esa manera) el archivo por error (como, por ejemplo, si ha iniciado dos instancias del mismo demonio), su salida no se sobrescribirá entre sí.
En las versiones recientes de Linux, puede verificar la posición actual y si se ha abierto un descriptor de archivo en modo de agregado mirando /proc/<pid>/fdinfo/<fd>:
$ cat /proc/self/fdinfo/4
pos: 2
flags: 0102001
O con:
$ lsof +f G -p "$$" -ad 4
COMMAND PID USER FD TYPE FILE-FLAG DEVICE SIZE/OFF NODE NAME
zsh 4870 root 4w REG 0x8401;0x0 252,18 2 59431479 /home/chazelas/log
~# lsof +f g -p "$$" -ad 4
COMMAND PID USER FD TYPE FILE-FLAG DEVICE SIZE/OFF NODE NAME
zsh 4870 root 4w REG W,AP,LG 252,18 2 59431479 /home/chazelas/log
Esos indicadores corresponden a los indicadores O ..._ pasados a la openllamada al sistema.
$ gcc -E - <<< $'#include <fcntl.h>\nO_APPEND O_WRONLY' | tail -n1
02000 01
( O_APPENDes 0x400 u octal 02000)
Entonces, el shell >>abre el archivo con O_WRONLY|O_APPEND(y 0100000 aquí es O_LARGEFILE que no es relevante para esta pregunta) mientras >es O_WRONLYsolo (y <>es O_RDWRsolo).
Si haces un:
sudo lsof -nP +f g | grep ,AP
para buscar archivos abiertos O_APPEND, encontrará la mayoría de los archivos de registro actualmente abiertos para escribir en su sistema.