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

war*_*rem 61 makefile tar

我正在使用make和tar备份.执行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
Run Code Online (Sandbox Code Playgroud)

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

小智 61

我也遇到了tar消息"因为我们读了它而改变了".对我来说,当我在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
Run Code Online (Sandbox Code Playgroud)

  • Tar以"1"为例:"如果tar被赋予\`--create',\`--append'或\`--update'选项,此退出代码意味着某些文件在存档时被更改,因此结果archive不包含文件集的确切副本." 这是令人沮丧的不良行为 - 它会杀死一条管道而且无法阻止它.*捂脸* (8认同)
  • @RyanBrodie我正在考虑`set -o pipefail; 焦油... | gzip`。但是我把它收回了。它不会杀死整个管道,因为退出被推迟到执行结束。 (2认同)
  • 这不是警告,而是错误。警告不会导致非零退出代码。 (2认同)

Moh*_*zim 39

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

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

解决方案1: tar不介意是否在内部的任何目录中创建存档..可能有原因导致无法在工作空间外创建存档.通过创建用于将存档放置为的临时目录来解决此问题:

mkdir artefacts
tar -zcvf artefacts/archive.tar.gz --exclude=./artefacts .
echo $?
0
Run Code Online (Sandbox Code Playgroud)

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

touch archive.tar.gz
tar --exclude=archive.tar.gz -zcvf archive.tar.gz .
echo $?
0
Run Code Online (Sandbox Code Playgroud)

  • 在解决方案2中,只需将`--exclude = archive.tar.gz`放在另一个optiosn` -zvcf`之前,它实际上运行良好. (3认同)
  • 第二种解决方案的关键点是“touch archive.tar.gz”,如果你想运行“tar”命令时它不存在,它将无法工作 (2认同)

Mad*_*ist 32

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

但是,99%的情况下,这样的错误意味着您在要尝试放入tar文件的目录中创建tar文件.因此,当tar尝试读取目录时,它会将tar文件作为目录的成员找到,开始读取它并将其写入tar文件,因此在它开始读取tar文件和完成时间之间读取tar文件后,tar文件发生了变化.

所以例如:

tar cf ./foo.tar .
Run Code Online (Sandbox Code Playgroud)

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


Fab*_*ann 17

如果它是1,则忽略tar退出状态的单行代码.没有必要set +e像sandeep的脚本那样.如果tar退出状态为0或1,则此单行将返回退出状态0.否则它将返回退出状态1.这与sandeep的脚本不同,如果不同于1,则保留原始退出状态值.

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


小智 6

加强法比安的单线;让我们说我们只想忽略退出状态 1 但如果退出状态是其他任何状态,则保留退出状态:

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

这在一行中完成了sandeep 脚本所做的一切。


Moh*_*jib 5

只需将外部目录用于输出,就为我解决了问题。

sudo tar czf ./../31OCT18.tar.gz ./
Run Code Online (Sandbox Code Playgroud)