• crontab使用进程锁解决冲突


    想到一个问题,如果在crontab里有个定时任务设置为一分钟执行一次,但是它执行的时间可能会超过一分钟,此时crontab一分钟后会再次运行该脚本吗?这样会不会出现冲突呢?网上找了下,说可以用Linux中的进程锁控制crontab执行的并发问题。

    给一个shell脚本加锁,使用flock命令。

    一般格式:
    flock [-sxun][-w #] fd#
    flock [-sxon][-w #] file [-c] command...

    常用选项:
    -s, --shared :获得一个共享的锁。
    -x, --exclusive :获得一个独占的锁。
    -u, --unlock :移除一个锁,通常是不需要的,脚本执行完后会自动丢弃锁。
    -n, --nonblock :如果没有立即获得锁直接失败而不是等待。
    -w, --timeout :如果没有立即获得锁就等待指定的时间。
    -o, --close :在运行命令前关闭文件的描述符。用于如果命令产生子进程时会不受锁的管控。
    -c, --command :在shell中运行一个单独的命令。
    -h, --help :显示帮助。
    -V, --version :显示版本。

    测试一下看看:
    在/home目录下建立一个test.sh。

    vim /home/test.sh

    输入:

    #!/bin/bash
    wget --limit-rate=200k -P /tmp http://cachefly.cachefly.net/100mb.test

    运行一个超过一分钟的命令。

    chmod +x /home/test.sh

    编辑crontab:

    crontab -e

    输入:

    */1 * * * * /usr/bin/flock -xn /var/run/test.lock -c '/home/test.sh'

    设置每一分钟执行一次。

    重启服务:

    service crond restart

    这样只有第一个进程执行完毕后,才会执行当前的下一个进程。在第一个进程执行过程中,下一分钟crontab运行flock检测到获得不了锁,就直接退出,直到第一个进程执行完,flock再次获得锁。

    注:

    1、这种使用文件锁的方式,在linux中非常常见,通过一个pid文件,来避免两个进程同时运行,mysql和postgresql都有pid文件,mysql中只记录了pid值,postgresql的pid中除了记录有pid值,还有数据目录,pid文件的创建时间,端口号,监听地址和共享内存的地址。

    2、使用PID文件锁还有一个好处,方便进程向自己发停止或者重启信号。Nginx编译时可指定参数--pid-path=/var/run/nginx.pid,进程起来后就会把当前的PID写入这个文件,当然如果这个文件已经存在了,也就是前一个进程还没有退出,那么Nginx就不会重新启动。进程管理工具Supervisord也是通过记录进程的PID来停止或者拉起它监控的进程的

    3、flock加的advisory lock,也就是建议性锁,巧合的是,postgresql中也有advisory lock,非常适用于秒杀等高并发的场景。flock是通过获取文件的fd来加锁的。

    参考:

    http://www.live-in.org/archives/1036.html

    https://linux.die.net/man/2/flock

  • 相关阅读:
    2019年技能学习计划
    EVM项目管理
    常用LINQ关键字用法汇总
    如何让Enum枚举实现异或操作
    使用COM打开Excel文档注意事项
    C#使用NPOI读写Excel的注意事项
    应用国际化多语言化实现方法
    DLL简单分析与调用方法
    C#读写Excel实践笔记
    Vue基础开发笔记
  • 原文地址:https://www.cnblogs.com/xiaotengyi/p/6926058.html
Copyright © 2020-2023  润新知