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


Sur ce page exemple de script 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 voudrais-tu cat /dev/null sur quelque chose? Je ne peux pas comprendre ce qui est prévu ici (est-ce comme utiliser while TRUE; sleep 1; elihw pour {some busy program}?). Pourtant, l'auteur l'appelle "Rien d'inhabituel".


75
2017-12-06 19:40


origine




Réponses:


Vous typiquement 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 du fichier. Le contenu du fichier sera clairement effacé par le cat /dev/null Cependant, le fichier lui-même, tel qu'il existe et est connu du système de fichiers sur lequel il se trouve, sera toujours présent avec le même numéro d'inode, la même propriété et les mêmes autorisations.

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. Donc faire-par exemple-un rm /var/log/messages && touch /var/log/messages perturberait d’autres processus et risquerait d’entraver les processus. Ce qui signifie un processus qui est en quelque sorte verrouillé à 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 dans l’utilisation / l’état d’un fichier, l’utilisation de 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 que vous liez à l'auteur déclare ce qui suit:

Il n'y a rien d'inhabituel ici, seulement un ensemble de commandes qui pourrait juste   aussi facilement ont été invoqués un par un à partir de la ligne de commande sur le   console ou dans une fenêtre de terminal. Les avantages de placer le   les commandes dans un script vont bien au-delà de ne pas avoir à les ressaisir   encore.

Donc, le "rien d'inhabituel" mentionné par l'auteur concerne le concept entier de ce que ce script bash spécifique est: Ce n'est qu'un ensemble de commandes simples qui peuvent être exécutées tout aussi facilement depuis la ligne de commande mais sont placées dans un fichier texte à éviter de devoir les retaper encore et encore.


39
2017-12-06 19:50



@jlliagre La seule chose qui soit "maintenue en vie" est le contexte de la question qui se concentre sur la raison pour laquelle l'auteur original le ferait. Si vous êtes passionné pour dissiper le «mythe», veuillez poster une réponse qui fournit un contexte pour la méthode de codage de l'auteur original ainsi qu'une perspective sur la raison pour laquelle vous pensez qu'il peut être remplacé par d'autres méthodes. - JakeGould
La réponse de @jlliagre Cyrus n'aborde pas la question centrale de savoir pourquoi l'auteur original aurait utilisé cette méthode ni le raisonnement qui la sous-tend. Le tutoriel mentionné est assez ancien et raisonnablement accepté. Ce n'est pas inexact ni ne perpétue une supposée "légende urbaine". C'est plutôt la façon dont une personne code par rapport à la manière dont une autre personne code. Aussi simple que cela. C'est un problème de style qui n'a aucun impact négatif sur la fiabilité ou la performance. - JakeGould
truncate -s 0 ferait la même chose et serait moins idiomatique. Cependant, les programmeurs de shell sont un groupe conservateur et on peut rencontrer des systèmes suffisamment anciens ou assez fous pour manquer de cette commande. - Schwern
@skift cat /dev/null > /foo/bar tronque le fichier; echo "" > /foo/bar le tronque puis écrit un caractère de nouvelle ligne. - David
Un autre avantage de cette méthode par rapport à rm & touch est que la propriété et les autorisations sont maintenues. - jjmontes


Pourquoi voudriez-vous chat / 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 pour la lecture ou l'écriture ne seraient pas affectés en dehors du fait que la taille du fichier serait remise à zéro.

Une alternative erronée souvent trouvée consiste à supprimer le fichier puis à le créer à nouveau:

rm file
touch file

ou similaire:

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 conservé par les processus dont le fichier supprimé est ouvert au moment de la suppression. La raison en est sous les systèmes de fichiers Unix, lorsque vous supprimez un fichier, vous dissociez uniquement son nom (chemin) de son contenu (inode). L'inode est maintenu en vie tant que des processus sont ouverts pour la lecture ou l'écriture.

Cela entraîne plusieurs effets négatifs: les journaux écrits après la suppression du fichier sont perdus car il n’existe aucun moyen simple ou portable d’ouvrir un fichier supprimé. Tant qu'un processus écrit sur 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 car il remplissait votre disque, le disque reste rempli. Une façon de résoudre ce problème consiste à 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 existe également des effets secondaires dus au fait que le fichier que vous créez peut ne pas avoir les mêmes autorisations, propriétaire et groupe que celui d'origine. Cela pourrait par exemple empêcher un analyseur de journal de lire le nouveau fichier créé, ou pire, empêcher le processus de journalisation d'écrire ses propres journaux.

La première méthode, cat /dev/null > file atteindre l'objectif correctement cependant, malgré une légende urbaine tenace, sa cat /dev/null la partie ne fait absolument rien d'utile. Il ouvre un pseudo fichier vide de par sa conception, il ne parvient pas à lire quoi que ce soit et ne fait que quitter. L'utilisation de cette commande est alors un gaspillage de frappes de touches, d'octets, d'appels système et de cycles du processeur. Elle peut être remplacée sans aucune modification fonctionnelle par la commande no-op sans aucun doute plus rapide. : ou même, avec la plupart des obus, sans aucune commande.

Laissez-moi essayer une métaphore pour expliquer comment inutile cat /dev/null est. Disons que votre objectif est de vider un verre.

  • Vous en retirez d'abord tout liquide. C'est suffisant et c'est précisément ce que (> file) compte tenu du fait que les redirections sont toujours traitées en premier.

  • Ensuite, vous choisissez 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 remarquerez peut-être les commentaires de cette ligne à partir de la version améliorée du script:

    cat / dev / null> wtmp # ':> wtmp' et '> wtmp' ont le même effet.

Ils ont en effet dommage cat /dev/null a été conservé dans le code.

Cela signifie que le code suivant fonctionnera avec tous les shells communs (les deux csh et sh des familles):

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

et cela fonctionnera avec tous les shells en utilisant la syntaxe Bourne, comme ash, bash, ksh, zsh et les goûts:

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

Notez cependant qu’avec les anciens shell Bourne pré-POSIX, l’une de ces commandes, y compris cat /dev/null ne pas tronquer un fichier s'il est écrit par la suite par un script shell en cours d'exécution en y ajoutant. Au lieu d'un fichier de zéro octet, ce serait un fichier fragmenté avec sa taille inchangée. La même chose se produirait si le fichier est écrit par un processus cherchant à la position qu'il pense être la position courante avant d'écrire.

Attention, certaines solutions alternatives souvent proposées pour tronquer un fichier présentent des failles.

  • Les deux suivants ne font tout simplement pas le travail. Le fichier résultant n'est pas vide mais contient une ligne vide. Cela briserait les fichiers journaux comme wtmp qui stockent des enregistrements de largeur fixe.

    echo > file
    echo "" > file
    
  • Le suivant basé sur un BSD sh L'option n'est pas portable, POSIX ne spécifie aucune option autorisée pour echo afin que vous puissiez vous retrouver avec un fichier contenant une ligne avec "-n":

    echo -n > file
    
  • Celui-là non portable non plus en utilisant un System V sh séquence d'échappement. Certains shells vont créer 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 en utilisant truncate n'est pas portable car cette commande, non spécifiée par POSIX, est peut-ê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
    
  • En utilisant le true commande qui est strictement équivalente à la non-op : quoique plus lisible:

    true > file
    

120
2017-12-06 21:24



@JonathanLeffler Je crois que cela fait partie de tous les courants csh mises en œuvre bien que cela ne soit pas nécessairement documenté. À partir du Solaris csh  page de manuel : Null command. This command is interpreted, but performs no action.. Je n'ai trouvé aucune mention de la même dans le tcsh page de manuel ou le BSD original csh ceux-là mais cette syntaxe a peut-être toujours fonctionné. - jlliagre
Une raison d'écrire cat /dev/null est de rendre vos intentions explicites. - Davidmh
@Davidmh Ce serait raisonnable, mais votre déclaration ne résiste pas aux vérifications de faits. J'ai observé cet idiome de coquille depuis probablement deux décennies. Lorsque j'ai eu l'occasion de demander à l'auteur le raisonnement derrière cela, j'ai toujours eu des théories peu judicieuses sur l'utilisation /dev/null être un moyen efficace d'injecter zéro octet, de toute façon plus fiable que d'utiliser : ou rien. Dans cette même page, Cyrus a répondu que ce qui était laconique mais droit au but n’avait aucun vote alors que celui de JakeGould qui contestait le fait cat /dev/null était un no-op (voir nos commentaires) déjà eu au moins quatre votes. - jlliagre
@jlliagre ma connaissance de la coque est assez basique, donc je ne suis peut-être pas la meilleure cible de population; mais un nu > ou : n'est pas clair Je suis d'accord pour dire qu'il est dommage que les mythes aient été propagés du fait de son utilisation. - Davidmh
@Davidmh Si vous voulez vraiment quelque chose d’explicite avant la redirection, je vous recommande printf "" > file qui est à la fois portable (POSIX) et léger comme souvent implémenté comme un shell intégré. - jlliagre


C'est une façon fastidieuse de mettre le fichier à zéro.

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

6
2017-12-06 19:44



Cette syntaxe ne fonctionnera pas dans chaque shell. - reinierpost
Correct. La question est uniquement marquée avec "bash". - Cyrus
@reinierpost Cela fonctionnera dans tous les shells Bourne, n'est-ce pas? Ne nous inquiétons pas de csh. - Barmar
: > messagesfonctionne également. : ou true sont les choix les plus évidents pour les commandes qui n'impriment rien et renvoient true. - Peter Cordes


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

echo -n > /var/log/messages

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


-2
2017-12-07 18:29



C'est en effet plus compréhensible mais malheureusement pas équivalent. Il va même casser des fonctionnalités comme dans le wtmp Cas. Voir ma réponse mise à jour. - jlliagre
echo -n évite newline. - bbaassssiiee
Il sera en effet si vous êtes sûr d'utiliser bash, -n n'est pas garanti pour fonctionner dans toutes les coques Bourne. - jlliagre