V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
horek
V2EX  ›  Linux

crontab 能否实现每 50 秒执行一次定时任务

  •  
  •   horek · 2019-03-13 00:54:55 +08:00 · 9981 次点击
    这是一个创建于 2076 天前的主题,其中的信息可能已经有所发展或是发生改变。
    我有一个需要定时 50 秒执行一次任务的需求,想了半天,只能实现每 10 秒执行一次、30 秒执行一次,就是不知道 50 秒执行一次能不能设置,求指教
    41 条回复    2019-03-21 10:01:08 +08:00
    ysc3839
        1
    ysc3839  
       2019-03-13 01:49:58 +08:00 via Android
    大概不行。可以设置成 10 秒执行一次,然后记录一下执行次数,到 5 了才实际执行代码。
    xfspace
        2
    xfspace  
       2019-03-13 09:17:55 +08:00 via Android   ❤️ 1
    #!/usr/bin/env bash
    sleep 50
    balabala

    crontab -e
    * * * * * /something/bashfile
    sarie
        3
    sarie  
       2019-03-13 09:24:41 +08:00
    @xfspace 厉害了
    zhangxiaodao
        4
    zhangxiaodao  
       2019-03-13 09:56:08 +08:00
    你都会设置 30 秒了,50 秒为啥不能设置?
    MajorAdam
        5
    MajorAdam  
       2019-03-13 10:05:37 +08:00
    之前试过用 cron 表达式应该是不行的
    hanbaobao2005
        6
    hanbaobao2005  
       2019-03-13 10:42:57 +08:00
    试一下
    */50 * * * * *
    是不是可行
    hayi
        7
    hayi  
       2019-03-13 10:48:14 +08:00
    @hanbaobao2005 这肯定不行,60 秒一个周期,30 秒内的都可以这样。大于的就不行
    Patrick95
        8
    Patrick95  
       2019-03-13 11:03:29 +08:00
    * * * * * /bin/bash -l -c "/path/to/executable; sleep 50 ; /path/to/executable"
    horek
        9
    horek  
    OP
       2019-03-13 11:30:14 +08:00
    @hayi 我也觉得大于 30 秒的都不行
    glasslion
        10
    glasslion  
       2019-03-13 11:42:34 +08:00   ❤️ 2
    @hayi
    @horek

    cron 表达式 */n 的含义是,当秒数 /分钟数...能被 n 整除时执行, 而不是每 n 分钟执行.
    zhfish
        11
    zhfish  
       2019-03-13 11:52:50 +08:00
    https://crontab.guru
    最少是 1 分钟
    hugee
        12
    hugee  
       2019-03-13 12:20:29 +08:00
    @xfspace
    @Patrick95 你两这个不仍然 1 分钟一次?


    @hanbaobao2005 你这个不是 50 分钟才一次?

    lz 说的是每 50 秒一次吧?@horek
    radc
        13
    radc  
       2019-03-13 12:25:19 +08:00   ❤️ 3
    其实搭配 sleep 是可以实现任意秒数间隔的 就是蛋疼了一点
    比如想要 10s 间隔,那就取个分钟整数,做 sleep 10/20/30/40/50/60 6 个 cronjob (*/1 * * * *)
    要 30s 间隔,就 sleep 30/60,两个 cronjob, (*/1 * * * *)

    比如楼主想要 50s,那就取整到 300s,弄这么几个....... 每 300 秒装填 6 个任务,分别以 50 秒间隔来执行。
    ```
    */5 * * * * (sleep 50; echo `date` >> /tmp/50s.log)
    */5 * * * * (sleep 100; echo `date` >> /tmp/50s.log)
    */5 * * * * (sleep 150; echo `date` >> /tmp/50s.log)
    */5 * * * * (sleep 200; echo `date` >> /tmp/50s.log)
    */5 * * * * (sleep 250; echo `date` >> /tmp/50s.log)
    */5 * * * * (sleep 300; echo `date` >> /tmp/50s.log)
    ```
    测试输出是这样,符合预期 挺 2b 的方法.... but it works! 😂
    ```
    Wed Mar 13 12:15:51 CST 2019
    Wed Mar 13 12:16:41 CST 2019
    Wed Mar 13 12:17:31 CST 2019
    Wed Mar 13 12:18:21 CST 2019
    Wed Mar 13 12:19:11 CST 2019
    Wed Mar 13 12:20:01 CST 2019
    Wed Mar 13 12:20:52 CST 2019
    Wed Mar 13 12:21:42 CST 2019
    Wed Mar 13 12:22:32 CST 2019
    ```
    seeusoon
        14
    seeusoon  
       2019-03-13 12:43:37 +08:00
    这种需求可以直接考虑 supervise+py 来弄,逻辑简单清晰易于维护更新
    具体逻辑用 py 实现,supervise 负责保证 py 进程不退出
    fuergaosi
        15
    fuergaosi  
       2019-03-13 12:47:28 +08:00 via iPhone
    @seeusoon supervise 现在应该还是不支持 py3 吧
    xuboying
        16
    xuboying  
       2019-03-13 12:49:03 +08:00
    这是不是一个 A->B 问题?
    sfqtsh
        17
    sfqtsh  
       2019-03-13 12:49:59 +08:00 via Android
    用 at 命令
    LoliconInside
        18
    LoliconInside  
       2019-03-13 12:53:23 +08:00 via Android
    While True:
    time.sleep 50
    reus
        19
    reus  
       2019-03-13 12:56:57 +08:00
    有 systemd 的 timer 不用,非要用过时的 crond ?
    7654
        20
    7654  
       2019-03-13 12:57:18 +08:00
    while [ 1 ]
    do
    sleep 50
    done &
    jasonyang9
        21
    jasonyang9  
       2019-03-13 12:57:29 +08:00
    用 SystemD Timers
    Trim21
        22
    Trim21  
       2019-03-13 12:58:04 +08:00 via Android
    @zhangxiaodao 因为*/50 会在每个小时的 0 和 50 分钟执行,而不是每 50 分钟执行一次…
    Cooky
        23
    Cooky  
       2019-03-13 13:08:23 +08:00 via Android
    50 秒 和 60 秒 最小公倍数 300 秒
    你定个 5 分钟一次的周期
    一次执行的时候 跑一次 sleep 一下 6 回就够了
    wwqgtxx
        24
    wwqgtxx  
       2019-03-13 13:11:52 +08:00
    用 systemd timers,能精确到 us 级别,随便你想要多少秒
    aimiyooo
        25
    aimiyooo  
       2019-03-13 13:14:24 +08:00
    crontab 不支持,可以用 supervisor+死循环脚本实现
    MrUser
        26
    MrUser  
       2019-03-13 13:43:19 +08:00
    第一步:每 30 秒调用一次中间脚本 do.sh (小于你的 50 秒就可以):
    ```
    * * * * * /home/user/bin/do.sh >>/var/log/crontab-do.sh.log 2>&1
    * * * * * sleep 30; /home/user/bin/do.sh >>/var/log/crontab-do.sh.log 2>&1
    ```

    第二步:在中间脚本 do.sh 里判断是不是够 50 秒了(当前时间戳能被 50 整除说明 50 秒到了):
    ```
    #!/bin/bash
    dateTime=`date "+%Y-%m-%d %H:%M:%S"`
    timeStamp=`date -d "$dateTime" +%s`
    remainder=$(($timeStamp % 50))
    if [ $remainder = 0 ]; then
    echo "50 秒了,该执行你的脚本了,在这里调用你的脚本"
    fi
    ```
    MrUser
        27
    MrUser  
       2019-03-13 13:45:42 +08:00
    有 BUG,收回上边的回复。。。。( BUG:需要 60 条 crontab 才行。。。。)
    inf0sys
        28
    inf0sys  
       2019-03-13 16:31:27 +08:00
    crontab 小时位 /72 试试; )
    taolu
        29
    taolu  
       2019-03-13 16:41:48 +08:00
    time_step=50
    for (( i=0; i<300; i=(i+${time_step}) )); do
    shell
    sleep ${time_step}
    done

    */5 * * * * shell
    Raymon111111
        30
    Raymon111111  
       2019-03-13 17:19:05 +08:00
    10 秒来一次, 用计数器控制是个简单又可行的方案.
    yc8332
        31
    yc8332  
       2019-03-13 17:22:06 +08:00
    cron 不是分钟级的吗?秒级的应该要自己实现吧
    deepdark
        32
    deepdark  
       2019-03-13 17:39:49 +08:00 via Android
    @xfspace 老哥你这 50 秒之后,一秒执行一次啊,你只是第一次执行推迟了 50 秒而已
    zeroz
        33
    zeroz  
       2019-03-13 17:49:19 +08:00
    PHP 是世界上最好的语言!
    Swoole Timer 毫秒精度的定时器 https://wiki.swoole.com/wiki/page/p-timer.html
    houm
        34
    houm  
       2019-03-13 18:04:39 +08:00
    设 6 条 Cron,试试可行不 @horek
    50 0/6 * * * ?
    40 1/6 * * * ?
    30 2/6 * * * ?
    20 3/6 * * * ?
    10 4/6 * * * ?
    0 5/6 * * * ?
    hahaayaoyaoyao
        35
    hahaayaoyaoyao  
       2019-03-13 20:57:13 +08:00 via Android
    @reus 同意
    cpdyj0
        36
    cpdyj0  
       2019-03-13 21:01:19 +08:00
    要不就别用 crontab 了,写个脚本死循环 timeout 50,拿 systemd 监控,定时重启(防止内存泄漏,不知 bash 这方面是怎么做的)
    gscoder
        37
    gscoder  
       2019-03-13 21:05:41 +08:00
    做不到,只能用计数器控制。但那样定时器和逻辑就耦合起来了,不太好。
    cpdyj0
        38
    cpdyj0  
       2019-03-13 21:07:11 +08:00
    哦,bash 好像是类似引用计数那种东西(好像连计数也不存在的 [garbage-collection-in-bash]( https://stackoverflow.com/questions/14806296/garbage-collection-in-bash)
    所以倒是不必担心内存问题了,就是监控下别挂了
    cpdyj0
        39
    cpdyj0  
       2019-03-13 21:07:43 +08:00
    @gscoder 写俩脚本 /手动斜眼
    sujin190
        40
    sujin190  
       2019-03-14 15:34:07 +08:00
    https://github.com/snower/forsun

    推荐下之前写的工具,支持秒级定时,命令行和 crontab 类似

    安装
    pip install forsun

    启动
    forsund

    设置定时
    forsun "set show_date_to_home */50/0 * * * * * sh 'date >> /tmp/date.log'"

    查看定时列表
    forsun "ls *"

    删除定时
    forsun "rm show_date_to_home"

    时间设置还是多了第三个数字代表的是执行次数,0 代表一直执行,从设置这一刻往后 50 秒运行
    NB40B938mff85mtq
        41
    NB40B938mff85mtq  
       2019-03-21 10:01:08 +08:00
    sleep 正解
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1049 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 19:46 · PVG 03:46 · LAX 11:46 · JFK 14:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.