web-dev-qa-db-fra.com

tar: le fichier a changé en le lisant

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

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

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


Edit-2 : c'est peut-être la raison

Comme je l'ai dit plus haut, le script bash Shell a bien fonctionné sur mon ancien ordinateur. En comparant avec l'ancien ordinateur, la version msys est différente. Il en va de même pour la version de la commande tar. Dans l'ancien ordinateur, tar correspond à 1.13.19 et à 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 je l'ai renommée tar_old. Et j'ai également mis à jour la commande tar dans le script shell et exécuter le script. Alors tout va bien. Il semble donc que le problème est la commande tar. Je suis sûr qu'il n'y a aucun fichier modifié lors de la tarage. Est-ce un bug de la commande tar dans la nouvelle version? Je ne sais pas.


Edit-1 : ajouter plus de détails

La sauvegarde est appelée par un script bash shell. Il analyse le répertoire cible et construit le fichier makefile, puis appelle make pour utiliser la commande tar pour la sauvegarde. Suit un fichier Make typique construit par le script bash Shell.

#--------------------------------------------
# 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 constater, le fichier 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 ne se trouve pas dans un répertoire que je tente de mettre dans un fichier tar. C'est pourquoi j'ai trouvé étrange que l'avertissement soit venu.

44
warem

Je rencontre aussi les messages "changés au fur et à mesure que nous le lisons". Pour moi, ce message s’est produit lors de la création du 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 qu’un fichier est écrasé ou modifié 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

Néanmoins, le code de sortie renvoyé par le fichier tar est "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 à partir d'une fonction dans les scripts, nous pouvons gérer le code de sortie comme ceci:

set +e 
tar -czf sample.tar.gz dir1 dir2
exitcode=$?

if [ "$exitcode" != "1" ] && [ "$exitcode" != "0" ]; then
    exit $exitcode
fi
set -e
50
sandeep

Si vous souhaitez obtenir de l'aide pour résoudre un problème de ce type, vous devez fournir la règle de création 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 dans un répertoire que vous essayez de placer dans le fichier tar. Donc, 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'écrit dans le fichier tar. En lisant le fichier tar, le fichier tar a changé.

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 ailleurs lorsque vous le créez ou de trouver un autre moyen (en utilisant --exclude ou autre) d’omettre le fichier tar.

26
MadScientist

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

Le problème vient du fait que dir . est en train de changer car xyz.tar.gz est créé après l'exécution de la commande. Il y a deux solutions:

Solution 1: tar ne gênera pas si l'archive est créée dans un répertoire quelconque à l'intérieur de .. Il peut y avoir des raisons pour lesquelles l’archive ne peut pas être créée en dehors de l’espace de travail. Contourné en créant un répertoire temporaire pour mettre l'archive comme:

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

Solution 2: Celui-ci me plait. créez le fichier archive avant d'exécuter tar:

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

Voici un one-liner pour ignorer l'état de sortie de 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 retournera avec le statut de sortie 0. Sinon, il retournera avec le statut de sortie 1. Ce script est différent de le script de sandeep où la valeur du statut de sortie initial est conservée si est différent de 1.

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

15
Fabian Ritzmann

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 s'il s'agit de quelque chose d'autre:

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

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

0
Jeremy

Utiliser simplement un répertoire outer pour la sortie a résolu le problème pour moi.

Sudo tar czf ./../31OCT18.tar.gz ./
0
Mohd Abdul Mujib