Mac创建定时任务

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: Mac创建定时任务

Mac 有两种方式可以添加定时任务:


  • crontab 命令
  • launchctl 定时任务


crontab 命令


通过crontab 命令,我们可以在固定的间隔时间执行指定的系统指令或 shell script脚本。时间间隔的单位可以是分钟、小时、日、月、周及以上的任意组合。这个命令非常适合周期性的日志分析或数据备份等工作。


命令格式

crontab [-u user] file
crontab [-u user] [ -e | -l | -r ]
  • -u user:用来设定某个用户的crontab服务;
  • file:file是命令文件的名字,表示将file做为crontab的任务列表文件并载入crontab。如果在命令行中没有指定这个文件,crontab命令将接受标准输入(键盘)上键入的命令,并将它们载入crontab。
  • -e:编辑某个用户的crontab文件内容。如果不指定用户,则表示编辑当前用户的crontab文件。
  • -l:显示某个用户的crontab文件内容,如果不指定用户,则表示显示当前用户的crontab文件内容。
  • -r:从/var/spool/cron目录中删除某个用户的crontab文件,如果不指定用户,则默认删除当前用户的crontab文件。
  • -i:在删除用户的crontab文件时给确认提示。


crontab 文件格式


分 时 日 月 星期 要运行的命令


  • 第1列分钟1~59
  • 第2列小时1~23(0表示子夜)
  • 第3列日1~31
  • 第4列月1~12
  • 第5列星期0~7(0和7表示星期天)
  • 第6列要运行的命令


备份/恢复 crontab


可以定时备份 crontab 以防误删操作


# 备份
crontab -l > $HOME/.mycron
# 恢复
crontab $HOME/.mycron

定时实例

# 每1分钟执行一次myCommand
* * * * * myCommand
# 每小时的第3和第15分钟执行
3,15 * * * * myCommand
# 在上午8点到11点的第3和第15分钟执行
3,15 8-11 * * * myCommand
# 每隔两天的上午8点到11点的第3和第15分钟执行
3,15 8-11 */2  *  * myCommand
# 每周一上午8点到11点的第3和第15分钟执行
3,15 8-11 * * 1 myCommand
# 晚上11点到早上7点之间,每隔一小时重启smb
* 23-7/1 * * * /etc/init.d/smb restart

注意清理系统用户的邮件日志

每条任务调度执行完毕,系统都会将任务输出信息通过电子邮件的形式发送给当前系统用户,这样日积月累,日志信息会非常大,可能会影响系统的正常运行,因此,将每条任务进行重定向处理非常重要。 例如,可以在crontab文件中设置如下形式,忽略日志输出:


0 */3 * * * /usr/local/apache2/apachectl restart >/dev/null 2>&1

launchctl 定时任务


下面将手把手教你在mac上创建定时任务。(任务目标:每天晚上十点定时执行/Users/demo/helloworld.py的python程序)


1. 创建run.sh脚本

进入 helloworld.py程序所在目录

cd /User/demo

创建run.sh脚本

vi run.sh

添加执行helloworld.py的命令


#!/bin/sh
# 记录一下开始时间
echo `date` >> /Users/demo/log &&
# 进入helloworld.py程序所在目录
cd /Users/demo &&
# 执行python脚本(注意前面要指定python运行环境/usr/bin/python,根据自己的情况改变)
/usr/bin/python helloworld.py
# 运行完成
echo 'finish' >> /Users/demo/log
:wq保存退出


注意,脚本要改成可执行的权限

chmod 777 run.sh


2. 编写plist文件

launchctl 将根据plist文件的信息来启动任务。

plist脚本一般存放在以下目录:


/Library/LaunchDaemons -->只要系统启动了,哪怕用户不登陆系统也会被执行


/Library/LaunchAgents -->当用户登陆系统后才会被执行


更多的plist存放目录:


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

进入~/Library/LaunchAgents,创建一个plist文件com.demo.plist



<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <!-- Label唯一的标识 -->
  <key>Label</key>
  <string>com.demo.plist</string>
  <!-- 指定要运行的脚本 -->
  <key>ProgramArguments</key>
  <array>
    <string>/Users/demo/run.sh</string>
  </array>
  <!-- 指定要运行的时间 -->
  <key>StartCalendarInterval</key>
  <dict>
        <key>Minute</key>
        <integer>00</integer>
        <key>Hour</key>
        <integer>22</integer>
  </dict>
<!-- 标准输出文件 -->
<key>StandardOutPath</key>
<string>/Users/demo/run.log</string>
<!-- 标准错误输出文件,错误日志 -->
<key>StandardErrorPath</key>
<string>/Users/demo/run.err</string>
</dict>
</plist>

launchctl 通过配置文件指定执行周期和任务,不同于 crontab,launchctl 的最小时间间隔是 1s。


plist 文件存放路径为/Library/LaunchAgents或/Library/LaunchDaemons,前者仅当用户登陆后才被执行,后者只要系统启动就会被执行。


支持两种方式配置执行时间:


  • StartInterval: 指定脚本每间隔多长时间(单位:秒)执行一次;

  • StartCalendarInterval: 可以指定脚本在多少分钟、小时、天、星期几、月时间上执行,类似如crontab的中的设置,包含下面的 key:
Minute <integer>
The minute on which this job will be run.
Hour <integer>
The hour on which this job will be run.
Day <integer>
The day on which this job will be run.
Weekday <integer>
The weekday on which this job will be run (0 and 7 are Sunday).
Month <integer>
The month on which this job will be run.

3. 加载命令

launchctl load -w com.demo.plist

这样任务就加载成功了。


# 加载任务, -w选项会将plist文件中无效的key覆盖掉,建议加上
$ launchctl load -w com.demo.plist
# 删除任务
$ launchctl unload -w com.demo.plist
# 查看任务列表, 使用 grep '任务部分名字' 过滤
$ launchctl list | grep 'com.demo'
# 开始任务
$ launchctl start  com.demo.plist
# 结束任务
$ launchctl stop   com.demo.plist

plist 文件的字段说明

<?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">  
<plist version="1.0">  
  <dict>
    <!-- 名称,要全局唯一 -->
    <key>Label</key>
    <string>com.uniflor.notifier</string>
    <!-- 要运行的程序, 如果省略这个选项,会把ProgramArguments的第一个
    元素作为要运行的程序 -->
    <key>Program</key>
    <string>/Users/uniflor/script.sh</string>
    <!-- 命令, 第一个为命令,其它为参数-->
    <key>ProgramArguments</key>
    <array>
      <string>/Users/uniflor/script.sh</string>
    </array>
    <!-- 运行时间 -->
    <key>StartCalendarInterval</key>
    <dict>
      <key>Minute</key>
      <integer>30</integer>
      <key>Hour</key>
      <integer>9</integer>
      <key>Day</key>
      <integer>1</integer>
      <key>Month</key>
      <integer>5</integer>
      <!-- 0和7都指星期天 -->
      <key>Weekday</key>
      <integer>0</integer>
    </dict>
    <!-- 运行间隔,与StartCalenderInterval使用其一,单位为秒 -->
    <key>StartInterval</key>
    <integer>30</integer>
    <!-- 标准输入文件 -->
    <key>StandardInPath</key>
    <string>/Users/uniflor/run-in.log</string>
    <!-- 标准输出文件 -->
    <key>StandardOutPath</key>
    <string>/Users/uniflor/Bin/run-out.log</string>
    <!-- 标准错误输出文件 -->
    <key>StandardErrorPath</key>
    <string>/Users/uniflor/Bin/run-err.log</string>
  </dict>  
</plist>

配置文件

进入到~/Library/LaunchAgents下建一个plist文件com.test.launchctl.plist,内容如下:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.test.launchctl.plist</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/bin/python</string>
        <string>/Workspace/test.py</string>
    </array>
    <key>StartCalendarInterval</key>
    <dict>
        <key>Minute</key>
        <integer>4</integer>
        <key>Hour</key>
        <integer>13</integer>
    </dict>
    <key>KeepAlive</key>
    <false/>
    <key>RunAtLoad</key>
    <true/>
    <key>StandardOutPath</key>
    <string>/tmp/AutoMakeLog.log</string>
    <key>StandardErrorPath</key>
    <string>/tmp/AutoMakeLog.err</string>
</dict>
</plist>
StartCalendarInterval: 执行周期
RunAtLoad: 加载时执行一次
StandardOutPath: 标准输出路径
StandardErrorPath: 错误输出路径

管理定时任务

加载任务

cd ~/Library/LaunchAgents
launchctl load com.test.launchctl.plist

卸载任务

launchctl unload com.felink.gitmirror.plist

立即执行一次任务

launchctl start ccom.test.launchctl.plist

停止任务

launchctl stop ccom.test.launchctl.plist


写个简单的applescript。


on callmeican()
    set meican_url to "https://meican.com" as string
    tell application "Google Chrome"
        open location meican_url
        activate
    end tell
end callmeican
say "不要这么拼了,预订美餐时间到了"
display dialog "不要这么拼了,预订美餐时间到了(截至时间16:30)!" buttons {"好的", "我不定了"} default button 1
if the button returned of the result is "好的" then
    -- action for 1st button goes here
    callmeican()
end if

脚本的作用大概是MAC会通过弹窗和语音提醒我该订餐了,如果选择定,就自动用浏览器打开订餐的页面。这个脚本每天在四点执行。


1、使用crontab设置定时任务


crontab -e 或者sudo crontab -e。
00 16 * * * osascript /Users/hanlingzhi/project/applescript/meican.scpt

输入完成后,保存退出。系统自动建立新cron,提示如下:crontab: installing new crontab。设置非常简单。


2、使用苹果的Schedule jobs using launchd设置定时任务。需要写一个plist文件,描述任务的动作、间隔的时间、日志输出等参数。


我创建一个plist文件com.hanlingzhi.cron.meican.plist,大概内容如下:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <!-- 名称,要全局唯一 -->
    <key>Label</key>
    <string>com.hanlingzhi.cron.meican</string>
    <!-- 命令, 第一个为命令,其它为参数-->
    <key>ProgramArguments</key>
    <array>
        <string>osascript</string>
      <string>/Users/hanlingzhi/project/applescript/meican.scpt</string>
    </array>
    <!-- 运行时间 -->
    <key>StartCalendarInterval</key>
    <dict>
      <key>Minute</key>
      <integer>0</integer>
      <key>Hour</key>
      <integer>16</integer>
    </dict>
    <!-- 标准输入文件 -->
    <key>StandardInPath</key>
    <string>/Users/hanlingzhi/project/applescript/log/run-in-meican.log</string>
    <!-- 标准输出文件 -->
    <key>StandardOutPath</key>
    <string>/Users/hanlingzhi/project/applescript/log/run-out-meican.log</string>
    <!-- 标准错误输出文件 -->
    <key>StandardErrorPath</key>
    <string>/Users/hanlingzhi/project/applescript/log/run-err-meican.log</string>
  </dict>
</plist>

然后将plist文件放在/Users/hanlingzhi/Library/LaunchAgents,你的用户目录下,然后执行launchctl load plist就可以启动了。


plist脚本存放路径为/Library/LaunchDaemons或用户目录/Library/LaunchAgents,其区别是后一个路径的脚本当用户登陆系统后才会被执行,前一个只要系统启动了,哪怕用户不登陆系统也会被执行。


可以通过两种方式来设置脚本的执行时间。一个是使用StartInterval,它指定脚本每间隔多长时间(单位:秒)执行一次;另外一个使用StartCalendarInterval,它可以指定脚本在多少分钟、小时、天、星期几、月时间上执行,类似如crontab的中的设置。


<key>StartInterval</key>
<integer>3600</integer>
或者
<key>StartCalendarInterval</key>
<dict>
  <key>Minute</key>
  <integer>30</integer>
  <key>Hour</key>
  <integer>9</integer>
</dict>

launchctl的命令使用大家看一下帮助文档。


由于操作还是比较复杂,为了帮助快速执行,写了个shell快速拷贝新的plist并完成服务重启


__path='/Users/hanlingzhi/project/applescript'
__plist_path=${__path}/plist
__launchagents_path='/Users/hanlingzhi/Library/LaunchAgents'
# 拷贝plist到用户自己定义的任务项目录
cp -rf ${__plist_path}/* ${__launchagents_path}
# 根据plist中的文件遍历load
for plist_file in `ls ${__plist_path}`
do
    echo "重启${plist_file}定时任务"
    launchctl unload ${__launchagents_path}/${plist_file}
    sleep 0.5
    launchctl load ${__launchagents_path}/${plist_file}
    task_name=`echo ${plist_file} | sed 's/.plist//g'`
    launchctl list | grep ${task_name}
done

总结一下


虽然plist的设置会复杂很多。但是当前在mac os还是倾向于推荐使用Plist的方法,crontab已不推荐使用。


两者的区别:


1、plist可以设置到秒,而crontab只能到分钟。


2、plist可以同时应用于Mac OS/Iphone。


3、plist对于MAC上系统交互的操作更支持(我就出现过用crontab设置,运行时出现execution error: 不允许用户交互。 (-1713)的错误


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
SQL Unix Linux
Mac免密登录服务器下载文件+Mac设置定时任务
Mac免密登录服务器下载文件+Mac设置定时任务
Mac免密登录服务器下载文件+Mac设置定时任务
|
Python
crontab - 解决 mac 下通过 crontab 设置了 Python 脚本的定时任务却无法运行
crontab - 解决 mac 下通过 crontab 设置了 Python 脚本的定时任务却无法运行
644 0
|
Python iOS开发 MacOS
Mac中的定时任务利器:launchctl
launchctl是一个统一的服务管理框架,可以启动、停止和管理守护进程、应用程序、进程和脚本等。 launchctl是通过配置文件来指定执行周期和任务的。
2126 0
|
3月前
|
NoSQL 数据可视化 Redis
Mac安装Redis
Mac安装Redis
71 3
|
2月前
|
iOS开发 MacOS Windows
Mac air使用Boot Camp安装win10 ,拷贝 Windows 文件时出错
Mac air使用Boot Camp安装win10 ,拷贝 Windows 文件时出错
|
3月前
|
数据安全/隐私保护 iOS开发 MacOS
Mac安装Navicat Premium 16.3.5
Mac安装Navicat Premium 16.3.5
244 3
|
4天前
|
开发工具 iOS开发 开发者
「Mac畅玩鸿蒙与硬件2」鸿蒙开发环境配置篇2 - 在 Mac 上安装 DevEco Studio
本篇将专注于如何在 Mac 上安装鸿蒙开发工具 DevEco Studio,确保开发环境能够顺利搭建。完成安装后,可以正式开始鸿蒙应用的开发工作。
23 1
「Mac畅玩鸿蒙与硬件2」鸿蒙开发环境配置篇2 - 在 Mac 上安装 DevEco Studio
|
27天前
|
机器学习/深度学习 Python
【10月更文挑战第5天】「Mac上学Python 6」入门篇6 - 安装与使用Anaconda
本篇将详细介绍如何在Mac系统上安装和配置Anaconda,如何创建虚拟环境,并学习如何使用 `pip` 和 `conda` 管理Python包,直到成功运行第一个Python程序。通过本篇,您将学会如何高效地使用Anaconda创建和管理虚拟环境,并使用Python开发。
54 4
【10月更文挑战第5天】「Mac上学Python 6」入门篇6 - 安装与使用Anaconda
|
29天前
|
IDE 开发工具 iOS开发
【10月更文挑战第3天】「Mac上学Python 3」入门篇3 - 安装Python与开发环境配置
本篇将详细介绍如何在Mac系统上安装Python,并配置Python开发环境。内容涵盖Python的安装、pip包管理工具的配置与国内镜像源替换、安装与配置PyCharm开发工具,以及通过PyCharm编写并运行第一个Python程序。通过本篇的学习,用户将完成Python开发环境的搭建,为后续的Python编程工作打下基础。
159 2
【10月更文挑战第3天】「Mac上学Python 3」入门篇3 - 安装Python与开发环境配置
|
30天前
|
iOS开发 MacOS Python
【10月更文挑战第1天】「Mac上学Python 1」入门篇1 - 安装Typora与Markdown编辑技巧
本篇将详细介绍如何在Mac系统上安装Typora这款简洁高效的Markdown编辑器,并学习Markdown常用语法。通过本篇,用户能够准备好记录学习笔记的工具,并掌握基本的文档编辑与排版技巧,为后续学习提供便利。
140 1
【10月更文挑战第1天】「Mac上学Python 1」入门篇1 - 安装Typora与Markdown编辑技巧