一、crontab基础
1. crontab操作
//列出全部定时任务
crontab -l
//编辑定时任务
crontab -e
2. crontab格式
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executee
第一列的 * 表示:分
第二列的 * 表示:时
第三列的 * 表示:日
第四列的 * 表示:月
第五列的 * 表示:周
3. 定期执行例子
# 每小时执行一次test.py文件
0 */1 * * * python3 /test/test.py
# 每70分钟执行一次test.py文件
*/70 * * * * python3 /test/test.py
# 每天21点15分执行一次test.py文件
15 21 * * * python3 /test/test.py
# 每月1号和10号的21点15分执行一次test.py文件
15 21 1,10 * * python3 /test/test.py
二、批量删除进程
参考:https://www.cnblogs.com/suhai/p/16585787.html
ps -ef|grep xxx|grep -v grep|awk '{print $2}'
关于grep
grep(global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。
第一步:
ps -ef|grep xxx
:查看全格式的所有进程
参数含义
- e:显示所有进程
- f:全格式
- h:不显示标题
- l:长格式
- w:宽输出
- a:显示终端上的所有进程,包括其他用户的进程
- r:只显示正在运行的进程
- x:显示没有控制终端的进程
e.g.ps -ef|grep java
:通过管道的方式,将ps
命令查询出来的进程信息内容筛选出与java进程相关的数据
root 3256 1 0 Aug11 ? 00:17:19 java -jar java_test.jar
root 6435 6395 0 08:38 pts/1 00:00:00 grep --color=auto java_test.jar
第二步:
grep -v grep
:
上一步查询到的进程信息中,除了需要的java_test.jar
进程外,还包括了grep --color=auto
进程信息
- -v: 反转查找,用于排除掉
grep
进程的信息数据,即grep --color=auto
第三步:
awk '{print $2}'
awk是行处理器:相比较屏幕处理的优点,在处理庞大文件时不会出现内存溢出或是处理缓慢的问题,通常用来格式化文本信息
awk处理过程依次对每一行进行处理,然后输出
print & $0 :awk打印指定内容的主要命令
在第一步中,我们查询出来了java进程的信息,此时需要获取到这条进程信息的PID
,进而对其执行删除操作
我们就可以使用awk
命令将自己需要的某一列数据单独提取出来,示例如下
ps -ef|grep java_test.jar|grep -v grep|awk '{print $2}'
3256
其中,$2
代表提取进程信息中第二列的值,而我们使用ps
命令查询出的进程信息中的第二列对应的正好就是进程的PID
(注意:$0
表示获取整个当前行)
可以看到,通过awk '{print $2}'
命令,成功拿到了java_test.jar
的PID:3256
e.g.:
# 查询进程是否在运行
is_exist($APP_NAME) {
pid=`ps -ef|grep $APP_NAME|grep -v grep|awk '{print $2}'`
# 如果不存在返回1,存在返回0
if [ -z "${pid}" ]; then
return 1
else
return 0
fi
}
三、shell脚本执行python
参考:https://zhuanlan.zhihu.com/p/363531715
假如要执行一个python文件,常规步骤为:
- 打开终端
- 激活虚拟环境(使用anoconda建立的虚拟环境,环境名称是py37):conda activate py37
- 切换路径:cd /usr/test/
- 执行python文件:python main.py
为了更便捷地操作,对步骤2~4进行封装,新建一个shell脚本文件,名为start_py.sh,文件具体内容如下:
conda activate py37
cd /usr/test/
python main.py
保存文件,退出。然后在终端上执行脚本即可:
source start_py.sh
tips
执行shell脚本文件一定是
source start_py.sh
不能是
bash start_py.sh
也不能是
sh start_py.sh
还不能是
./start_py.sh
其区别在于,source启动的shell脚本,是在父进程中继续运行的。而后面的3个启动方法,是新建子进程运行的,那样切换路径和激活虚拟环境就没有意义了。
四、遇到过的问题
1. 无法激活conda环境
先说方法:
* * * * * source ~/miniconda3/bin/activate mini_bot && bash restart.sh
现在conda在crontab上读取会报错,告诉你需要conda init,所以要用source
其次crontab里面需要使用绝对路径(activate
是个文件,所以也需要绝对路径)。查看activate
路径的方法:
which activate
也可以使用如下方法,先进入activate目录,再激活环境:
* * * * * cd ~/miniconda3/bin && source activate name && bash /root/restart.sh
2. nohup无法执行
最初采用 nohup nb run &
的方式执行,发现nohup.out
中没有内容,怀疑没有成功以nohup方式运行;奇怪的是:直接sh restart.sh
可以将日志输出到nohup.out
。
于是采用第二种完整方式:nohup nb run >> nohup.out 2>&1 &
,最终成功。
#!/bin/bash
## stop
ps -ef|grep "nb run"|grep python|awk '{print $2}'|xargs kill -15
## restart
# conda activate mini_bot -- 已在crontab里激活
cd /root/install/mini_jx3_bot/
# nohup nb run & -- 原语句,无法运行
nohup nb run >> nohup.out 2>&1 &
>>
: 追加式写入
>
: 覆盖式写入
3. bash权限
问题:bash: ./restart.sh 权限不够
解决方法:
chmod +x /root/restart.sh
# 最好使用绝对路径
4. pam_unix(cron:session): session closed for user root
此前一直无法成功执行,使用命令service cron status
时发现有如上错误。
参考 https://blog.csdn.net/FuJinlong94/article/details/120428955
解决方法:
- 进入/etc/pam.d目录
- 打开文件 common-session-noninteractive
- 查找 session required pam_unix.so 内容(一般在最后)
- 在这一行上方添加:
session [success=1 default=ignore] pam_succeed_if.so service in cron quiet use_uid
- 保存并退出
- 重启crond服务(Ubuntu为cron):
service crond restart
5. shell脚本执行方式
注意文件头和执行方式
#!bin/sh
对应sh xxx.sh
#!bin/bash
对应bash xxx.sh
6. crontab -e无用
解决方法:修改/etc/crontab
vim /etc/crontab
SHELL=/bin/bash ## 注意和cron命令中的执行方式对应
PATH=......
.......
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed
0 * * * * root cd /home/ubuntu/miniconda3/bin && source activate mini_bot && bash /root/restart.sh
## 每个小时0分的时候以root身份执行命令