Pourquoi voudriez-vous cat /dev/null sur quelque chose ?
Vous ferez cela pour tronquer le contenu d'un fichier tout en gardant l'inode intact. Tous les programmes qui ont ce fichier ouvert en lecture ou en écriture ne seront pas affectés en dehors du fait que la taille du fichier sera remise à zéro.
Une alternative bidon souvent trouvée consiste à supprimer le fichier puis à le recréer :
rm file
touch file
ou autre :
mv file file.old
gzip file.old
touch file
Le problème est que ces méthodes n'empêchent pas l'ancien fichier d'être maintenu en écriture par les processus ayant le fichier supprimé ouvert au moment de la suppression. La raison en est que sous les systèmes de fichiers Unix, lorsque vous supprimez un fichier, vous ne faites que dissocier son nom (chemin) de son contenu (inode). L'inode est maintenu en vie tant que des processus l'ont ouvert en lecture ou en écriture.
Cela entraîne plusieurs effets négatifs : les journaux écrits après la suppression du fichier sont perdus car il n'y a pas de moyen direct/portable d'ouvrir un fichier supprimé. Tant qu'un processus écrit dans le fichier supprimé, son contenu utilise toujours de l'espace sur le système de fichiers. Cela signifie que si vous supprimez/créez le fichier parce qu'il remplissait votre disque, celui-ci reste rempli. Une façon de résoudre ce dernier problème est de redémarrer les processus de journalisation, mais vous ne voudrez peut-être pas le faire pour les services critiques et les journaux intermédiaires seraient définitivement perdus. Il y a aussi des effets secondaires dus au fait que le fichier que vous créez peut ne pas avoir les mêmes permissions, propriétaire et groupe que le fichier original. Cela pourrait par exemple empêcher un analyseur de logs de lire le fichier nouvellement créé, ou pire, empêcher le processus de journalisation d'écrire ses propres logs.
La première méthode, cat /dev/null > file
atteindre l'objectif correctement Cependant, malgré une légende urbaine tenace, son cat /dev/null
ne fait absolument rien d'utile. Elle ouvre un pseudo-fichier qui est vide à dessein, elle ne parvient pas à lire quoi que ce soit à partir de ce fichier et finalement elle se termine. L'utilisation de cette commande est donc un gaspillage de frappes, d'octets, d'appels système et de cycles CPU et elle peut être remplacée sans aucun changement fonctionnel par la commande no-op, indubitablement plus rapide :
ou même, avec la plupart des obus, par aucune commande.
Laissez-moi essayer une métaphore pour expliquer à quel point c'est inutile. cat /dev/null
est. Disons que votre objectif est de vider un verre.
-
Il faut d'abord enlever tout le liquide qu'il contient. C'est suffisant et c'est précisément ce que ( > file
), étant donné que les redirections sont toujours traitées en premier.
-
Ensuite, vous prenez une bouteille vide ( /dev/null
) et le verser dans le verre vide ( cat
). C'est l'étape inutile...
Si vous lisez votre document lié jusqu'à la fin, vous pourriez remarquer les commentaires dans cette ligne de la version améliorée du script :
cat /dev/null > wtmp # **': > wtmp' and '> wtmp' have the same effect.**
Ils l'ont fait en effet ; dommage cat /dev/null
a été conservé dans le code.
Cela signifie que le code suivant fonctionnera avec tous les shells courants (à la fois csh
y sh
familles) :
cd /var/log
: > messages
: > wtmp
echo "Log files cleaned up."
et cela fonctionnera avec tous les shells utilisant la syntaxe Bourne, comme ash
, bash
, ksh
, zsh
et autres :
cd /var/log
> messages
> wtmp
echo "Log files cleaned up."
Notez cependant qu'avec les anciens shells Bourne pré-POSIX, n'importe laquelle de ces commandes, y compris la commande cat /dev/null
ne tronquera pas un fichier s'il est écrit après coup par un Shell Shell toujours en cours d'exécution qui l'ajoute. Au lieu d'un fichier de zéro octet, ce serait un fichier clairsemé dont la taille resterait inchangée. La même chose se produirait si le fichier était écrit par un processus cherchant la position qu'il pense être la position actuelle avant d'écrire.
Sachez également que certaines solutions alternatives souvent proposées pour tronquer un fichier présentent des failles.
-
Les deux suivantes ne font pas l'affaire. Le fichier résultant n'est pas vide mais contient une ligne vide. Cela casserait les fichiers journaux comme wtmp
qui stockent des enregistrements de largeur fixe.
echo > file
echo "" > file
-
Le suivant, basé sur un BSD sh
n'est pas portable, POSIX ne spécifie pas d'options autorisées pour echo, donc vous pouvez vous retrouver avec un fichier contenant une ligne avec " -n
" :
echo -n > file
-
Cette dernière n'est pas non plus portable en utilisant un System V sh
séquence d'échappement. Certains shells créeront un fichier contenant une ligne avec " \c
" :
echo "\c" > file
-
Celui-ci utilise une commande conçue pour faire le travail. Le problème est d'utiliser truncate
n'est pas portable car cette commande, n'étant pas spécifiée par POSIX, pourrait être absente d'un système Unix/Linux.
truncate -s 0
Enfin, voici quelques alternatives qui sont portables et feront correctement le travail :