有一次新同事入职,一不小心将跳板机上的 crontab 清空了,导致凌晨一大批任务异常,同事问了运维同学也没有备份,这一百多个任务要是恢复起来可不是件容易的事儿。

还好我去年某天开始做了定时备份,每分钟一次 backup 到本地磁盘,最后很容易的将 crontab 给恢复了。

这件事情过后我也在想,一台跳板机整个部门都共用一个账号, Linux 水平和安全意识又参差不齐,其实很难避免以后还会误操作,比如一下子将 home 目录全干掉。

所以我想 backup 最好不要保存在本地,于是想一条命令将其备份到 hadoop 集群上去。

1、问题

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

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

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

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

2、分析

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

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

2.1 开启 cron.log

sudo vim /etc/rsyslog.d/50-default.confcron.*  /var/log/cron.log #将cron前面的注释符去掉#重启rsyslog#sudo /etc/init.d/rsyslog restartsudo service rsyslog restartsudo 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! 的警告。

2.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

2.3 如何修复

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

2.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 类型这样就不会有问题了。

2.3.2 封装成脚本

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

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

2.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 都分析了一遍,希望能对大家有所启发和参考。

The End

OK,今天的内容就到这里,如果觉得内容对你有所帮助,欢迎点赞转发。
如果觉得不错,希望能动动手指转发给你身边的朋友们。

看不到日志_迷之 crontab 异常:不运行、不报错、无日志?相关推荐

  1. 【Android NDK 开发】NDK C/C++ 代码崩溃调试 - Tombstone 报错信息日志文件分析 ( 获取 tombstone_0X 崩溃日志信息 )

    文章目录 一.崩溃信息描述 二.手机命令行操作 三.电脑命令行操作 四.Tombstone 内容 Tombstone 报错信息日志文件被保存在了 /data/tombstones/ 目录下 , 先 R ...

  2. 【Android NDK 开发】NDK C/C++ 代码崩溃调试 - Tombstone 报错信息日志文件分析 ( 使用 addr2line 命令行工具查找动态库中的报错代码位置 )

    文章目录 一.从 Tombstone 报错日志中查找报错动态库 二.addr2line 命令行工具使用 64 位动态库使用的 aarch64-linux-android-addr2line.exe 工 ...

  3. jstack 脚本 自动日志_运维老司机又翻车, 居然没用过日志切割Logrotate

    运维老司机又翻车, 居然没用过日志切割Logrotate 作为一个运维老司机, 这次又翻车了.只能说明一个原因, 就是菜, 所有才要多学习. 说起日志切割, 自己可以说是溜的一批.基本的套路就是在cr ...

  4. mysql把data移走后报错_【mysql案例】Failedtoopenlog--datadir物理迁移报错

    1.1.1.mysql5.6.14的datadir迁移时遇到报错 [环境描述] 在机器A上安装了perconamysql 5.6.14,数据库停启正常,datadir路径为pathA,并且已经做了应用 ...

  5. 华硕飞行堡垒8intel WiFi6 AX201 160mhz网络适配器报错问题解决日志

    硬件信息: 问题描述: 有时开机就检测不到网络,有时进系统有网,过一会断网且找不到无线网.进管理界面可见网络适配器冒黄色感叹号.报错代码为10或43 解决日志: (我解决的步骤) 最开始就想到是网卡驱 ...

  6. python graphics画圆_求高手解答·· graphics画圆出现报错!

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 错误报告如下: Exception in thread Thread-1: Traceback (most recent call last): File ...

  7. mysql floor报错_【学习笔记】MYSQL的floor报错原理分析总结

    网上关于floor报错的文章很多,但都是利用语句,介绍原理的文章大多一笔带过,不过我终于找到一篇像样的原理文章,于是参考着来理解原理,参考的这个链接说的很详细了,但我仍然还有些不明白的地方,所以就研究 ...

  8. python字符串拼接数字_解决Python中字符串和数字拼接报错的方法

    解决Python中字符串和数字拼接报错的方法 前言 众所周知Python不像JS或者PHP这种弱类型语言里在字符串连接时会自动转换类型,如果直接将字符串和数字拼接会直接报错. 如以下的代码: # co ...

  9. idea本地跑如何看gc日志_不可思议,竟然还有人不会查看GC垃圾回收日志?

    日志的重要性,不需要过多强调了.通过日志,我们可以发现程序可能有内存(泄露)问题.本文从案例出发,具体介绍这些日志信息,以期帮助大家更好地了解垃圾回收的运行情况. 还是先上图,看看本文的主要内容: 我 ...

  10. python如何写日志_【Python】教你如何在python中添加日志

    背景 起因是这次的项目用thrift来连接算法(python)和业务逻辑(java),因此有必要在python中添加日志来记录传入的参数.这样,当算法端没有正确响应时,就能方便地排查原因. 简易版实现 ...

最新文章

  1. 把ListT转换为DataTable
  2. 放弃MyBatis!我选择 JDBCTemplate!
  3. 响应式 媒体查询 盒模型
  4. 细数网站成功赢利须具备的四大核心要素
  5. 【C/C++】等分或指定行数把txt文档拆分成多份
  6. QT的QSignalBlocker类的使用
  7. NOTIFYICONDATA结构
  8. JavaFX中的塔防(4)
  9. android开发之多线程实现方法概述
  10. 【转载】6种.net分布式缓存解决方案
  11. python将数值进行关联_小疯谈python:(三)数据类型之数值类型
  12. 二十二、Oracle学习笔记:Oracle异常
  13. html静态页面留言板,html静态留言板
  14. 如何设置微信公众号多条被关注自动回复个性语
  15. 【人工智能】图灵测试
  16. 新浪微博相册图片外链限制,图床不显示解决方法总结!
  17. Android流畅度总结
  18. 用python爬小说_今天分享一个用Python来爬取小说的小脚本!(附源码)
  19. 全国青少年科技创新大赛全国青少年信息学奥林匹克系列比赛(大赛系列第12期)
  20. redis分布式事务锁

热门文章

  1. PostgreSQL创建数据库用户
  2. Linux ELF文件学习(1)
  3. 数据包接收系列 — 上半部实现(网卡驱动)
  4. Java大数类自我需要掌握的
  5. 使用pyinstaller讲python文件打包成exe文件运行时,弹出命令行界面
  6. 高翔视觉SLAM十四讲:第三讲中plotTrajectory.cpp怎么运行
  7. C#网络编程----文件流
  8. linux mint 8812ac网卡,kali虚拟机连接无线网卡comfast cf-812AC(Realtek 8812BU芯片)(不支持wlan0mon)...
  9. javascript代码_认识 JavaScript 可执行代码
  10. mysql passwor authen_Navicat连接虚拟机的MySQL时 提示“Password authentication failed”