余晖落尽暮晚霞,黄昏迟暮远山寻
本站
当前位置:网站首页 > 编程知识 > 正文

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

xiyangw 2023-05-14 11:40 14 浏览 0 评论

1、背景

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

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

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

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 restartsudo 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 postfixsudo 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/bashPATH=/sbin:/bin:/usr/sbin:/usr/binMAILTO=rootHOME=/# .---------------- 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>&1bash -c "ls <(ooxx)" > debuglog/a.log 2>&1

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

相关推荐

辞旧迎新,新手使用Containerd时的几点须知

相信大家在2020年岁末都被Kubernetes即将抛弃Docker的消息刷屏了。事实上作为接替Docker运行时的Containerd在早在Kubernetes1.7时就能直接与Kubelet集成使...

分布式日志系统ELK+skywalking分布式链路完整搭建流程

开头在分布式系统中,日志跟踪是一件很令程序员头疼的问题,在遇到生产问题时,如果是多节点需要打开多节点服务器去跟踪问题,如果下游也是多节点且调用多个服务,那就更麻烦,再者,如果没有分布式链路,在生产日志...

Linux用户和用户组管理

1、用户账户概述-AAA介绍AAA指的是Authentication、Authorization、Accounting,即认证、授权和审计。?认证:验证用户是否可以获得权限,是3A的第一步,即验证身份...

linux查看最后N条日志

其实很简单,只需要用到tail这个命令tail-100catalina.out输入以上命令,就能列出catalina.out的最后100行。...

解决linux系统日志时间错误的问题

今天发现一台虚拟机下的系统日志:/var/log/messages,文件时间戳不对,跟正常时间差了12个小时。按网上说的执行了servicersyslogrestart重启syslog服务,还是不...

全程软件测试(六十二):软件测试工作如何运用Linux—读书笔记

从事过软件测试的小伙们就会明白会使用Linux是多么重要的一件事,工作时需要用到,面试时会被问到,简历中需要写到。对于软件测试人员来说,不需要你多么熟练使用Linux所有命令,也不需要你对Linux...

Linux运维之为Nginx添加错误日志(error_log)配置

Nginx错误日志信息介绍配置记录Nginx的错误信息是调试Nginx服务的重要手段,属于核心功能模块(nginx_core_module)的参数,该参数名字为error_log,可以放在不同的虚机主...

Linux使用swatchdog实时监控日志文件的变化

1.前言本教程主要讲解在Linux系统中如何使用swatchdog实时监控日志文件的变化。swatchdog(SimpleWATCHDOG)是一个简单的Perl脚本,用于监视类Unix系统(比如...

syslog服务详解

背景:需求来自于一个客户想将服务器的日志转发到自己的日志服务器上,所以希望我们能提供这个转发的功能,同时还要满足syslog协议。1什么是syslog服务1.1syslog标准协议如下图这里的fa...

linux日志文件的管理、备份及日志服务器的搭建

日志文件存放目录:/var/log[root@xinglog]#cd/var/log[root@xinglog]#lsmessages:系统日志secure:登录日志———————————...

运维之日志管理简介

日志简介在运维过程中,日志是必不可少的东西,通过日志可以快速发现问题所在。日志分类日志分类,对不同的日志进行不同维度的分析。操作系统日志操作系统是基础,应用都是在其之上;操作系统日志的分析,可以反馈出...

Apache Log4j 爆核弹级漏洞,Spring Boot 默认日志框架就能完美躲过

这两天沸沸扬扬的Log4j2漏洞门事件炒得热火朝天:突发!ApacheLog4j2报核弹级漏洞。。赶紧修复!!|Java技术栈|Java|SpringBoot|Spring...

Linux服务器存在大量log日志,如何快速定位错误?

来源:blog.csdn.net/nan1996jiang/articlep/details/109550303针对大量log日志快速定位错误地方tail/head简单命令使用:附加针对大量log日志...

Linux中查看日志文件的正确姿势,求你别tail走天下了!

作为一个后端开发工程师,在Linux中查看查看文件内容是基本操作了。尤其是通常要分析日志文件排查问题,那么我们应该如何正确打开日志文件呢?对于我这种小菜鸡来说,第一反应就是cat,tail,vi(或...

分享几款常用的付费日志系统,献给迷茫的你!

概述在前一篇文章中,我们分享了几款免费的日志服务器。他们各有各的特点,但是大家有不同的需求,有时免费的服务器不能满足大家的需要,下面推荐几款付费的日志服务器。1.Nagios日志服务器Nagio...

取消回复欢迎 发表评论: