用户添加定时任务后如
每月30 号发工资
订单到期未付款恢复
这种是如何做的?
直接在Linux 操作crontab 可以,
但是用户添加一个任务就加到 crontab 怎么实现?
用户添加定时任务后如
每月30 号发工资
订单到期未付款恢复
这种是如何做的?
直接在Linux 操作crontab 可以,
但是用户添加一个任务就加到 crontab 怎么实现?
可以参考 laravel
的 任务调度
。即使不用 laravel
,也可以参考 laravel
的 任务调度
的实现思路, 其实原理很简单:
crontab任务
,每分钟执行一次某个 php
脚本。用 crontab 每分钟执行一遍实现的调度的时间精度只有一分钟,想要更小的精度可以考虑用
swoole
、workerman
、reactphp
之类的库来实现,至于任务执行规则可以参考 linux 自带的crontab
规则,也就是* * * * *
这样的。
又或者直接用现成的 php 任务调度框架。
我引用一下Naist
首先你要会使用crontab,没错,不会用就自己百度了,这里不做回答,可以写一篇博客了。
然后在命令行
crontab -e
了之后
0 0 30 * * php 需要定期执行的php脚本位置
有可能不是crontab,我之前用node.js
写过一个用户可以自己定时的WebSocket,在后台挂起。当用户向这个WebSocket发送请求时,把定时的时间记录到一个缓存文件中(JSON),然后设置node.js
自己的定时器。
如果这个WebSocket服务挂掉了的话,只要重新启动这个后台脚本,脚本会通过缓存的JSON里记录的时间,重新设定计划任务。这里我可以放一些代码,核心的代码被省略,另外加了点注释供参考
'use strict';
// 一些NodeJS包
const WebSocket = require('ws');
const path = require('path');
const crontab = require('node-crontab');
const spawn = require('cross-spawn');
const fsExtra = require('fs-extra');
const objectValues = require('object-values');
// 省略了一些配置
const wss = new WebSocket.Server({port: 8080}); // 创建WebSocket服务
let ScheduleList = {}; // 这个为存储时间的JS对象
let JobList = {}; // 这个为存储定时任务ID的JS对象,如果要取消任务,就通过这个来查找定时任务ID
// 省略了日志方法
// 故障后重启载入任务时间的方法
const loadJobs = () => {
let jobsCache = path.resolve(__dirname, './config/scheduler.jobs');
if(fsExtra.pathExistsSync(jobsCache)) {
ScheduleList = fsExtra.readJsonSync(jobsCache, {throw: false}) || {};
}
};
// 用户传入时间时将任务时间对象ScheduleList重写到文件的方法
const saveJobs = () => {
let jobsCache = path.resolve(__dirname, './config/scheduler.jobs');
fsExtra.outputJsonSync(jobsCache, ScheduleList);
};
// 根据ScheduleList重新创建计划任务的方法
const rerunJobs = () => {
for(let jobScheduleId in ScheduleList) {
let hour = ScheduleList[jobScheduleId].hour || 0;
let minute = ScheduleList[jobScheduleId].minute || 0;
let jobId = crontab.scheduleJob(`${minute} ${hour} * * *`, () => {
// 此处省略了任务创建的具体操作,用的cross-spawn包
});
JobList[id] = jobId;
}
};
loadJobs(); // 启动时载入时间
rerunJobs(); // 根据时间重新创建计划任务
wss.on('connection', ws => {
ws.on('message', message => {
// 省略了传入数据的解析
// 如果任务存在,先删除任务
if(JobList[id]) {
crontab.cancelJob(JobList[id]);
delete ScheduleList[id];
delete JobList[id];
}
// 重新添加任务
let jobId = crontab.scheduleJob(`${minute} ${hour} * * *`, () => {
// 同rerunJobs()里的创建操作,省略细节
});
ScheduleList[id] = {id: id, hour: hour, minute: minute};
JobList[id] = jobId;
saveJobs(); // 保存任务计划时间
ws.send(JSON.stringify(response(null, {message: '应用成功'}))); // 给请求者反馈
});
});
7 回答5.3k 阅读
4 回答4k 阅读
2 回答5.9k 阅读✓ 已解决
1 回答4k 阅读✓ 已解决
3 回答1.8k 阅读✓ 已解决
2 回答2.2k 阅读✓ 已解决
2 回答2.5k 阅读✓ 已解决
有些个回答的方法并不太好,不用为好,小心为妙。
1.如果不一定非要php解决,那么采用linux的crontab
2.如果要用php解决,那么使用workerman( 这么简单一个需求,我就不让你用swoole了,太折腾 )
3.如果要用php解决,而且非要自己撸,请扩展如下简单粗暴的代码:
不用看了,我的回答的最全面最好使的