在bash下执行锁定的一种简单且看似可靠的方法是:
exec 9>>lockfile
flock 9
然而,bash臭名昭著地将这样的fd锁传播到所有派生的东西,包括执行的程序等。
有没有办法告诉bash不要复制fd?很棒的是,锁被附加到一个fd上,当程序终止时,无论它是如何终止的,fd都会被删除。
我知道我可以做这样的事情:
run_some_prog 9>&-
但这是相当乏味的。
有没有更好的解决方案?
发布于 2012-01-15 07:26:30
您可以使用flock(1)
的-o
命令行选项(长选项--close
,这可能更适合于编写自文档化的脚本)来指定在通过flock(1)
执行命令之前应该关闭文件描述符
-o, --close
Close the file descriptor on which the lock is held
before executing command. This is useful if command
spawns a child process which should not be holding
the lock.
发布于 2012-08-08 18:11:07
显然,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
这有点CLUMSY
,因为FD的关闭距离锁太远了。
你可以重构这一点,放松“自然”的命令流,但将属于一起的东西放在一起:
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
顺便说一句,如果你真的想确保bash
不会引入额外的文件描述符(为了“隐藏”关闭的FD并跳过真正的fork),例如,如果你执行一些守护进程,然后它将永远持有锁,推荐使用后一种变体,只是为了确认一下。lsof -nP
和strace your_script
是你的朋友。
发布于 2012-01-15 07:25:26
在bash中,没有办法将FD标记为close-on-exec,所以没有更好的解决方案。
https://stackoverflow.com/questions/8866175
复制相似问题