在bash中的文件中执行原子写操作


13

通过庆典会后文件这个问题,一个它仍然不是很清楚,我哪能执行原子写入(追加)操作在bash文件。我有一个在多个实例中运行的脚本,有时必须将数据写入文件:

echo "$RESULT" >> `pwd`/$TEMP_DIR/$OUT_FILE

如何使所有同时运行的脚本的所有写操作都变为原子文件(这样,一个实例中的数据不会与另一个实例中的数据重叠)?


1
仅供参考,您不需要`pwd`; 您可以只使用点(.)。另外,您应该引用整个文件名,因为它包含变量
2016年

1
您可能还想研究使用FIFO的可能性。
2016年

@Wildcard谢谢。我pwd以前在脚本中使用过的方法是通知用户当前的工作目录,并在日志文件中写入条目。现在查看FIFO。
塞比2016年

1
实际上,在此站点上,对FIFO有更好的介绍。我几分钟前提供的链接只是POSIX规范mkfifo,并不完全是入门级的。
通配符

无论是FIFO还是文件,您仍然冒着两个实例同时写入并使彼此的输出乱码的风险。
clacke

Answers:


10

似乎您需要使用flockman(http://linux.die.net/man/1/flock)中的示例

(
flock -x 200

# Put here your commands that must do some writes atomically

) 200>/var/lock/mylockfile 

并将所有必须是原子的命令都放在()中。


即使(flock -s 200#将您必须执行一些原子写操作的命令放在此处)200> / var / lock / mylockfile是否跨多个同时运行的脚本读取,写操作仍将是原子操作 或者相反,锁定是否仅相对于/ var / lock / mylockfile?
塞比2016年

1
您的脚本锁定了/ var / lock / mylockfile,但是脚本的仅一个实例可以对其执行写锁定。其他实例将等到/var/lock/mylockfile可用于锁定。

-s是共享锁-适用于读取,对于写锁,必须使用-x / -e。它在您链接的手册页中。
埃文·本

该代码在什么时候解锁?一旦有东西被/var/lock/mylockfile调用的过程写入flock -x
克里斯·斯特里钦斯基

@ChrisStryczynski您可以(flock -x 200; date; sleep 10; date;) 200>/var/lock/mylockfile在两个外壳程序中运行此示例,并看到只有在执行()中的所有命令(在子外壳程序中)之后,解锁才会发生

4

flock是联锁操作的方式之一。该实用程序是util-linux工具集的一部分,仅适用于Linux。其他实用程序可在更广泛的平台上使用,它们基于Daniel J. Bernstein的setlockdaemontools软件包中的实用程序:

  • setlock 来自daemontools
  • setlock 来自Bruce Guenter的daemontools-encore
  • s6-setlock 摘自Laurent Bercot的s6
  • chpst 从Gerrit Pape的肖像
  • runlock 来自韦恩·马歇尔的观点
  • setlock 从我的nosh工具集中

这些工具的操作范式与M. Kurenkov的答案(也flock可以使用但不在该答案中的用法)中使用的范例稍有不同。一个调用setlock程序将加载链式链接到必须互锁的命令。 setlock本身会打开并锁定锁文件,并在其进程中保留一个文件描述符以供打开。锁定将一直持续到该过程(除非随后的命令链接到通过查找并关闭打开的文件描述符显式释放锁定)。

对于问题中的情况,必须将生成输出行的命令互锁,要知道这会代替外壳内置命令而调用外部 命令:echoecho

setlock mylockfile回显“ $ RESULT” >> ./$TEMP_DIR/$OUT_FILE

在这种情况下,无需在附加模式下互锁打开输出文件。如果是这样,则必须在锁中打开该文件,这需要使用fdredir/之类的程序redirfd

setlock mylockfile fdredir-追加1“ ./$TEMP_DIR/$OUT_FILE”回显“ $ RESULT”
如果需要,可以将其转换为shell函数:

outfile(){setlock mylockfile fdredir-追加1“ ./$TEMP_DIR/$OUT_FILE”“ $ @”; } 
[…]外文件
回显“ $ RESULT”
或坚持使用shell语法并由互锁下运行的第二个shell解释它,如果一个人的shell变量未作为环境变量导出,则需要一些不平凡的引用:

setlock mylockfile sh -c'echo'“ $ RESULT”'>>“ ./'$TEMP_DIR'/'$OUT_FILE'”'

当然,这可以概括为除写入输出文件以外的内容:

setlock mylockfile sh -c'...互锁;东西 …'

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.