背景

由于工作中经常定期发送某些“提醒”邮件,所以为了“偷懒”,就研究了一下macbook如何自动定时发送邮件;

发送邮件小程序

由于主力技术栈是java,所以就随便写了一个自动发送邮件的java小程序; 这类程序网上很多,就不赘述了,在此po出我的示例代码:

Java发邮件 入口程序:javaMailDemo.java(其他不相关的可以忽略) 这里考虑到防止误发,用一个小的swing UI包装了一下。 自行运行一下看看效果接口;

mac自动执行程序

编写了一段shell脚本,触发之前编写好的程序;

#!/bin/sh
java -cp /Users/Desktop/javamail/javamail-1.0-SNAPSHOT.jar com.fengshenju.JavaMailDemo
  1. 用mac的Launch机制,自动触发shell脚本 首先参照案例(网上百度),编写一份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>Javamail</key>
    <string>com.fengshenju</string>
    <!-- 任务加载时就默认启动一次 -->
    <key>RunAtLoad</key>
    <true/>
    <!-- 任务内容 -->
    <key>ProgramArguments</key>
    <array>
    <!-- 执行一个脚本_(:зゝ∠)_脚本都可以执行了,基本上什么羞羞的事情都可以做了,脚本内容在最下面贴出 -->
      <string>/Users/Desktop/javamail/javamail.sh</string>
    </array>

    <!--
        任务执行间隔,如果计算机进入休眠,在唤醒前有多个任务被执行,则这些时间会合并成一个事件再执行。
    -->
    <key>StartInterval</key>
    <integer>60</integer>

    <!--
        日历的形式执行任务
        Minute <integer>    分钟
        Hour <integer>      小时
        Day <integer>       哪天
        Weekday <integer>   周几(0和7都表示周日)
        Month <integer>     几月
        = = 感觉挺麻烦,在下面说几个例子方便理解
    -->
    <key>StartCalendarInterval</key>
    <array>
        <dict>
            <key>Weekday</key>  <!-- 周几 -->
            <integer>1</integer>
            <key>Hour</key>     <!-- 小时 -->
            <integer>8</integer>
            <key>Minute</key>   <!-- 分钟 -->
            <string>58</string>
        </dict>
        <dict>
            <key>Weekday</key>
            <integer>2</integer>
            <key>Hour</key>
            <integer>8</integer>
            <key>Minute</key>
            <string>52</string>
        </dict>
    </array>

    <!-- 输出日志路径 -->
    <key>StandardOutPath</key>
    <string>/Users/Desktop/javamail/stdout.log</string>
    <!-- 异常日志路径 -->
    <key>StandardErrorPath</key>
    <string>/Users/Desktop/javamail/stderr.log</string>
</dict>
</plist>

然后可将plist文件上传至

~/Library/LaunchAgents           # 当前用户定义的任务
 /Library/LaunchAgents           # 系统管理员定义的任务
 /Library/LaunchDaemons          # 管理员定义的系统守护进程任务
 /System/Library/LaunchAgents    # 苹果定义的任务
 /System/Library/LaunchDaemons   # 苹果定义的系统守护进程任务

四者中任何一个目录,当然建议就用第一个目录。 假设plist文件名为:com.fengshenju.javamail.plist

放置好后,可用如下指令,加载plist文件,让规则生效 launchctl load ~/Library/LaunchAgents/com.fengshenju.javamail.plist

注:加载文件时,它会自动触发一次程序

可能遇到的问题

  1. 触发程序后,没有执行,如何查看 plist中异常日志路径:StandardErrorPath的配置,可查看里面的相关日志;
  2. 程序被触发后,报错:operation not permitted 原因是mac在某个版本后,启动了沙箱机制,需要将其关闭; 具体操作:重启,按住command+R键,进入恢复模式,打开terminal输入:csrutil disable ,再重启即可
  3. plist触发shell执行jar包时,报错:找不到主加载类; 需要将shell脚本中的jar包路径改为全路径;
  4. 常用的plist指令
# 加载任务
launchctl load ~/Library/LaunchAgents/com.hello.plist
# 强制加载任务, -w选项会将plist文件中无效的key覆盖掉
launchctl load -w ~/Library/LaunchAgents/com.hello.plist

# (-w强制)移除任务
launchctl unload ~/Library/LaunchAgents/com.hello.plist
launchctl unload -w ~/Library/LaunchAgents/com.hello.plist

# 手动执行任务
launchctl start com.hello

# 列出所有任务
launchctl list

# 查看任务列表, 使用 grep '任务部分名字' 过滤
$ launchctl list | grep 'com.hello'

参照链接:MAC定时任务