2
oneisall8955 195 天前
每隔 7 分钟执行一次?
https://crontab.guru/#*/7_*_*_*_* |
3
superrichman 195 天前 5
60 不能被 7 整除,单纯用 cron 是不行的
|
4
FranzKafka95 195 天前 via Android
@superrichman 为什么要考虑 60 被 7 整除,op 的需求只是间隔 7 分钟
|
5
xzh920126 195 天前 6
cron 每分钟执行一次 sh ,在 sh 里判断时间
|
6
timnottom 195 天前
|
7
Puteulanus 195 天前 3
用 7 条 cron 把一个 420 分钟循环内落在每个小时里的分钟数都给写上,应该可以
|
8
wuyadaxian OP @xzh920126 sh 不能修改。实际上可能是我不能控制的已经封装好的程序。这里只是讨论单纯用 crontab 内能不能实现。用 sh 就很方便了。
|
10
abelyao 195 天前
@tmtstudio
@oneisall8955 @FranzKafka95 @xzh920126 cron 不行吧?*/7 * * * * 的话,在 17:56 会执行一次,在 18:00 又会执行一次了 |
11
xzh920126 195 天前 1
|
12
superrichman 195 天前 4
@FranzKafka95 因为 cron 表达式 */7 只会在能被 7 整除的时候执行,举例来说 17:56 和 18:00 的时候都会执行,这可不是每 7 分钟运行一次的意思。
|
13
dapang1221 195 天前
*/7 * * * * date >> /var/root/test.log
加上了,半小时后我过来回复到底能不能用 |
14
xzh920126 195 天前
@wuyadaxian 明白你的意思了,等大佬解惑~
|
15
bthulu 195 天前
别用 cron, 不稳定, 不定什么时候就漏执行了
|
16
wuyadaxian OP @xzh920126 都上 sh ,不如直接 sh 内调用,然后 sleep 420 。循环就好。所以只是在讨论。实际用其他脚本语言会更快。
|
17
Moyyyyyyyyyyye 195 天前
|
18
ChengLuffy 195 天前 1
@wuyadaxian cron 每分钟 -> bash 脚本判断 -> 目标程序执行
|
19
1462326016 195 天前
|
20
lithiumii 195 天前 via Android
cron 写每分钟运行,命令先判断当前时间是否整除然后再运行,bash 的各种离谱写法应该可以实现
|
21
hahahahahahahah 195 天前
crontab 没法实现
|
22
Puteulanus 195 天前 5
|
23
wuyadaxian OP @Puteulanus 换天的时候会混乱。按照上面代码,第一天 23:48,23:55 分执行,第二天 00:00,00:07 执行.-------实际第二天应该 00:02,00:09 执行
|
24
carity 195 天前
五楼方案不是挺好的吗
|
25
Puteulanus 195 天前
@wuyadaxian 确实,忘了考虑这点 😂
|
26
wuyadaxian OP @Puteulanus 穷举法其实我想过,前面 4 位,分/小时/天/月,每次进位都会出现问题。因为 60 分/24 小时/28 天 or29 天 or30 天 or31 天/12 月 ,以上数字均不能被 7 整除形成循环。全部穷举后如果每年都是 365 天,7 年可以循环一次。但是实际上每 4 年有一次有闰年,也就是每 28 年才能穷举一次所有时间。
|
27
busier 195 天前 2
@wuyadaxian "都上 sh ,不如直接 sh 内调用,然后 sleep 420 。循环就好。所以只是在讨论。实际用其他脚本语言会更快。"
不可靠!脚本运行命令以及等待命令返回都是要消耗时间的,并且这个时间还不确定。 你可以每 sleep 420 将系统 RTC 时间写一下 log ,累积起来时间偏差会越来越大! 所以应该通过不断(例如每 0.2s)读取 UNIX 时间戳方式判断是否经过了 7 秒。而不能去 sleep 7 秒。 |
28
wuyadaxian OP @busier 感谢提醒,收到。确实 sleep 是在调用之后,会累计增加前面一句调用时间。
|
29
wudanyang 195 天前
|
30
busier 195 天前
@wuyadaxian 你前面的,涉及时间计算的问题统一用 UNIX 时间戳进行。彻底解决各种烦恼!
|
31
emor 195 天前
用 5 楼的方式,每分钟扫描一次,获取时间戳,t = 时间戳毫秒/11000/60 ,再用对 t 对 7 取余
|
32
wuyadaxian OP @Puteulanus 等等,我发现一周可以被 7 整除,而且一周这个单位不会被前面 4 个所影响。所以使用最后一个周作为标记来进行穷举即可。
|
33
snipking 195 天前 2
@wuyadaxian 不是还有星期这一位吗?考虑到跨天,写 49 条也能穷举了
|
34
wuyadaxian OP @Puteulanus 我们只需要每天穷举 7 条 cron ,每周 7 天穷举 49 条 cron 就能实现。如果需要增加偏移量,只需要更改周的位置即可。
|
35
skyrim61 195 天前
@dapang1221 半个小时过去了
|
36
suyuyu 195 天前
@dapang1221 38 分钟了怎么说
|
37
wps353 195 天前
systemd.timer 应该可以
|
38
mohumohu 195 天前
#!/bin/sh
start_time=$(date +%s) while true; do current_time=$(date +%s) elapsed_time=$((current_time - start_time)) if [ $elapsed_time -ge 420 ]; then ./myscript.sh start_time=$(date +%s) fi sleep 1 done |
39
mohumohu 195 天前
* * * * * ( [ -f /tmp/timestamp ] || date +\%s > /tmp/timestamp ) && [ $(( $(date +\%s) - $(cat /tmp/timestamp) )) -ge 420 ] && ( ./myscript.sh && date +\%s > /tmp/timestamp )
|
40
wuyadaxian OP @mohumohu 后面 command 部分能接这种复杂的命令集吗?我尝试了下 cron 没运行(不知道是不是我的问题),但是直接输入后面的 command 是可以运行的。
|
41
mohumohu 195 天前
@wuyadaxian 写绝对路径试试,/bin/date
|
42
pckillers 195 天前 4
cron 每分钟执行一次 sh 。 sh 里每次都判断特定文件夹里有几个文件。有 6 个文件时清空文件夹并执行实际代码。 不满 6 个文件时把当前 timestamp 作为文件名创建文件,不执行代码。
这样就能 7 分钟一次了 |
43
Richared 195 天前
定时每分钟执行,脚本里判断次数不就完了么。
|
44
lolizeppelin 195 天前 1
先说清楚,间隔从执行开始算起还是执行后算起
执行前算起的话,脚本执行超过 7 分钟如何处理 |
45
wuyadaxian OP |
46
wuyadaxian OP @lolizeppelin 每隔 7 分钟,执行一次 test 脚本,不管 test 脚本之后的状态。
|
47
lolizeppelin 195 天前
Ubuntu 22.04 不是有 systemd 么,
timer OnUnitActiveSec 搞定,用啥 cron |
48
lrh3321 195 天前
该切到 systemd 的 timer 上了
|
49
yankebupt 195 天前
如楼主回复所言,day of the week 可以被 7 整除,所以穷举一下是可以的,可能也就一千多条吧,换上用 slash(/)的 initial value 优化下也有几百条,真的合适么……
|
50
wuyadaxian OP @yankebupt 见 33 ,34 楼,只需要 49 条,还可以设置偏移量。
|
51
wuyadaxian OP @mohumohu 我找到一篇文章,https://href.lu/15A 。此文章表示在 macOS 中成功使用了复杂的 command 。但是我在我现在的 linux ubuntu 下没有运行成功。不知道是不是哪里错了,比如需要用引号之类的。
|
52
brant2ai 195 天前
从每个小时的角度,每隔 7 分钟,就有 7 种开始时间。所以可以在每个小时开始时判断开始判断是那种,然后复写调度。
|
53
yinxs2003 195 天前 via Android
*/7
对吗,我猜的 |
54
brant2ai 195 天前
@brant2ai 比如 0 分钟开始,调度就是 0 ,07 ,14 ,21 ,28 ,35 ,42 ,49 ,56 ,以及下个小时的 03 。在 63 的时间点,判断是不是个位,如果是,则继续加到下一个小时,并覆盖 crontab
|
55
killva4624 195 天前
每 7 分钟一次,不能能用简单整除的方法,我想到的:
- 要么就穷举一次循环,把循环分钟记录下来作为判断; - 要么就每次执行完写一次时间到文件,下次运行的时候从这个文件判断要不要是不是已间隔 7 分钟。 |
56
xuanbg 195 天前
cron 做不到,脚本内循环判断时间戳/60 后对 7 取余是否为 0 即可。但你要保证每次执行业务逻辑都能在 7 分钟内完成才行。
|
57
wuyadaxian OP @brant2ai 复写的时候是哪段代码或什么外部程序或者谁(真人)来进行。
|
58
brant2ai 195 天前
@wuyadaxian #57 你可以写到/etc/crontab 里,每次删除最后一条再把新的插入进去
|
59
brant2ai 195 天前
@wuyadaxian #57 就是你自己的这个脚本本身需要有权限去写。开权限就可以了
|
60
RedisMasterNode 195 天前
@xzh920126
> cron 每分钟执行一次 sh ,在 sh 里判断时间 就算能修改 sh 好像也不行呀,看上下文基本可以确认是个无状态的任务(那就假设它是吧),sh 里怎么知道上次执行是啥时候,隔了多久咧 |
61
wuyadaxian OP @brant2ai 要操作外部脚本啊,那就不在讨论范围了。都能用外部脚本了,方法就多了,楼上很多。
|
62
dapang1221 195 天前 4
Thu May 30 17:07:00 CST 2024
Thu May 30 17:14:00 CST 2024 Thu May 30 17:21:00 CST 2024 Thu May 30 17:28:00 CST 2024 Thu May 30 17:35:00 CST 2024 Thu May 30 17:42:00 CST 2024 Thu May 30 17:49:01 CST 2024 Thu May 30 17:56:00 CST 2024 Thu May 30 18:00:00 CST 2024 Thu May 30 18:07:00 CST 2024 Thu May 30 18:14:00 CST 2024 Thu May 30 18:21:00 CST 2024 Thu May 30 18:28:00 CST 2024 Thu May 30 18:35:00 CST 2024 Thu May 30 18:42:00 CST 2024 实测只用 */7 * * * * 确实不行 - - @skyrim61 @suyuyu |
63
foursking 195 天前
*/7 不行,如果一定要实现间隔,貌似只能 外部引入一个 sleep_7_minutes.sh 实现
|
64
brant2ai 195 天前
@wuyadaxian #61
$schedule->command('b2buhrenApi:productSync') ->when(intval(time()/60) % 7 ==0); 这个是老外的回答,你试试 https://laracasts.com/discuss/channels/laravel/how-to-run-schedule-every-7-minutes?page=1&replyId=821790 |
65
RRRoger 195 天前
最小公倍数原理
|
66
brant2ai 195 天前
@wuyadaxian #61 又找了一个
[[ $(($(date +'%s / 60 % 7 '))) -eq 0 ]] && |
67
wuyadaxian OP @brant2ai 我试试
|
68
brant2ai 195 天前
@wuyadaxian #61 * * * * * [[ $(($(date +'%s / 60 % 7 '))) -eq 0 ]] && command 前面的这个并上你的命令,每分钟做判断,如果是就执行
|
69
aa51513 195 天前 via Android
@RedisMasterNode 写文件,把上次运行的时间写到文件里,我看很多程序就把自身运行的 pid 写到文件里,很常规的操作吧
|
70
wuyadaxian OP @brant2ai bash: syntax error near unexpected token `(' 是我的环境问题吗
|
71
wuyadaxian OP @brant2ai 你可以看看 45 楼和 51 楼,我不确定是不是我环境或者什么问题,在 ubuntu 下无法执行。
|
72
brant2ai 195 天前
@wuyadaxian #70 减掉一层括号试试
|
73
wuyadaxian OP @brant2ai 另外这个算没用 cron 了吧。
|
74
RedisMasterNode 195 天前
@aa51513 要能这么玩我估计不会有本帖 hhh
|
75
vipfts 195 天前
@wuyadaxian #34 学到了
|
76
mohumohu 195 天前
* * * * * source /etc/profile && ( [ -f /tmp/timestamp ] || date +\%s > /tmp/timestamp ) && [ $(( $(date +\%s) - $(cat /tmp/timestamp) )) -ge 10 ] && ( echo 2 && date +\%s > /tmp/timestamp )
|
77
brant2ai 195 天前
@wuyadaxian #73
@wuyadaxian #70 我在服务器上测试是可以的 [[ $(($(date +'%s / 60 % 7 '))) -eq 0 ]] && echo hello 。另外这个是目前最简单的不用引用外部的做法 |
78
wuyadaxian OP @brant2ai 同样,在 cron 里面* * * * * [[ $(($(date +'%s / 60 % 7 '))) -eq 0 ]] && command 。 [无法运行] ------在 tty 内,[[ $(($(date +'%s / 60 % 7 '))) -eq 0 ]] && command 。 [正常运行]
|
79
wuyadaxian OP @brant2ai 我也可以直接在 tty 中使用这行 command ,但是 cron 里面不会运行
|
80
brant2ai 195 天前
@wuyadaxian #79 你检查下 crontab 是不是写对的
|
81
wuyadaxian OP |
82
wuyadaxian OP |
83
wuyadaxian OP |
84
lovelylain 195 天前
@wuyadaxian 那就写到脚本里面呗,每分钟执行 1 次脚本,脚本里[[ $(($(date +'%s / 60 % 7 '))) -eq 0 ]] || exit
|
85
wuyadaxian OP @brant2ai 如果你那边服务器可以运行,请告诉我以下你服务器的系统和版本号。我去装一个测试下,看是不是只有 ubuntu 不行。
|
87
yangxiaopeipei 195 天前
执行完 sleep 7*60
|
88
brant2ai 195 天前
@wuyadaxian #83 我也试试,crontab 好像是不太行,我改了几次命令,好像还是执行不了
|
89
director 195 天前
每分钟跑一次,在程序里判断时间点/7 的余数为某个值就执行
|
90
momomirage 195 天前
一周有 7 天
所以用多(但是有限)个 cron 表达式合起来应该可以每 7 分钟一次 |
91
wuyadaxian OP |
92
zzhaolei 195 天前
不会是面试题吧?要么加一层,然后写入上次执行的时间,如果也不能写文件,那就放弃吧,纯 crontab 肯定实现不了
|
93
feedcode 195 天前 2
换个思路
systemd-run --on-boot=30 --on-unit-active=420 bash /path/script.sh Running timer as unit: run-r2f2f454d18944d79af858a4be4f48cd5.timer Will run service as unit: run-r2f2f454d18944d79af858a4be4f48cd5.service 如果测试 ok,把对应的 timer 和 service 从/run/systemd/transient/ move 到/etc/systemd/system 做持久化 |
94
Ipsum 195 天前
最简单就是每分钟运行,然后脚本获取当前时间,分钟能被 7 整除就运行。否则就退出。如果是其他时间 60 能被 n 整除可以用*/n
|
95
dxdydz 195 天前 via iPhone
我想了个双脚本思路,大致内容如下
script_a.sh: #!/bin/bash # 使用 at 命令在 7 分钟后执行脚本 b #run task echo "/path/to/script_b.sh" | at now + 7 minutes script_b.sh: #!/bin/bash # 使用 at 命令在 7 分钟后执行脚本 a #run task echo "/path/to/script_a.sh" | at now + 7 minutes |
96
noyle 195 天前 4
@wuyadaxian
`[[ $(($(date +'%s / 60 % 7 '))) -eq 0 ]] &&` 这句在 cron 里有几个问题: 1 ,`[[`是 bash 扩展,不是命令,所以在 cron 的 shell 环境里报错,改用`[ ... ]`或者`test ...`应该就没问题了。[1] 2 ,字面`%`在 cron 里应该用`\`转义。[2] 所以,下面这条应该可以: `*/1 * * * * root [ $(($(date +'\%s / 60 \% 7 '))) -eq 0 ] && ( echo "CRON RUN" | logger )` [1] https://stackoverflow.com/a/47576482/6681141 [2] https://serverfault.com/questions/274475/escaping-double-quotes-and-percent-signs-in-cron |
97
ZeekChatCom 194 天前 via iPhone
写复杂命令在 cron 里面可以实现,但是这个和套一层 shell 有啥本质区别?无非是把外层的判断写在了 cron 行上面了而已
|
98
james122333 194 天前 via Android
直接写 bash 脚本 cron 本来就是用在规律用途 也比较鸡肋 因为 bash 本身就能实现 cron 的功能
有准确的用法 至于 sleep 为何会不准因为是外部命令 启动要时间 用久会有大误差 这需求有不只一种实现方法 systemd? 垃圾东西就不要用了 |
99
hackerwgf 194 天前
哎,就喜欢这样的 v2
|
100
asche910 194 天前
用脚本吧,sleep ( 7 * 60 ),然后异步执行
|