阿毛
It's me !
想你所想
记录一次Mac上crontab未成功执行问题的排查过程!

记录一次排查Mac上编写的crontab任务无法成功执行的过程!

问题

当前登录用户下,crontab -e编写的任务竟然没有成功执行(因为逻辑中加入了,任务只要运行,就会输出日志,显然没有对应输出)

排查

1、跟踪crontab自身日志

crontab日志默认输出“/var/log/cron.log”中。
发现没有最新cron输出,怀疑crontab任务并没有运行?

2、检查crontab任务是否正常运行

如同Ubuntu中的systemctl一样,Mac也提供了服务管理的工具launchctl,和systemctl一样都是作为系统超级进程,管理其他服务。这里需要知道,launchctl是通过plist文件进行服务管理的,每个plist都是一个服务。在整个OS中有多个目录分类存放不同的plist文件,不同目录对应不同的服务类型。如下:

  • ~/Library/LaunchAgents 由用户自己定义的服务项
  • /Library/LaunchAgents 由管理员为用户定义的服务项
  • /System/Library/LaunchAgents 由Mac OS 为用户定义的服务项
  • /Library/LaunchDaemons 由管理员定义的守护进程服务项
  • /System/Library/LaunchDaemons 由Mac OS 定义的守护进程服务项

“/System/Library” 、“ /Library”、“~/Library”目录的区别在于 /System/Library目录是存放Apple自己开发的软件。 /Library目录是系统管理员存放的第三方软件。 ~/Library/是用户自己存放的第三方软件。 而LaunchDaemons和LaunchAgents的区别在于 LaunchDaemons是用户未登陆前就启动的服务(守护进程)。 LaunchAgents是用户登陆后启动的服务(守护进程)。所以一般我们自定义的plist一般写在“~/Library/LaunchAgents”下。

关于launchctl的内容,这里就不过多阐述了,可以自行了解。

有了launchctl的基本了解,接下来排查crontab服务的运行。

首先,launchctl list | grep 'cron'查看是否存在crontab服务,应该没有,再sudo launchctl list | grep 'cron',这是出现crontab服务

 humh@MacBook-Pro ~ launchctl list | grep 'cron'
 ✘ humh@MacBook-Pro ~ sudo launchctl list | grep 'cron'
201	0	com.vix.cron

其中第一列是pid;第二列是服务状态,0代表正常;第三列是服务plist名。之所以sudo查看有,是因为crontab默认Mac系统启动服务。

那么问题来了,既然服务正常,为什么crontab看起来没有执行,于是看了下plist,locate com.vix.cron或全局查找plist文件位置。

 humh@MacBook-Pro  ~  locate com.vix.cron
/System/Library/LaunchDaemons/com.vix.cron.plist

plist大致内容如下

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
	"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>Label</key>
	<string>com.vix.cron</string>
	<key>ProgramArguments</key>
	<array>
		<string>/usr/sbin/cron</string>
	</array>
	<key>KeepAlive</key>
	<dict>
		<key>PathState</key>
		<dict>
			<key>/etc/crontab</key>
			<true/>
		</dict>
	</dict>
	<key>QueueDirectories</key>
	<array>
		<string>/usr/lib/cron/tabs</string>
	</array>
	<key>EnableTransactions</key>
	<true/>
</dict>
</plist>

逐行看了下,发现“/etc/crontab”竟然不存在!!!这就是导致crontab没有真正运行的原因,KeepAlive的PathState这个配置大概意思就是,通过判断配置项文件是否存在,来服务保活。于是,按照下面这个模板创建了“/etc/crontab”

SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root

# For details see man 4 crontabs

# 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

此时,crontab服务正常!(如果未自动执行,尝试重启Mac)可是,编写cron任务还是不正常,这时再次排查cron错误日志

3、crontab服务正常后,再次排查cron相关日志

查看“/var/log/cron.log”,并没有发现什么有效信息。

https://file.blog.humh.cn/2021/05/d2b5ca33bd970f64a6301fa75ae2eb22.png

因为cron如果执行存在问题,默认会通过MTA服务给系统管理员发邮件,这里我并没有配置什么邮箱,可以直接查看“/var/mail/humh”,其中humh是我当前登录用户,这里记录了需要发送邮件的内容。果然,原来是我cron任务写的有问题!关键信息如下:

https://file.blog.humh.cn/2021/05/d2b5ca33bd970f64a6301fa75ae2eb22-1.png

我的cron任务是想着将标准输出和错误输出都追加到特定日志中,所以直接用了“&>>”。但我不知道“&>>”这种方式,是bash 3.6.5及之后版本才支持的特性

查看我Mac的bash版本

 humh@MacBook-Pro ~ bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17)
Copyright (C) 2007 Free Software Foundation, Inc.

显然版本不支持,于是改回旧方式,正常!!

* * * * * cd /Users/humh/cron_job_sh && ./keep_vpn.sh >> /Users/humh/cron_job_sh/keep_vpn.log 2>&1

至此,此次排查结束,问题解决。。。


本文参考

首页      code      记录一次Mac上crontab未成功执行问题的排查过程!

发表评论

textsms
account_circle
email

想你所想

记录一次Mac上crontab未成功执行问题的排查过程!
记录一次排查Mac上编写的crontab任务无法成功执行的过程! 问题 当前登录用户下,crontab -e编写的任务竟然没有成功执行(因为逻辑中加入了,任务只要运行,就会输出日志,显然没有…
扫描二维码继续阅读
2021-05-20