我正在尝试通过合并flock来保护我的脚本免于并行执行。我在这里阅读了许多线程并且遇到了对此的引用:http://www.kfirlavi.com/blog/2012/11/06/elegant-locking-of-bash-program/其中包含了其他线程中提供的许多示例。
我的脚本最终将在Ubuntu(> 14),OS X 10.7和10.11.4上运行。我主要在OS X 10.11.4上进行测试,并通过自制软件安装了flock。
当我运行下面的脚本时,正在创建锁,但我认为我正在分配下标,而我正在尝试确保这些脚本不会运行多个实例。
#!/bin/bash
#----------------------------------------------------------------
set -vx
set -euo pipefail
set -o errexit
IFS=$'\n\t'
readonly PROGNAME=$(basename "$0")
readonly LOCKFILE_DIR=/tmp
readonly LOCK_FD=200
subprocess1="/bash$/subprocess1.sh"
subprocess2="/bash$/subprocess2.sh"
lock() {
local prefix=$1
local fd=${2:-$LOCK_FD}
local lock_file=$LOCKFILE_DIR/$prefix.lock
# create lock file
eval "exec $fd>$lock_file"
# acquier the lock
flock -n $fd \
&& return 0 \
|| return 1
}
eexit() {
local error_str="$@"
echo $error_str
exit 1
}
main() {
lock $PROGNAME \
|| eexit "Only one instance of $PROGNAME can run at one time."
##My child scripts
sh "$subprocess1" #wait for it to finish then run
sh "$subprocess2"
}
main
$ subprocess1是一个脚本,它加载ncftpget并登录到远程服务器以获取一些文件。完成后,连接关闭。我想通过cron每15分钟进行一次subprocess1。我已经成功完成了这项工作,但有时会抓住很多文件并且工作时间超过15分钟。这种情况很少见,但确实发生了。在这种情况下,我想确保无法启动$ subprocess1的第二个实例。为清楚起见,这种下标的一个小例子是:
#!/bin/bash
remoteftp="someftp.ftp"
ncftplog="somelog.log"
localdir="some/local/dir"
ncftpget -R -T -f "$remoteftp" -d "$ncftplog" "$localdir" "*.files"
EXIT_V="$?"
case $EXIT_V in
0) O="Success!";;
1) O="Could not connect to remote host.";;
2) O="Could not connect to remote host - timed out.";;
3) O="Transfer failed.";;
4) O="Transfer failed - timed out.";;
5) O="Directory change failed.";;
6) O="Directory change failed - timed out.";;
7) O="Malformed URL.";;
8) O="Usage error.";;
9) O="Error in login configuration file.";;
10) O="Library initialization failed.";;
11) O="Session initialization failed.";;
esac
if [ "$EXIT_V" = 0 ];
then
echo ""$O"
else
echo "There has been an error: "$O""
echo "Exiting now..."
exit
fi
echo "Goodbye"
和subprocess2的一个例子是:
#!/bin/bash
...preamble script setup items etc and then:
java -jar /some/javaprog.java
当我使用“sh lock.sh”执行父脚本时,它会在脚本中无错误地退出并退出。我遇到的第一个问题是,如果我再次加载脚本,我会收到一个错误,指示只能运行一个lock.sh实例。我应该在脚本中添加什么来指示进程尚未完成(而不仅仅是退出并返回提示)。
但是,如果subprocess1自己运行,lock.sh将加载subprocess1的第二个实例,因为它没有被锁定。如何锁定子脚本并理想地确保分叉进程也得到了解决?如果有人在终端上运行subprocess1或者有一个失控的实例,如果cron加载了lock.sh,我会希望它在尝试加载其实例subprocess1和subprocess2时失败而不仅仅是在cron尝试加载两个lock.sh时退出实例
我主要担心的是加载由subprocess1调用的ncftpget的多个实例,然后是第三个我希望合并的脚本“subprocess2”,它启动一个处理下载文件的java程序,ncftpget和java程序不能没有破坏很多东西的并行进程。但我对如何充分控制它们感到茫然。
我以为我可以在lock.sh的main()函数中使用类似的东西:
#This is where I try to lock the subscript
pidfile="${subprocess1}"
# lock it
exec 200>$pidfile
flock -n 200 || exit 1
pid=$$
echo $pid 1>&200
但我不确定如何加入它。