TL; DR
Ouvrez votre fichier journal en mode ajout :
cmd >> log
Ensuite, vous pouvez le tronquer en toute sécurité avec:
: > log
Détails
Avec un shell de type Bourne, il existe 3 façons principales d'ouvrir un fichier pour l'écriture. En mode écriture seule ( >), lecture + écriture ( <>) ou ajout (et écriture seule >>).
Dans les deux premiers, le noyau se souvient de la position actuelle dans laquelle vous (par vous, je veux dire, la description du fichier ouvert , partagée par tous les descripteurs de fichier qui l'ont dupliqué ou hérité en forçant à partir de celui sur lequel vous avez ouvert le fichier) fichier.
Quand vous faites:
cmd > log
logest ouvert en mode écriture seule par le shell pour la sortie standard de cmd.
cmd(son processus initial engendré par le shell et tous les enfants possibles) lors de l'écriture sur leur stdout, écrivez à la position actuelle du curseur détenue par la description du fichier ouvert qu'ils partagent sur ce fichier.
Par exemple, si l' cmdécriture initiale zzz, la position sera au décalage d'octets 4 dans le fichier, et la prochaine fois que cmdses enfants écrivent dans le fichier, c'est là que les données seront écrites, que le fichier ait augmenté ou diminué dans l'intervalle. .
Si le fichier a diminué, par exemple s'il a été tronqué avec un
: > log
et cmdécrit xx, ceux- xxci seront écrits en offset 4, et les 3 premiers caractères seront remplacés par des caractères 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
Cela signifie que vous ne pouvez pas tronquer un fichier qui a été ouvert en mode écriture seule (et c'est la même chose en lecture + écriture ) comme si vous le faisiez, les processus qui avaient des descripteurs de fichier ouverts sur le fichier, laisseront des caractères NUL au début de la fichier (ceux-ci, sauf sur OS / X, ne prennent généralement pas d'espace sur le disque, ils deviennent des fichiers rares).
Au lieu de cela (et vous remarquerez que la plupart des applications le font lorsqu'elles écrivent dans des fichiers journaux), vous devez ouvrir le fichier en mode ajout :
cmd >> log
ou
: > log && cmd >> log
si vous souhaitez démarrer sur un fichier vide.
En mode ajout, toutes les écritures sont effectuées à la fin du fichier, quelle que soit la dernière écriture:
$ 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
C'est aussi plus sûr que si deux processus ont ouvert (de cette manière) le fichier par erreur (comme par exemple si vous avez démarré deux instances du même démon), leur sortie ne se remplacera pas.
Sur les versions récentes de Linux, vous pouvez vérifier la position actuelle et si un descripteur de fichier a été ouvert en mode ajout en regardant /proc/<pid>/fdinfo/<fd>:
$ cat /proc/self/fdinfo/4
pos: 2
flags: 0102001
Ou avec:
$ 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
Ces drapeaux correspondent aux drapeaux O ..._ passés à l' openappel système.
$ gcc -E - <<< $'#include <fcntl.h>\nO_APPEND O_WRONLY' | tail -n1
02000 01
( O_APPENDest 0x400 ou octal 02000)
Ainsi, le shell >>ouvre le fichier avec O_WRONLY|O_APPEND(et 0100000 ici est O_LARGEFILE qui n'est pas pertinent pour cette question) alors que >est O_WRONLYseulement (et <>est O_RDWRseulement).
Si vous faites:
sudo lsof -nP +f g | grep ,AP
pour rechercher des fichiers ouverts avec O_APPEND, vous trouverez la plupart des fichiers journaux actuellement ouverts pour l'écriture sur votre système.