MAC本如何优雅的创建定时任务


在MACOS上设置定时任务大体有两种方案。一种是使用crontab,一种是使用Schedule,今天结合我的使用简单介绍一下。

先说一下背景,为什么MAC可以用crontab。如果使用过Linux的同学,设置定时任务经常会使用crontab、nohup。苹果根据FreeBSD开发了Mac OS,后续的每一个新版本的Mac OS系统都很大程度上保留了FreeBSD的新特性。当然也包括Shell,也包括crontab。

适用的场景,举个例子,公司每天下午4点钟准时订餐,错过可能就要饿肚子了(吐舌头),为了在繁忙的工作中,还能够记起这个事情,决定设置个定时任务提醒自己。

我第一选择了写个简单的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,其区别是后一个路径的脚本当用户登陆系统后才会被执行,前一个只要系统启动了,哪怕用户不登陆系统也会被执行。

  • 系统定义了几个位置来存放任务列表

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

可以通过两种方式来设置脚本的执行时间。一个是使用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)的错误)


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM