我有一个脚本,它将本地文件复制到远程目录,并使用提及刚刚复制的脚本的新行更新远程文件。
有时,需要删除远程目录中的某些文件,并且应该更新提及它们的相应文件以删除相应的条目。
问题:该脚本可以从多个实例运行,并且可以针对远程服务器中的多个目录运行。即,远程服务器中有超过 1 个目录,用于存储我们根据传递给实例的类型复制的文件。如何使文件的副本和“日志”的更新有些原子性?
我没有运行太多并发实例,因此这是一个严重的问题,但我想知道是否有办法进行此类更改,以确保文件正确更新。
例如,以下内容会起作用吗?
scp file.bin remoteserver:/foo/$type/
grep -v "oldfile.bin" entries.log > entries.log.backup && mv entries.log.backup entries.log
echo "$record" >> entries.log
答案1
你需要使用锁;如果您正在运行 Linux 并拥有flock
(的一部分util-linux
),那么就很简单
scp file.bin remoteserver:/foo/$type/
(
flock 9
grep -v "oldfile.bin" entries.log > entries.log.backup && mv entries.log.backup entries.log
echo "$record" >> entries.log
) 9>entries.log.lock
这将复制文件,等待获取锁,然后以独占方式更新日志。我假设您想附加到日志中。
这里的想法是用作entries.log.lock
锁定文件(我们不能使用日志文件本身,因为我们将替换它)。9>entries.log.lock
如有必要,创建文件并将文件描述符 9 与其关联,在子 shell 中将运行括号之间的命令。flock 9
获取文件描述符 9 所指向的文件的锁,必要时等待;该锁将一直保持到文件描述符关闭为止,这将在子 shell 退出时发生。grep
,mv
然后echo
在锁下继续。
并发进程将能够scp
并行,但日志操作将被串行化。
如果你没有flock
,哪些 Unix 命令可以用作信号量/锁?有多种替代方案(该mkdir
方法在任何地方都适用)。