我有一台服务器每小时接收目录
backupname.tar.gz
中的文件。/home/my_user/drop
我安装了 incron 实用程序,并使用 incrontab -e 条目在 /drop 中出现新文件时运行脚本
这是脚本:
#!/bin/sh
#
# First clear the 2 immediate use directories
rm /home/my_user/local_ready/*
wait
sleep 1
rm /home/my_user/local_restore/*
wait
sleep1
# Copy the file from the /drop /local_ready
cp /home/my_user/drop/*.tar.gz /home/my_user/local_ready/
wait
sleep 5
# Now move the file to the /current folder
mv /home/my_user/drop/*.tar.gz /home/my_user/current/
wait
sleep 1
# Next we delete any stray files dropped that are not
# of the target type so we can keep /drop clean.
rm /home/my_user/drop/*
wait
sleep 1
# Un-Tar the files into the /local_restore directory
tar -xzf /home/my_user/local_ready/*.tar.gz -C /home/my_user/local_restore/
wait
sleep 1
# This should complete the movement of files
我遇到的问题是复制到/local_restore
目录的文件被截断,就好像脚本中的下一个命令导致命令中断一样cp
。
首先,我在其中添加了 sleep 命令以尝试使其工作,然后我在脚本中的每个命令之后添加了 wait 命令,以尝试使其工作,认为这将强制所有内容等待 cp 命令完成文件复制到下一个位置。
我什至无法判断该tar
命令是否正在工作,因为它取决于该命令是否成功地cp
沿着链向上放置文件。根据我仅使用解压缩其中一个文件的命令运行的测试,我怀疑在脚本退出之前它也不会完成。至少在我用来测试我的时序理论的另一个 3 线测试中发生了这种情况。
顺便说一句...该mv
命令工作得很好,整个文件按预期移动。
任何人都可以确定为什么脚本中运行的命令似乎无法完成其任务?
我被要求显示 incrontab 条目的内容,所以这里是:
/home/my_user/drop/ IN_CREATE /home/my_user/bin/cycle_backups
(cycle_backups显然是脚本文件的名称)
这是运行 Ubuntu 16.04 LTS 的 KVM 类型 VPS 云服务器,拥有 10GB 内存和超过 100GB 磁盘空间。当文件被删除时,这是服务器除了系统空闲之外唯一要做的事情!
我承认我的服务器有点慢,因此当尝试将 200mb 文件复制到另一个目录时,即使我在命令行中正确执行此操作,也需要一两秒才能完成。
我无法解释这个问题,这使得找到解决方案变得更加困难。
公平警告:我在这方面并不是最擅长的,但我不认为这是一件不可能完成的事情。
答案1
wait
由于没有后台任务,因此任何调用都不会在脚本中执行任何操作。您可以安全地删除这些内容。
我也会删除对的调用sleep
。它们只会在这些点延迟脚本执行。无论如何,只有前一个命令正确完成后,命令才会启动。也sleep1
有可能生成“命令未找到”错误。
我在你的脚本中看到的唯一真正的问题是最后一次调用tar
:
tar -xzf /home/my_user/local_ready/*.tar.gz -C /home/my_user/local_restore/
如果 中有多个档案/home/my_user/local_ready
,则此命令将提取第一个档案,并尝试从该档案中提取其他档案的名称。该-f
标志采用单身的存档,并且您实际上无法一次提取多个存档。
相反,使用循环:
for archive in /home/my_user/local_ready/*.tar.gz; do
tar -xzf "$archive" -C /home/my_user/local_restore/
done
我有被忽略考虑如果此脚本与其自身同时运行会发生什么情况。您提到当新文件出现时您有一些工具可以执行脚本,但不清楚如果两个或更多文件同时出现会发生什么。由于脚本正在处理全部文件在一次调用中,我非常确定两个同时运行的脚本很可能会踩到对方的脚趾。
就我个人而言,我可能会每隔五分钟运行一次脚本。或者,使用某种形式的锁定来确保脚本在脚本的另一个副本已经在运行时不会运行(请参见“shell 脚本中的锁定是否正确?”)。
这是我自己重写的代码(不进行任何形式的锁定):
#!/bin/sh -e
cd /home/my_user
# clear directories
rm -f local_ready/*
rm -f local_restore/*
# Alternatively, remove directories completely
# to also get rid of hidden files etc.:
#
# rm -rf local_ready; mkdir local_ready
# rm -rf local_restore; mkdir local_restore
# handle the archives, one by one
for archive in drop/*.tar.gz; do
tar -xzf "$archive" -C local_restore
cp "$archive" current
mv "$archive" local_ready
done
这将清除非隐藏名称的目录,然后提取每个存档。提取存档后,它将被复制到目录local_ready
,然后存档也会从 移动drop
到current
。
我用来sh -e
使脚本在错误时终止,并cd
进入/home/my_user
目录以避免脚本中出现长路径(这也使得以后更容易将整个操作移动到子目录或其他地方)。我用于rm -f
清除这些目录,如果glob 没有扩展到任何内容,rm
则会抱怨。*
显然,您还可以单独处理存档复制和提取:
cp drop/*.tar.gz current
mv drop/*.tar.gz local_ready
for archive in local_ready/*.tar.gz; do
tar -xzf "$archive" -C local_restore
done
为了节省空间,您可能需要研究硬链接local_ready
和中的文件current
:
mv drop/*.tar.gz local_ready
for archive in local_ready/*.tar.gz; do
ln "$archive" current
tar -xzf "$archive" -C local_restore
done
答案2
您应该将掩码更改为 IN_CLOSE_WRITE