文档章节

迷之 crontab 异常:不运行、不报错、无日志

大数据之路
 大数据之路
发布于 04/02 00:51
字数 1450
阅读 2365
收藏 10
点赞 1
评论 1

1、背景

前几天新同学入职,一不小心将跳板机上的 crontab 清空了,导致凌晨一大批任务异常,同事问了运维同学也没有备份,这一百多个任务要是恢复起来可不是件容易的事儿。还好我去年某天开始做了定时备份,每分钟一次 backup 到本地磁盘,最后很容易的将 crontab 给恢复了。

这件事情过后我也在想,一台跳板机整个部门都共用一个账号, Linux 水平和安全意识又参差不齐,其实很难避免以后还会误操作,比如一下子将 home 目录全干掉。所以我想 backup 最好不要保存在本地,于是想一条命令将其备份到 hadoop 集群上去。

2、问题

当时觉得这个问题很简单,于是随手写了一条类似这样的命令:

*/1 * * * *  /bin/cat <(seq 10) >> /root/a.log 2>&1

本地测试了没问题,但是 crontab 怎么都不成功,也看不到错误日志,a.log 一直是空的。

这个我就比较好奇了,按理说 a.log 应该是能拿到所有的标准输出和标准错误的,究竟什么原因导致 crontab 既不执行又不报错呢?

3、分析

debug 终极大法还是得看日志,本 case 最让人疑惑的在于没有日志,如果能找到日志所有的迷雾应该都能烟消云散。

于是,我尝试看看 /var/log 下有没有 crontab 的执行日志,看了下服务器居然没开启 cron.log,由于非管理员没权限修改任何配置或设置,于是我在本地 WSL 里用 Ubuntu 把问题复现了下。

3.1 开启 cron.log

sudo vim /etc/rsyslog.d/50-default.conf
cron.*  /var/log/cron.log #将cron前面的注释符去掉
#重启rsyslog
#sudo /etc/init.d/rsyslog restart
sudo service rsyslog restart
sudo service cron restart

虽然能看到 crontab 执行日志了,但全都是一些没意义的日志或 info 提示:

Mar 31 20:58:20 Surface-Pro5 crontab[223]: (root) BEGIN EDIT (root)
Mar 31 20:58:53 Surface-Pro5 crontab[223]: (root) REPLACE (root)
Mar 31 20:58:53 Surface-Pro5 crontab[223]: (root) END EDIT (root)
...
Mar 31 21:13:01 Surface-Pro5 CRON[451]: (CRON) info (No MTA installed, discarding output)
Mar 31 21:14:01 Surface-Pro5 CRON[471]: (CRON) info (No MTA installed, discarding output)
...

仔细观察日志发现貌似在提示我们 MTA 没装,crontab 输出被丢弃了。同时查看 sudo tail -f /var/mail/<user> 发现爆出大量 warning: unable to look up public/pickup: No such file or directory! 的警告。

3.2 安装 postfix

由于 crontab 通知机制是将错误会以邮件形式发给所属登录账号或者系统管理员,如果没有安装邮件管理服务,那么这部分信息会被系统丢弃。那咱们安装 postfix 即可:

sudo apt-get install postfix
sudo service postfix start

再次查看日志发现了报错日志:

  1 From root@Surface-Pro5.localdomain  Sat Mar 31 21:33:38 2018
  2 Return-Path: <root@Surface-Pro5.localdomain>
  3 X-Original-To: root
  4 Delivered-To: root@Surface-Pro5.localdomain
  5 Received: by Surface-Pro5.localdomain (Postfix, from userid 0)
  6     id CCE42300000000E229; Sat, 31 Mar 2018 21:25:02 +0800 (DST)
  7 From: root@Surface-Pro5.localdomain (Cron Daemon)
  8 To: root@Surface-Pro5.localdomain
  9 Subject: Cron <root@Surface-Pro5> /bin/ls <(seq 10) >> /root/a.log 2>&1
 10 MIME-Version: 1.0
 11 Content-Type: text/plain; charset=UTF-8
 12 Content-Transfer-Encoding: 8bit
 13 X-Cron-Env: <SHELL=/bin/sh>
 14 X-Cron-Env: <HOME=/root>
 15 X-Cron-Env: <PATH=/usr/bin:/bin>
 16 X-Cron-Env: <LOGNAME=root>
 17 Message-Id: <20180331133337.CCE42300000000E229@Surface-Pro5.localdomain>
 18 Date: Sat, 31 Mar 2018 21:25:02 +0800 (DST)
 19 
 20 /bin/sh: 1: Syntax error: "(" unexpected

3.3 如何修复

看到邮件里的错误提示咱们立马就能明白 crontab 之所以无法执行,是因为 crontab 环境变量默认加载的是 sh,而非 bash,不支持进程代换这种语法,咱们有两种办法避免:

3.3.1 crontab 开头指定 shell 类型

完整的 crontab 格式如下:

SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/
# .---------------- 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 
# |  |  |  |  |
# *  *  *  *  *  command to be executed

也就是说,咱们可以在 crontab 文件的开头指定 shell 类型这样就不会有问题了。

3.3.2 封装成脚本

其实不建议在 crontab 里执行复杂逻辑,最好封装成脚本,这样好控制,比如:

*/1 * * * *  bash a.sh >> /root/a.log 2>&1

3.4 重定向无法获取错误的原因

虽然咱们根据错误日志知道怎样修改让命令正常执行,但是我们并未回答文章开头的疑问:究竟为何 2>&1 无法重定向拿到所有的标准输出和标准错误?有点违反常理了。这个还和 shell 解释器类型无关,比如下面这条命令,在 bash 下也是只能拿到标准输出,无法拿到标准错误:

ls <(ooxx) > debuglog/a.log 2>&1

这个问题的深层次原因得追溯到 shell 的一个概念:子进程

其实上图中的命令这样改也行:

ls <(ooxx >> debuglog/b.log 2>&1) >> debuglog/a.log 2>&1

因为 <() 是在子进程进行的,> debuglog/a.log 2>&1 只能拿到当前进程的标准输出与标准错误。

另外需要注意的是通过()或管道fork出来的子进程,继承了父进程的所有环境变量,和平时bash xxx.sh或者./xxx.sh起的不同的, 而$$是一起继承的,但$BASHPID继承后重新赋值了,这和新开个bash的方式是不同的。

除了上面的写法,如果要深究茴字还有几种写法,那么还有如下两种写法:

bash a.sh > debuglog/a.log 2>&1
bash -c "ls <(ooxx)" > debuglog/a.log 2>&1

至此,从文章开头的问题,咱们从如何让日志输出以及代码如何改写,到最后的 root cause 都分析了一遍,希望能对大家有所启发和参考。

【全文完】

© 著作权归作者所有

共有 人打赏支持
大数据之路
粉丝 1484
博文 516
码字总数 343984
作品 0
武汉
架构师
加载中

评论(1)

花样撸码
踩过此坑:stuck_out_tongue:
Linux下日志文件监控系统Logwatch的使用记录

在维护Linux服务器时,经常需要查看系统中各种服务的日志,以检查服务器的运行状态,如登陆历史、邮件、软件安装等日志。作为运维人员,我们一个个去检查会十分不方便;且大多时候,这会是一...

吞吞吐吐的
2017/08/10
0
0
Redis Failed opening the RDB file crontab for saving Permission denied

Redis正常运行一段时间后,会在日志文件中报如下异常,导致Redis中内容被清空: Failed opening the RDB file crontab (in server root dir /etc) for saving: Permission denied 问题是,我...

李毅超
2017/12/11
19
1
一次crontab任务报command not found错误

用过*nix 系统的同学对crontab一定不陌生,最近系统重装之后一直被command not found这个错误给困扰,本来打算work around,通过绝对路径解决,无奈天生比较懒惰,不想一个一个的去改脚本,于...

bug0day
2016/08/28
404
4
crontab系统使用雷区(为什么cron任务没运行)

写好的程序,手动执行没问题,上crontab就报错 Crontab任务的执行环境与手动执行时的执行环境不同。 手动执行时,任务的执行环境为当前用户或指定用户的执行环境,典型的执行环境是环境变量,...

panzhc
2014/01/08
0
0
OGG维护优化脚本(二十四)-OGG状态监控系统--后台脚本

这个简易监控系统具体是由html实现的 后台没有数据库,只有从各台机器收集并上传过来的html文件 通过定时shell脚本整理并分类到各个目录,然后通过apache被网页调用 具体更新频率取决于各数据...

netsman1030
07/03
0
0
Linux定时任务Crontab

1.安装cron vixie-cron软件包是cron的主程序; crontabs软件包是用来安装、卸装、或列举用来驱动 cron 守护进程的表格的程序 2.设置为开机自启 查看crontab服务是否已设置为开机启动,执行命...

_周小董
05/22
0
0
crontab执行身份的小坑

有个ubuntu服务器,跑着apache, PHP7, Laravel,supervisor。 apache和supervisor都是www-data用户。平时管理员ssh登上去用的都是devuser用户。 今天发现Laravel日志异常了,连着几天都是只...

zgldh
2017/09/26
40
0
CentOS定时同步系统时间

使用Linux.VPS第二天,发现系统时间不正确,手动修改或者同步正确一次后,运行半天发觉时间又快了几分钟,反正是运行得越久就越快,难道VPS穿越啦? 和VPS管理员沟通无果,再上网搜索一番后,...

闪电
2015/09/10
690
0
基于XtraBackup的备份有效性检查脚本

生产环境的MySQL是通过crontab的方式,定时调度热备脚本备份数据。目前是通过XtraBackup软件实现热备。关于热备脚本方面,请查看我原先的博客《使用shell实现mysql自动全备、增备&日志备份》...

Jenkin_lin
06/26
0
0
webcron

一个定时任务管理器,基于Go语言和beego框架开发。用于统一管理项目中的定时任务,提供可视化配置界面、执行日志记录、邮件通知等功能,无需依赖*unix下的crontab服务。 项目背景 开发此项目...

_周小董
02/03
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

ndarray花式索引

花式索引 花式索引(Fancy indexing)是一个NumPy术语,它指的是利用整数数组进行索引。假设我们有一个8×4数组: In [117]: arr = np.empty((8, 4))In [118]: for i in range(8): ....

火力全開
5分钟前
0
0
Mybaties报错Error querying database

Mybaties我们经常用到动态SQL,如下我们利用动态去做判断,这样写当然没问题,但是当我们不是去判断orgCode(本文中orgCode一直为String类型)是否为空而是判断orgCode是否是一个值的时候该怎...

王子城
7分钟前
0
0
Android 调用手机自带的下载器下载

亲测有用,原文下载地址: 原文地址:https://blog.csdn.net/weixin_36554045/article/details/79108796 下面是原文: 创建一个广播类 public class UpdataBroadcastReceiver extends Broad...

她叫我小渝
10分钟前
0
0
idea工具debug断点红色变成灰色,断点无效

来自:idea工具debug断点红色变成灰色 没事别瞎点,禁用了断点当然不走了 看这篇博客底下的评论笑死我了 真香警告!

不开心的时候不要学习
12分钟前
0
0
知识点总结

jq如何拿到data-info的自定义属性 1.1 原生可以获取到所有属性el.attrbutes 1.2 jq的$(el).attr('属性名称') 继承的几种方式,原型链 2.1 扩展原型对象实现继承 2.2 替换原型对象实现继承 2....

litCabbage
15分钟前
0
0
python语言规范

http://zh-google-styleguide.readthedocs.io/en/latest/google-python-styleguide/python_style_rules/...

ghou-靠墙哭
19分钟前
0
0
istio 监控,遥测 (理论)

Istio提供了一种灵活的模型来强制执行授权策略并收集网格中服务的遥测。 基础架构后端旨在提供用于构建服务的支持功能。它们包括诸如访问控制系统,遥测捕获系统,配额执行系统,计费系统等之...

xiaomin0322
21分钟前
0
0
阿里资深专家面试问题收集

corejava hashcode相等的两个对象一定相等吗?equals呢?反过来相等吗? 介绍一下集合框架? hashtable,hashmap底层实现是什么?hashtable和concurrenthashmap底层实现的区别? hashmap和treemap的...

undefine
22分钟前
8
0
alpine安装软件指定安装源

linux-alpine安装软件指定安装源 一、永久修改apk下载源地址 vi etc/apk/repositories 替换成阿里源 http://mirrors.aliyun.com/alpine/v3.8/main/http://mirrors.aliyun.com/alpine/v3...

我心中有猛狗
23分钟前
0
0
Centos7通过yum安装nginx

添加源地址(直接install可能不是最新版本的) sudo rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm 安装 sudo yum install -y ng......

iplusx
25分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部