遇到个奇怪事儿,在轻量应用服务器上开启定时任务时,有两种方法可以实现,但是其中一种方法会出现 MySQL 报错,而另外一种则可以正常运行。
方法一:
crontab -e
该方法添加定时任务后,MySQL 在执行过程中,会报如下错误:
Traceback (most recent call last):
File "/root/anaconda3/envs/spider/lib/python3.8/site-packages/mysql/connector/connection_cext.py", line 705, in cmd_query
self._cmysql.query(
_mysql_connector.MySQLInterfaceError: Lost connection to MySQL server during query
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/root/anaconda3/envs/spider/lib/python3.8/site-packages/twisted/internet/defer.py", line 1078, in _runCallbacks
current.result = callback( # type: ignore[misc]
File "/root/anaconda3/envs/spider/lib/python3.8/site-packages/scrapy/utils/defer.py", line 340, in f
return deferred_from_coro(coro_f(*coro_args, **coro_kwargs))
File "/root/magazines_spider/magazines_spider/pipelines.py", line 42, in process_item
self.cur.execute("""select id from magazines where title_zh = %s""", (str(item['title_zh']),))
File "/root/anaconda3/envs/spider/lib/python3.8/site-packages/mysql/connector/cursor_cext.py", line 357, in execute
result = self._connection.cmd_query(
File "/root/anaconda3/envs/spider/lib/python3.8/site-packages/mysql/connector/opentelemetry/context_propagation.py", line 97, in wrapper
return method(cnx, *args, **kwargs)
File "/root/anaconda3/envs/spider/lib/python3.8/site-packages/mysql/connector/connection_cext.py", line 713, in cmd_query
raise get_mysql_exception(
mysql.connector.errors.OperationalError: 2013 (HY000): Lost connection to MySQL server during query
方法二:
手写守护进程,定时执行相关任务。
所谓守护进程,就是没有父进程的孤立进程,该进程可以在后台持续运行。在命令行中创建的进程,都属于该终端 tty 的子进程,当前终端关闭后,由该终端派生出的子进程都会随之结束。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
int main() {
pid_t pid;
time_t t;
// 创建子进程,父进程退出
if ((pid = fork()) < 0) {
perror("fork");
exit(-1);
} else if (pid > 0) {
exit(0);
}
// 创建新会话,与原先终端脱离
if (setsid() < 0) {
perror("setsid");
exit(0);
}
// 更改当前工作目录
chdir("/");
// 重设文件权限掩码
if (umask(0) < 0) {
perror("unmask");
exit(0);
}
while(1) {
time_t now = time(NULL);
struct tm tm_now;
localtime_r(&now, &tm_now);
char buff[100];
strftime(buff, sizeof(buff), "%H:%M", &tm_now);
if (!strcmp(buff, "02:25")) {
if ((pid = fork()) < 0) {
perror("fork");
exit(-1);
} else if (pid > 0) {
sleep(100);
} else {
worker();
}
}
sleep(10);
}
return 0;
}
void worker() {
if (execl("/bin/sh", "sh", "/root/magazines_spider/run.sh", NULL) < 0) {
printf("execl error!\n");
}
return ;
}
使用这种方法就不会报错,不知道是什么原因导致的?