79 votes

Pourquoi voudriez-vous `cat /dev/null > /var/log/messages` ?

Sur ce page d'exemples de scripts bash l'auteur présente ce script :

# Cleanup
# Run as root, of course.

cd /var/log
cat /dev/null > messages
cat /dev/null > wtmp
echo "Log files cleaned up."

Pourquoi voulez-vous cat /dev/null sur quelque chose ? Je n'arrive pas à comprendre ce que l'on veut faire ici (est-ce comme si l'on utilisait while TRUE; sleep 1; elihw para {some busy program} ?). Pourtant, l'auteur dit qu'il n'y a "rien d'inhabituel".

122voto

jlliagre Points 13539

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 :

  • Impression explicite d'une chaîne vide dans le fichier :

     printf "" > file
  • Utilisation de la true qui est strictement équivalente à la commande no-op : bien que plus lisible :

     true > file

43voto

Giacomo1968 Points 48326

En général, vous cat /dev/null > [something] lorsque vous souhaitez effacer le contenu d'un fichier tout en vous assurant qu'il n'y a absolument aucun risque d'interruption de l'état réel du fichier. Le contenu du fichier sera clairement effacé par la commande cat /dev/null Pourtant, le fichier lui-même, tel qu'il existe et est connu du système de fichiers sur lequel il réside, sera toujours là avec le même numéro d'inode, la même propriété et les mêmes permissions.

Dans le cas d'un fichier journal, il se peut que le fichier journal lui-même soit marqué "en cours d'utilisation" par un autre processus. Ainsi, en faisant, par exemple, un rm /var/log/messages && touch /var/log/messages perturberait les autres processus et pourrait provoquer l'étouffement des processus en cours. Ce qui signifie qu'un processus qui, d'une manière ou d'une autre, est verrouillé sur un numéro d'inode spécifique connecté au fichier /var/log/messages pourrait soudainement paniquer et dire, "Hey ! Qu'est-il arrivé à /var/log/messages !" même si le fichier est toujours là. Sans parler des problèmes potentiels liés à la recréation incorrecte de la propriété et des autorisations.

En raison de cette incertitude quant à l'utilisation/état d'un fichier, l'utilisation de la fonction cat /dev/null > [something] est préféré par les administrateurs système qui veulent effacer un journal mais ne veulent pas potentiellement interférer avec le fonctionnement des processus déjà existants.

Aussi, dans le contexte de la page vers laquelle vous établissez un lien l'auteur déclare ce qui suit :

Il n'y a rien d'inhabituel ici, seulement un ensemble de commandes qui pourraient juste facilement être invoquées une par une à partir de la ligne de commande de la console ou dans une fenêtre de terminal. Les avantages de placer les commandes dans un script vont bien au-delà du fait de ne pas avoir à les retaper encore et encore. encore.

Ainsi, le "rien d'inhabituel" mentionné par l'auteur concerne le concept global de ce qu'est ce script bash spécifique : C'est juste un ensemble de commandes simples qui peuvent tout aussi bien être exécutées à partir de la ligne de commande mais qui sont placées dans un fichier texte pour éviter d'avoir à les retaper encore et encore.

6voto

Rachel Blackman Points 81

Il s'agit d'une méthode lourde pour ramener le fichier à une taille nulle.

cd /var/log
> messages
> wtmp
echo "Log files cleaned up."

-3voto

bbaassssiiee Points 1345

Pour tronquer un fichier ouvert. Ceci est équivalent, et plus compréhensible :

echo -n > /var/log/messages

(Ajouté -n pour éviter la nouvelle ligne)

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X