Блокировка файлов Bash, включая flock для подпроцессов
Я пытаюсь защитить свои скрипты от параллельного выполнения с помощью 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 через homebrew.
Когда я запускаю приведенный ниже сценарий, создаются блокировки, но я думаю, что разветвляю подписки, и именно эти сценарии я стараюсь обеспечить, чтобы не выполнялось более одного экземпляра каждый.
#!/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 и регистрируется на удаленном сервере, чтобы получить некоторые файлы. После завершения соединение закрывается. Я хочу subprocess1 каждые 15 минут через cron. Я сделал это с успехом, но иногда есть много файлов, чтобы захватить, и работа занимает больше 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"
и пример подпроцесса2:
#!/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 экземпляров.
Моя главная задача заключается в загрузке нескольких экземпляров ncftpget, который вызывается subprocess1, а затем, далее, третьего сценария, который я надеюсь включить, "subprocess2", который запускает java-программу, которая работает с загруженными файлами, и ncftpget, и java-программа могут не иметь параллельных процессов, не ломая много вещей. Но я не знаю, как их контролировать.
Я думал, что мог бы использовать что-то похожее на это в функции main() lock.sh:
#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
но я не уверен, как это включить.