Bra*_*ean 5 shell-script files
我正在尝试通过脚本压缩虚拟机映像文件,但我想确保该文件未被访问。我可以检查 virt-manager 是否正在运行,因为它应该是访问图像的唯一程序,但我不知道是否有更好的方法来做到这一点。我还希望脚本继续尝试,直到文件可以压缩为止。我也不知道怎么办。
#Check if virt-manager is running
if pgrep "virt-manager" > /dev/null
then
#re-run script until success
else
gzip -k < /home/brady/.vms/windows10/hdd.img > /media/backup/vms/windows10/hdd.$(date +"%F.%T).img.gz
Run Code Online (Sandbox Code Playgroud)
该lsof命令可以告诉您文件是否正在使用中。你可以把它放在一个while带有 a的循环中,sleep让它每隔一段时间检查一次。
例如:
在窗口 1 中,您可以运行 sleep 10000 > /tmp/x
在窗口 2 中运行此脚本:
#!/bin/bash
FILE=/tmp/x
while [ -n "$(lsof "$FILE")" ]
do
sleep 1
done
echo "File $FILE not in use"
Run Code Online (Sandbox Code Playgroud)
现在,当您按下control-C中止按钮时,sleep您将在一秒左右内看到“文件未使用”响应。
在安装了 inotify 工具的 Linux 上,您可以执行以下操作:
#! /bin/zsh -
file=${1?}
# if it's a symlink, we want the real file, readlink also tells us
# if the file is accessible
file=$(readlink -e -- "$file") || exit
# start inotifywait as a coproc so we can terminate it after we're
# done:
coproc LC_ALL=C inotifywait -me close --format . -- "$file" 2>&1
# Now wait for the "Watches established." messaged. First, that allows us
# to verify inotifywait started properly, and that also avoids the race
# condition where the last file user is gone after our fuser check but
# before the watch is in place
read <&p && read <&p && [ "$REPLY" = "Watches established." ] || exit
# Now watch CLOSE events until the file has no more user:
while fuser -s "$file" && read <&p; do continue; done
printf '"%s" is no longer used, renaming it to prevent new access\n' "$file"
kill %
ret=0
if mv -- "$file" "$file.moved-away"; then
printf 'and now compressing it\n'
pixz -t < "$file.moved-away" > "$file.xz" || ret=$?
mv -- "$file.moved-away" "$file" || ret=$? # move back
else
ret=$?
fi
exit "$ret"
Run Code Online (Sandbox Code Playgroud)
使用inotifywait,每次关闭文件的 fd 时我们都会收到通知。这意味着我们不必经常检查文件,只要最后一个用户关闭文件就可以开始压缩。
请注意,从我的测试来看,与我最初担心的相反,这也适用于 mmapped 文件,因为在这些情况下,CLOSE事件不是close()在最后生成,而是在最后一个munmap()(当文件完全释放时)。
fuser -s检查文件是否打开的方法比lsof. fuser也更有可能可用,因为它是标准的 UNIX 命令(虽然-s不是标准选项,但 Linux 上可用的版本确实支持它)。
我们将文件移开以防止在压缩之前进一步访问。
我们使用pixz(多线程版本的xz,虽然xz现在最新版本也支持多线程),因为它提供了比 gzip 更好的压缩率,更重要的是,因为压缩文件是随机访问的(您可以挂载内容或引导它在使用 nbdkit 的 VM 中,而无需解压缩整个图像)。
注意,相似的lsof,fuser将不会检测到文件被用作loop或mtd设备后端。对于循环设备,您可以losetup -j "$file"用来检查文件是否正在以这种方式使用。例如,您可以在文件移开后插入此循环:
while [ -n "$(losetup -j "$file.moved-away")" ]; do
sleep 1
done
Run Code Online (Sandbox Code Playgroud)