tar:文件在我们阅读时发生了变化

时间:2013-12-02 00:04:02

标签: makefile tar

我正在使用maketar进行备份。执行makefile时,tar命令显示file changed as we read it。在这种情况下,

  • 警告出现时,tar包正常
  • 但它会停止以下备份的tar命令
  • 显示警告的文件实际上没有改变 - 警告出现真的很奇怪
  • 显示警告的文件随机出现,我的意思是,每次运行我的makefile时,显示警告的文件都不同
  • --ignore-failed-read没有帮助。我在MinGW中使用tar 1.23
  • 我刚将计算机更改为WIN7 64位。该脚本在旧的WIN7 32位中运行良好。但tar版本并不像1.23那样新。

如何在警告后停止tar警告停止备份?


编辑-2 :这可能是

的原因

正如我上面所说,bash shell脚本在我的旧计算机上运行良好。与旧计算机相比,msys版本不同。 tar命令的版本也是如此。在旧计算机中,tar为1.13.19,在新计算机中为1.23。我复制了旧的tar命令,而没有将其依赖项msys-1.0.dll复制到新计算机并将其重命名为tar_old。我还在shell脚本中更新了tar命令并运行脚本。一切都好。所以,似乎问题是tar命令。我确信在去皮时没有任何文件被更改。这是新版本中tar命令的错误吗?我不知道。


编辑-1 :添加更多详情

备份由bash shell脚本调用。它扫描目标目录并构建makefile然后调用make以使用tar命令进行备份。接下来是由bash shell脚本构建的典型makefile。

#--------------------------------------------
# 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

如您所见,tar包存储在〜/ MS_bak_MSYS / tools / VC / VC_2010.tar.bz2中。我在〜/ qqaa中运行脚本。 tar命令不包括~/MS_bak_MSYS。所以,我创建的tar文件不在我试图放入tar文件的目录中。这就是为什么我觉得警告出现的原因很奇怪。

8 个答案:

答案 0 :(得分:55)

我也遇到了tar消息"在我们阅读它时改变了#34;。对我来说,当我在bitbake构建环境中制作Linux文件系统的tar文件时,会出现这些消息。这个错误是零星的。

对我而言,这不是因为从同一目录创建tar文件。我假设在创建tar文件期间实际上有一些文件被覆盖或更改。

该消息是一个警告,它仍然会创建tar文件。我们仍然可以通过设置选项

来抑制这些警告消息

--warning=no-file-changed

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

tar返回的退出代码仍然是" 1"在警告信息案例中: http://www.gnu.org/software/tar/manual/html_section/Synopsis.html

因此,如果我们从脚本中的某个函数调用tar文件,我们可以像这样处理退出代码:

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

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

答案 1 :(得分:28)

如果您需要帮助调试此类问题,则需要提供make规则或至少提供您调用的tar命令。如果没有命令可以看到,我们怎么能看到命令出了什么问题呢?

然而,99%的情况下,这样的错误意味着您正在尝试放入tar文件的目录中创建tar文件。因此,当tar尝试读取目录时,它会将tar文件作为目录的成员找到,开始读取它并将其写入tar文件,因此在它开始读取tar文件和完成时间之间读取tar文件后,tar文件已经改变。

例如:

tar cf ./foo.tar .

没有办法“停止”这个,因为它没有错。只需在创建它时将tar文件放在其他位置,或者找到另一种方法(使用--exclude或其他)来省略tar文件。

答案 2 :(得分:26)

虽然很晚但我最近遇到了同样的问题。

问题是因为dir .正在更改,因为在运行命令后创建了xyz.tar.gz。有两种解决方案:

解决方案1: 如果存档是在tar内的任何目录中创建的,.都不会介意。可能有原因导致无法在工作空间之外创建存档。通过创建一个临时目录来将存档放置为:

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

解决方案2: 这个我喜欢。在运行tar之前创建存档文件:

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

答案 3 :(得分:15)

如果是1,则忽略tar退出状态的单行代码。sandeep's script中不需要set +e。如果tar退出状态为0或1,则此单行将返回退出状态0.否则它将返回退出状态1.这与sandeep's script不同,如果是,则保留原始退出状态值与1不同。

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

答案 4 :(得分:1)

加强Fabian的单线程;让我们说我们只想忽略退出状态1,但如果是其他原因则保留退出状态:

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

这就是sandeep的脚本在一行上所做的一切。

答案 5 :(得分:0)

只需使用外部目录作为输出,就可以解决我的问题。

...
INNER JOIN (
        SELECT TOP 1 WITH TIES
                InstrumentDescription,
                version AS maxVersion,
                IsLatest, 
                Isin,
                Cusip,
                RbcType1,
                RbcType2,
                RbcType3  
        FROM [trade_management].[dbo].[Trades.BondRef] 
        WHERE ValidTo between '2018-10-30 00:00:00.0000000 +00:00' and '2018-10-30 23:59:29.0000000 +00:00' 
        ORDER BY ROW_NUMBER() OVER (PARTITION BY InstrumentDescription ORDER BY version DESC)
        ) AS B
ON B.InstrumentDescription = tr.InstrumentDescription
...

答案 6 :(得分:0)

它为我工作,增加了20秒的简单睡眠超时。 如果您的源目录仍在写入,则可能会发生这种情况。因此,请进行睡眠以使备份完成,然后tar应该可以正常工作。这也帮助我获得了正确的退出状态。

sleep 20
tar -czf ${DB}.${DATE}.tgz ./${DB}.${DATE}

答案 7 :(得分:0)

我不确定它是否适合您,但我注意到tar在管道模式下对已更改/删除的文件不会失败。明白我的意思。

测试脚本:

#!/usr/bin/env bash
set -ex
tar cpf - ./files | aws s3 cp - s3://my-bucket/files.tar
echo $?

手动删除随机文件...

输出:

+ aws s3 cp - s3://my-bucket/files.tar
+ tar cpf - ./files
tar: ./files/default_images: File removed before we read it
tar: ./files: file changed as we read it
+ echo 0
0