tar: le fichier a changé à la lecture

J’utilise make et tar pour sauvegarder. Lors de l’exécution de makefile, la commande tar affiche le file changed as we read it . Dans ce cas,

  • le paquet de tar est ok quand l’avertissement arrive
  • mais il arrête la commande tar pour la sauvegarde suivante
  • le fichier montrant l’avertissement en fait ne change pas – il est vraiment étrange que l’avertissement arrive
  • les fichiers montrant l’avertissement apparaissent aléatoirement, je veux dire, chaque fois que je lance mon makefile, les fichiers affichant l’avertissement sont différents
  • --ignore-failed-read n’aide pas. J’utilise le tar 1.23 dans MinGW
  • Je viens de changer mon ordinateur en WIN7 64 bits. Le script fonctionne bien dans l’ancien WIN7 32 bits. Mais la version tar n’est pas aussi nouvelle que la version 1.23.

Comment puis-je arrêter l’avertissement du tar pour arrêter ma sauvegarde après l’avertissement?


Edit-2 : ce pourrait être la raison

Comme je l’ai dit plus haut, le script shell bash a bien fonctionné sur mon ancien ordinateur. En comparaison avec l’ancien ordinateur, la version msys est différente. Il en est de même pour la version de la commande tar. Dans l’ancien ordinateur, tar est 1.13.19 et il est 1.23 dans le nouvel ordinateur. J’ai copié l’ancienne commande tar sans copier sa dépendance msys-1.0.dll sur le nouvel ordinateur et la renommer tar_old. Et j’ai également mis à jour la commande tar dans le script shell et exécuté le script. Alors tout va bien. Donc, il semblait que le problème était la commande tar. Je suis sûr qu’il n’ya aucun fichier modifié lors du tarage. Est-ce un bug pour la commande tar dans la nouvelle version? Je ne sais pas.


Edit-1 : append plus de détails

La sauvegarde est appelée par un script shell bash. Il parsing le répertoire cible et crée makefile, puis appelle la commande make to use pour la sauvegarde. Suivi est un makefile typique construit par le script shell bash.

 #-------------------------------------------- # backup VC #-------------------------------------------- # the program for packing PACK_TOOL=tar # the option for packing tool PACK_OPTION=cjvf # M$: C driver WIN_C_DIR=c: # M$: D driver WIN_D_DIR=d: # M$: where the software is WIN_PRG_DIR=wuyu/tools # WIN_PRG_DIR= # where to save the backup files BAKDIR=/home/Wu.Y/MS_bak_MSYS VC_FRAMEWORK=/home/Wu.Y/MS_bak_MSYS/tools/VC/VC_framework.tar.bz2 VC_2010=/home/Wu.Y/MS_bak_MSYS/tools/VC/VC_2010.tar.bz2 .PHONY: all all: $(VC_FRAMEWORK) $(VC_2010) $(VC_FRAMEWORK): $(WIN_C_DIR)/$(WIN_PRG_DIR)/VC/Framework/* @$(PACK_TOOL) $(PACK_OPTION) "$@" --ignore-failed-read /c/$(WIN_PRG_DIR)/VC/Framework $(VC_2010): $(WIN_C_DIR)/$(WIN_PRG_DIR)/VC/VS2010/* @$(PACK_TOOL) $(PACK_OPTION) "$@" --ignore-failed-read /c/$(WIN_PRG_DIR)/VC/VS2010 

Comme vous pouvez le voir, le package tar est stocké dans ~ / MS_bak_MSYS / tools / VC / VC_2010.tar.bz2. Je lance le script dans ~ / qqaa. ~/MS_bak_MSYS est exclu de la commande tar. Ainsi, le fichier tar que je crée n’est pas dans un répertoire que je tente de placer dans un fichier tar. C’est pourquoi j’ai trouvé étrange que l’avertissement soit apparu.

Je rencontre également les messages tar “modifiés à mesure que nous les lisons”. Pour moi, ces messages sont apparus lorsque je faisais un fichier tar du système de fichiers Linux dans un environnement de construction bitbake. Cette erreur était sporadique.

Pour moi, cela n’était pas dû à la création d’un fichier tar à partir du même répertoire. Je suppose que certains fichiers sont écrasés ou modifiés lors de la création du fichier tar.

Le message est un avertissement et crée toujours le fichier tar. Nous pouvons toujours supprimer ces messages d’avertissement en définissant l’option

--warning=no-file-changed

( http://www.gnu.org/software/tar/manual/html_section/warnings.html )

Le code de sortie renvoyé par tar est toujours “1” dans le cas du message d’avertissement: http://www.gnu.org/software/tar/manual/html_section/Synopsis.html

Donc, si nous appelons le fichier tar d’une fonction dans des scripts, nous pouvons gérer le code de sortie comme suit:

 set +e tar -czf sample.tar.gz dir1 dir2 exitcode=$? if [ "$exitcode" != "1" ] && [ "$exitcode" != "0" ]; then exit $exitcode fi set -e 

Si vous voulez aider à déboguer un problème comme celui-ci, vous devez fournir la règle make ou au moins la commande tar que vous avez appelée. Comment pouvons-nous voir ce qui ne va pas avec la commande s’il n’y a pas de commande à voir?

Cependant, dans 99% des cas, une erreur comme celle-ci signifie que vous créez le fichier tar à l’intérieur d’un répertoire que vous essayez de placer dans le fichier tar. Ainsi, lorsque tar essaie de lire le répertoire, il trouve le fichier tar en tant que membre du répertoire, commence à le lire et à l’écrire dans le fichier tar, entre le moment où il commence à lire le fichier tar et sa fin En lisant le fichier tar, le fichier tar a été modifié.

Donc, par exemple, quelque chose comme:

 tar cf ./foo.tar . 

Il n’y a aucun moyen d’arrêter cela parce que ce n’est pas faux. Il suffit de placer votre fichier tar quelque part lorsque vous le créez ou de trouver un autre moyen (en utilisant --exclude ou autre) pour omettre le fichier tar.

Bien que ce soit très tard mais j’ai récemment eu le même problème.

Le problème est parce que dir . change à xyz.tar.gz que xyz.tar.gz est créé après l’exécution de la commande. Il y a deux solutions:

Solution 1: tar ne sera pas gênant si l’archive est créée dans un répertoire à l’intérieur . . Il peut y avoir des raisons pour lesquelles il est impossible de créer l’archive en dehors de l’espace de travail. Contourné en créant un répertoire temporaire pour mettre l’archive en tant que:

 mkdir artefacts tar -zcvf artefacts/archive.tar.gz --exclude=./artefacts . echo $? 0 

Solution 2: Celui-ci me plaît. créer le fichier d’archive avant d’exécuter tar:

 touch archive.tar.gz tar --exclude=archive.tar.gz -zcvf archive.tar.gz . echo $? 0 

Voici un one-liner pour ignorer le statut de sortie tar s’il est 1. Il n’est pas nécessaire de set +e comme dans le script de sandeep . Si le statut de sortie tar est 0 ou 1, ce one-liner renverra avec le statut de sortie 0. Sinon, il retournera avec le statut de sortie 1. Ceci est différent du script sandeep où la valeur de statut de sortie d’origine est préservée si elle est différente de 1 .

tar -czf sample.tar.gz dir1 dir2 || [[ $? -eq 1 ]]

Pour améliorer le one-liner de Fabian; disons que nous voulons ignorer uniquement le statut de sortie 1 mais conserver le statut de sortie si c’est autre chose:

 tar -czf sample.tar.gz dir1 dir2 || ( export ret=$?; [[ $ret -eq 1 ]] || exit "$ret" ) 

Cela fait tout ce que fait le script de sandeep, sur une seule ligne.