27.13. flock - manage locks from shell scripts
?
### flock
??? 當多個進程可能會對同樣的數據執行操作時,這些進程需要保證其它進程沒有在操作,以免損壞數據.通常,這樣的進程會使用一個“鎖文件”,也就是建立一個文件來告訴別的進程自己在運行,如果檢測到那個文件存在則認為有操作同樣數據的進程在工作.
這樣的問題是,進程不小心意外死亡了,沒有清理掉那個鎖文件,那么只能由用戶手動來清理了.
flock 是對于整個文件的建議性鎖;也就是說如果一個進程在一個文件(inode)上放了鎖,那么其它進程是可以知道的,(建議性鎖不強求進程遵守)最棒的一點是,它的第一個參數是文件描述符,在此文件描述符關閉時,鎖會自動釋放;而當進程終止時,所有的文件描述符均會被關閉.于是,很多時候就不用考慮解鎖的事情.
flock分為兩種鎖:
一種是共享鎖 使用-s參數
一種是獨享鎖 使用-x參數
選項和參數:
-s? --shared:獲取一個共享鎖,在定向為某文件的FD上設置共享鎖而未釋放鎖的時間內,其他進程試圖在定向為此文件的FD上設置獨占鎖的請求失敗,而其他進程試圖在定向為此文件的FD上設置共享鎖的請求會成功.
-x,-e,--exclusive:獲取一個排它鎖,或者稱為寫入鎖,為默認項
-u,--unlock: 手動釋放鎖,一般情況不必須,當FD關閉時,系統會自動解鎖,此參數用于腳本命令一部分需要異步執行,一部分可以同步執行的情況.
-n,--nb, --nonblock:非阻塞模式,當獲取鎖失敗時,返回1而不是等待.
-w, --wait, --timeout seconds : 設置阻塞超時,當超過設置的秒數時,退出阻塞模式,返回1,并繼續執行后面的語句.
-o, --close : 表示當執行command前關閉設置鎖的FD,以使command的子進程不保持鎖.
-c, --command command : 在shell中執行其后的語句.
<>打開${LOCK_FILE} (打開LOCK_FILE文件,與文件描述符101綁定),原因是定向文件描述符是先于命令執行的.因此假如在您要執行的語句段中需要讀 LOCK_FILE 文件,例如想獲得上一個腳本實例的pid,并將此次的腳本實例的pid寫入 LOCK_FILE ,此時直接用>打開 LOCK_FILE 會清空上次存入的內容,而用<打開 LOCK_FILE 當它不存在時會導致一個錯誤.
#### example
> ntp
#!/bin/bash
#
#author junun
#description this script for start or stop check sever time from an ntp server every 1s
#please add in /etc/rc.local
#
script_0=$0
script_name=${script_0##*/}
lockfile=/var/lock/subsys/$script_name
pidfile=/var/run/$script_name
start() {
??? [ -f $lockfile ] && echo? -e "\033[31m$script_name is running...\033[0m" &&? exit 1
??? while true ;do
??????? /usr/sbin/ntpdate clock.isc.org > /dev/null 2>&1
??????? echo $$ > $pidfile
??????? touch $lockfile
??????? sleep 1
??? done
}
stop() {
??? [ ! -f $lockfile ] && echo? -e "\033[31m$script_name is not running...\033[0m" &&? exit 1
??? kill -TERM `cat $pidfile`
??? rm -rf $lockfile
}
case "$1" in
??? start)
??????? $1
??????? ;;
??? stop)
??????? $1
??????? ;;
??? *)
????? echo $"Usage: $0 {start|stop}"
????? exit 2
esac
exit $?
*/10 * * * * /usr/bin/flock -xn /var/run/check_time.lock -c '/usr/local/bin/monitor/check_time start &' > /dev/null 2>&1
>2 monitor
#!/bin/bash
#
#
SHELL_DIR=$(cd $(dirname $0);pwd)
LOCK_FILE=/dev/shm/`echo ${SHELL_DIR}|sed 's!/!.!g;s!.!!'`.monitor.lock
{
??? flock -n 100 || { exit 2; }
??? cd ${SHELL_DIR}
??? function monitor() {
??????? while true;do
??????????? ./run.sh monitor
??????????? sleep 3
??????? done
??? }
??? monitor >> ../logs/monitor.log 2>&1 &
} 100<>${LOCK_FILE}
#!/bin/bash
#
ulimit -c unlimited
ulimit -u unlimited
ulimit -HSn 655350
SERVER_NAME='changed_order_deal'
SHELL_DIR=$(cd $(dirname $0);pwd)
BASE_DIR=$(cd $(dirname $0);cd ..;pwd)
SHELL_FILE="${SHELL_DIR}/run.sh"
SERVER_BIN=${SHELL_DIR}/${SERVER_NAME}
LOG_DIR=${BASE_DIR}/logs
PID_FILE=${LOG_DIR}/PID
CONF_FILE=${BASE_DIR}/conf/${SERVER_NAME}.conf
LOCK_FILE=/dev/shm/`echo ${SERVER_BIN}|sed 's!/!.!g;s!.!!'`.monitor.lock
start() {
??? if [ ! -f "${SERVER_BIN}" ];then
??????? echo `date +"%F %T"` - ERROR - Can not find ${SERVER_BIN} ...
??????? exit 1
??? fi
??? PID=`/sbin/pidof ${SERVER_BIN}`
??? if [ x"${PID}" == x"" ];then
??????? cd ${SHELL_DIR}
??????? mkdir -p ${LOG_DIR}
??????? nohup ${SERVER_BIN} -flagfile=${CONF_FILE} >> ${LOG_DIR}/${SERVER_NAME}.stdout.log 2>&1 &
??????? # place the following shell sentence right after the nohup statement
??????? /sbin/pidof ${SERVER_BIN} > ${PID_FILE}????????? #進程pid寫入文件
??????? echo "`date +"%F %T"` - start ${SERVER_BIN} "
??? else
??????? ps aux|grep pt_auth
??????? echo "`date +"%F %T"` - ERROR - PID:${PID} exist. ${SERVER_BIN} is already running."
??? fi
}
stop() {
??? PID=`cat ${PID_FILE}`
??? if [ x"${PID}" == x"" ];then
??????? echo "`date +"%F %T"` - ERROR - ${SERVER_BIN} is not running..."
??? else
??????? kill -15 $PID
??????? while true
??????? do
??????????? if test $( ps aux | awk '{print $2}' | grep -w "$PID" | grep -v 'grep' | wc -l ) -eq 0;then
??????????????? echo "`date +"%F %T"` - SUCCESS - ${SERVER_BIN} has been stopped..."
??????????????? > ${PID_FILE}
??????????????? break
??????????? else
??????????????? echo "`date +"%F %T"` - wait to stop..."
??????????????? sleep 1
??????????? fi
??????? done
??? fi
}
kill9() {
??? PID=`cat ${PID_FILE}`
??? if [ x"${PID}" == x"" ];then
??????? echo "`date +"%F %T"` - ERROR - ${SERVER_BIN} is not running..."
??????? exit 1
??? else
??????? kill -9 $PID
??? fi
}
restart() {
??? stop
??? start
}
monitor() {
??? check_num=`ps ax -o pid,cmd|grep "$SERVER_BIN"|grep -v grep|wc -l`
??? if [ $check_num -eq 0 ];then
??????? start
??????? echo `date +"%F %T"` - restart.
??? fi
}
case "$1" in
??? "start")
????? start;
??? ;;
??? "stop")
????? stop;
??? ;;
??? "restart")
????? restart;
??? ;;
??? "kill9")
????? kill9;
??? ;;
??? "monitor")
????? monitor;
??? ;;
? *)
??? echo "Usage: $(basename "$0") start/stop/restart/kill9/monitor"
??? exit 1
esac
* * * * * /srv/bin/monitor.sh? &> /dev/null
?
?
原文出處:Netkiller 系列 手札
本文作者:陳景峯
轉載請與作者聯系,同時請務必標明文章原始出處和作者信息及本聲明。
總結
以上是生活随笔為你收集整理的27.13. flock - manage locks from shell scripts的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Cannot find module '
- 下一篇: Python 爬虫 大量数据清洗 -