Quand «ls -s» affiche-t-il «0»

13

Bien sûr, la façon standard de tester si un fichier est vide est avec test -s FILE, mais l'un de nos clients a reçu un script contenant des tests comme celui-ci:

RETVAL=`ls -s ./log/cr_trig.log | awk '{print $1}'`
if test $RETVAL -ne 0
then
    echo "Badness: Log not empty"
    exit 25
fi

avec les affirmations du fournisseur selon lesquelles il fonctionne dans les deux environnements dans lesquels ils l'ont testé. Inutile de dire qu'il a mal échoué aux deux endroits où je l'ai testé.

Alors, je suis devenu curieux. Quand ls -simprime-t-on 0pour les fichiers vides?

Voici mes conclusions jusqu'à présent:

  • GFS sur Linux: 4
  • ext4 sous Linux: 0
  • ZFS sur Solaris: 1
  • UFS sur Solaris: 0
  • jfs sur AIX: 0
  • VxFS sur HP-UX: 0
  • HFS sur HP-UX: 0
  • HFS sur Mac OS X: 0

Je n'ai pas encore examiné les systèmes de fichiers en réseau.

Question: Comment puis-je expliquer avec élégance aux autres que leurs scripts sont faux ?

À mon avis, la version "correcte" serait:

if test ! -s ./log/cr_trig.log
then
    echo "Badness: Log not empty"
    exit 25
fi
MattBianco
la source
5
Montrez-leur simplement vos tests. Vous avez des données solides qui prouvent que leur test n'est pas portable, de quoi avez-vous besoin de plus?
Mat
L'une des questions les plus intéressantes que j'ai vues jusqu'à présent sur ce serveur. Dommage que l'on ne puisse dépenser qu'un point.
ktf
@ktf Vous pouvez toujours attribuer une prime.
Joe

Réponses:

6

Constatation très intéressante. Bien que je n'ai jamais utilisé ls -spour vérifier si un fichier est vide ou non, j'aurais supposé qu'il signale également 0les fichiers vides.

À votre question: comme l'a déjà fait remarquer Mat , montrez-leur les résultats de votre test. Pour leur expliquer les résultats, indiquez que ls -sla quantité de blocs alloués dans le système de fichiers est indiquée, et non la taille réelle en octets. De toute évidence, certaines implémentations de système de fichiers allouent des blocs même si elles n'ont pas à stocker de données au lieu de stocker uniquement un pointeur NULL dans l'inode.

L'explication peut être liée aux performances. Créer des fichiers vides qui resteront vides est une exception pour le traitement normal (l'usage le plus courant que j'ai vu serait la création de fichiers d'état où l'existence d'un fichier représente un certain état du logiciel).

Mais normalement, un fichier créé obtiendra bientôt des données, donc les concepteurs d'un certain FS peuvent avoir supposé qu'il est payant d'allouer immédiatement un bloc de données lors de la création du fichier, donc lorsque les premières données arrivent, cette tâche est déjà terminée.

La deuxième raison pourrait être qu'un fichier a contenu dans le passé des données qui ont été effacées. Au lieu de libérer le dernier bloc de données, il peut être utile de conserver ce bloc de données pour une réutilisation par le même fichier.

ÉDITER:

Une autre raison m'est venue à l'esprit: les systèmes de fichiers où vous avez trouvé des valeurs> 0 sont ZFS , l'implémentation RAID + LVM + FS et GFS , un système de fichiers de cluster. Les deux peuvent avoir à stocker des métadonnées pour maintenir l'intégrité des fichiers qui ne sont pas stockés dans les inodes. Il se pourrait que le ls -snombre de blocs de données soit alloué à ces métadonnées.

ktf
la source
4

Contrairement à la plupart des systèmes de fichiers (sinon tous), ZFS ne préalloue pas un tableau statique d'inodes. La création d'un fichier vide sur ZFS utilisera alors un nouveau bloc de données qui est celui signalé par ls -s.

Je soupçonne GFS d'avoir à stocker des données de synchronisation / verrouillage menant à l'autre résultat non nul.

jlliagre
la source
2

ls -s signale le nombre de blocs qui sont alloués au fichier, sans inclure ce qui est stocké directement dans l'entrée de répertoire.

Dans la plupart des cas, le nombre de blocs est le nombre d'octets divisé par la taille du bloc en octets, arrondi.

Le nombre de blocs peut être inférieur à celui d'un fichier clairsemé . Par exemple, sur la plupart des systèmes de fichiers, cela créera un fichier de 8192 octets couvrant 0 blocs:

$ perl -e 'truncate STDOUT, 8192' >a
$ ls -l a
-rw-r--r-- 1 gilles gilles 8192 Nov  1 21:32 a
$ ls -s a
0 a

Inversement, le nombre de blocs peut être supérieur si le système de fichiers préalloue des blocs pour les fichiers ou utilise des blocs pour stocker des métadonnées. Je ne suis pas surpris que Zfs ait une correspondance non évidente entre la taille des fichiers et le nombre de blocs, étant donné le grand nombre de fonctionnalités qu'il offre et son orientation vers les grands systèmes de fichiers; Je ne connais pas les détails, mais le nombre de blocs dépend non seulement de la taille des fichiers mais aussi de son historique (vous pouvez avoir plus d'un bloc dans un fichier vide si c'est le résultat de tronquer un fichier plus gros).

Pour expliquer pourquoi ls -sest faux: il ne compte pas la taille du fichier, mais une quantité dépendante du système de fichiers. C'est une manière très indirecte de déterminer si un fichier est vide en premier lieu, nécessitant un outil externe ( ls) et une certaine analyse; au lieu de cela, ils devraient utiliser test -s, ce qui ne nécessite aucune analyse, et effectue exactement ce qui est demandé. S'ils pensent que ls -sc'est un bon moyen de tester si un fichier est vide, c'est à eux qu'il incombe de justifier qu'il fonctionne.

Gilles 'SO- arrête d'être méchant'
la source