Bash 防止锁传播
在bash下执行锁定的一种简单且看似可靠的方法是:Bash 防止锁传播,bash,locking,file-descriptor,Bash,Locking,File Descriptor,在bash下执行锁定的一种简单且看似可靠的方法是: exec 9>>lockfile flock 9 然而,众所周知,bash将这种fd锁传播到所有分叉的东西,包括执行的程序等 有没有办法告诉bash不要复制fd?锁被附加到fd上是很好的,当程序终止时,fd会被移除,不管它是如何终止的 我知道我可以做一些事情,比如: run_some_prog 9>&- 但这相当乏味 有更好的解决方案吗?在bash中没有办法将FD标记为close on exec,因此没有更好的解决
exec 9>>lockfile
flock 9
然而,众所周知,bash将这种fd锁传播到所有分叉的东西,包括执行的程序等
有没有办法告诉bash不要复制fd?锁被附加到fd上是很好的,当程序终止时,fd会被移除,不管它是如何终止的
我知道我可以做一些事情,比如:
run_some_prog 9>&-
但这相当乏味
有更好的解决方案吗?在bash中没有办法将FD标记为close on exec,因此没有更好的解决方案。您可以使用
-o
命令行选项来flock(1)
(长选项--close
,这可能更适合在脚本中编写自文档性质的代码)要指定在通过flock(1)
执行命令之前应关闭文件描述符,请执行以下操作:
-o
不适用于文件描述符,它只适用于文件。您必须使用-u
解锁文件描述符
我所做的是:
# start of the lock sections
LOCKFILE=/tmp/somelockfile
exec 8>"$LOCKFILE"
if ! flock -n 8;then
echo Rejected # for testing, remove this later
exit # exit, since we don't have lock
fi
# some code which shouldn't run in parallel
# End of lock section
flock -u 8
rm -f "$LOCKFILE"
通过这种方式,文件描述符将被锁定的进程关闭,并且由于每个其他进程都将退出,这意味着只有持有锁的进程才会解锁文件描述符并删除锁定文件。显然
flock-o FD
无法解决此问题。对于同一shell脚本中的后续命令,消除多余FD的一个技巧是将剩余部分包装到一个关闭FD的部分中,如下所示:
var=outside
exec 9>>lockfile
flock -n 9 || exit
{
: commands which do not see FD9
var=exported
# exit would exit script
# see CLUMSY below outside this code snippet
} 9<&-
# $var is "exported"
# drop lock closing the FD
exec 9<&-
: remaining commands without lock
写得好一点,保持自然的命令流,代价是另一个fork加上一个额外的流程和一点不同的工作流,这通常很方便但这不允许在外壳中设置变量:
var=outside
exec 9>>lockfile
flock -n 9 || exit
(
exec 9<&-
: commands which do not see FD9
var=exported
# exit does not interrupt the whole script
exit
var=neverreached
)
# optionally test the ret if the parentheses using $?
# $var is "outside" again
# drop lock closing the FD
exec 9<&-
: remaining commands without lock
var=外部
exec 9>>锁文件
鸥群-n 9 | |出口
(
exec 9Thx!正是我想要的。不适用于flock 9
,这仅适用于flock-o lockfile命令[args..]
情况
functions_running_with_lock()
{
: commands which do not see FD9
var=exported
# exit would exit script
}
var=outside
exec 9>>lockfile
flock -n 9 || exit
functions_running_with_lock 9<&-
# $var is "exported"
# drop lock closing the FD
exec 9<&-
: remaining commands without lock
var=outside
exec 9>>lockfile
flock -n 9 || exit
(
exec 9<&-
: commands which do not see FD9
var=exported
# exit does not interrupt the whole script
exit
var=neverreached
)
# optionally test the ret if the parentheses using $?
# $var is "outside" again
# drop lock closing the FD
exec 9<&-
: remaining commands without lock