这样一个需求

调度器中同一个任务需要多次执行,但是每次执行前要确认环境是否就绪,不就绪需要进行初始化

这个初始化操作会需要较长的执行时间,且并发执行的情况下多个任务同时初始化会导致最终初始化的环境失败

解决思路

使用文件作为lock,同时lock记录当前的进程号

同时只有一个shell进程能进行lock的操作

初始化锁: 创建lock文件,写入自己的进程号,同时等待1s(防止同时检测文件不存在多个进程同时写入),再次判断写入的lock是当前进程

其他进程间隔固定时间进行检测文件存在,再判断lock进程是否存在,不存在则删除lock文件,自己尝试获取锁

初始化完成写入环境的version值到success,下次初始化过程中如果有success文件且version值相等则不再次初始化

## file_lock.sh
## sh file_lock.sh 1
#!/bin/bash
max_times=120
sleep_sec=1
try_times=0
lock_wait=1

VERSION=$1
if [[ -z ${VERSION} ]]; then
  VERSION=$(date +%Y%m%d%H%M%S%N | cut -b 1-17)
fi
stat_path=/tmp
version_file_name=version_file
lock_file_name=file_lock
version_file=${stat_path}/${version_file_name}
lock_file=${stat_path}/${lock_file_name}

for((; try_times<=max_times; try_times++)); do
if [[ -f ${lock_file} ]]; then
  pid=$(cat ${lock_file})
  echo "current lock pid:${pid}" 
  PID_EXIST=false
  if [[ -n '$pid' ]]; then
     PID_EXIST=$(ps aux | awk '{print $2}'| grep -w $pid)
  fi
  if [[ $PID_EXIST ]]; then
    echo "wait for other install, lock_file is ${lock_file}";
    sleep $sleep_sec;
  else
    echo "lock process not exists, remove and continue."
    if [[ -f ${lock_file} ]]; then
      rm ${lock_file}
    fi
  fi
else
  echo "no other script locked.";
  # try again
  mkdir -p ${stat_path}
  echo $$ > ${lock_file}
  sleep ${lock_wait}
  if [[ -f ${lock_file} ]] && [[ $(cat ${lock_file}) == $$ ]] ; then
    break;
  fi
fi
done

if [[ $try_times -gt $max_times ]]; then
  echo "all retry failed, delete lock and exit -1";
  if [[ -f ${lock_file} ]]; then
    rm ${lock_file}
  fi
exit -1
fi

echo "get exclusive lock, ready to do something"

if [[ "$(cat ${version_file})" != "${VERSION}" ]]; then
  echo "sleep 5s to mock"
  sleep 5s
else
  echo "no different."
fi

echo "something done"
if [[ -f ${lock_file} ]]; then
  echo ${VERSION} > ${version_file}
  echo "remove ${lock_file}"
  rm ${lock_file}
fi

echo "do something others"

## test_file_lock.sh
## sh test_file_lock.sh 1
#!/bin/bash
for (( i=50;i>0;i-- ))
do
sh file_lock.sh $1 &
done