定时任务上一次还没跑完,下一次又启动时,常见结果是重复写文件或同时占用资源。Linux 上可以让 flock 持有一个文件描述符,拿不到锁就直接退出。
环境:Linux、Bash 4.4+、util-linux 的 flock。保存为 job.sh:
#!/usr/bin/env bash
set -Eeuo pipefail
lock_file=${LOCK_FILE:-/tmp/report-job.lock}
exec 9>"$lock_file"
if ! flock -n 9; then
printf 'job is already running\n' >&2
exit 75
fi
printf 'start pid=%s\n' "$$"
sleep "${1:-2}"
printf 'done pid=%s\n' "$$"
可以用临时锁文件验证第二个进程会被拒绝:
chmod +x job.sh
tmp=$(mktemp -d)
trap 'rm -rf -- "$tmp"' EXIT
LOCK_FILE="$tmp/job.lock" ./job.sh 1 &
first=$!
sleep 0.1
set +e
LOCK_FILE="$tmp/job.lock" ./job.sh 0
status=$?
set -e
wait "$first"
test "$status" -eq 75
锁跟着文件描述符存活,脚本正常结束或异常退出后都会由内核释放,不需要手动删除锁文件。需要排队等待时,把 flock -n 9 改成 flock -w 30 9,最多等 30 秒。这个写法依赖 Linux 的 flock,macOS 默认环境不能直接照搬。