在 macOS 上,launchd 是系统级的作业调度与服务管理器。相比传统 crontab,launchd 的优势是:支持按系统事件触发(如登录、网络就绪)、对用户/系统作业区分更清晰、并且可以用统一的日志体系排查问题。
参考链接(建议收藏):https://www.launchd.info/;Apple 文档:https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html
大多数个人定时任务建议放在 ~/Library/LaunchAgents(当前用户登录后运行)。如果你想让任务在开机后、无需登录就运行,那是 /Library/LaunchDaemons(通常需要管理员权限、并且注意权限与路径)。本文以 LaunchAgents 为例。
先创建目录(如果还没有):mkdir -p ~/Library/LaunchAgents
下面示例会在每天 23:30 运行一个脚本:把下载目录中 30 天前的 .dmg / .zip 移动到归档文件夹。它不会涉及任何破解/绕过付费等敏感操作,只做本地文件整理。
1) 创建脚本(示例路径):mkdir -p ~/bin 然后编辑 ~/bin/archive-downloads.sh,给执行权限:chmod +x ~/bin/archive-downloads.sh
脚本思路(示例命令,按你习惯调整):
mkdir -p "$HOME/Downloads/_Archive"
find "$HOME/Downloads" -maxdepth 1 -type f ( -name "*.dmg" -o -name "*.zip" ) -mtime +30 -exec mv -n {} "$HOME/Downloads/_Archive/" ;
2) 创建 launchd 配置(plist):保存为 ~/Library/LaunchAgents/com.demo.archive-downloads.plist
注意:plist 里的尖括号需要写成真实字符;这里用 < / > 只是为了在网页里展示。
<? 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.demo.archive-downloads</string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>-lc</string>
<string>$HOME/bin/archive-downloads.sh</string>
</array>
<key>StartCalendarInterval</key>
<dict><key>Hour</key><integer>23</integer><key>Minute</key><integer>30</integer></dict>
<key>StandardOutPath</key><string>/tmp/com.demo.archive-downloads.out</string>
<key>StandardErrorPath</key><string>/tmp/com.demo.archive-downloads.err</string>
</dict>
</plist>
加载并启用(推荐的写法):launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.demo.archive-downloads.plist
如果你修改了 plist,常见做法是先卸载再重新加载:
launchctl bootout gui/$(id -u) com.demo.archive-downloads
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.demo.archive-downloads.plist
立刻手动跑一次(验证脚本是否能正常执行):launchctl kickstart -k gui/$(id -u)/com.demo.archive-downloads
1) 路径问题:launchd 环境变量比你在终端里少,脚本里尽量用绝对路径,或者用 /bin/bash -lc 让它读取 shell 配置。
2) 权限问题:确保脚本可执行(chmod +x),并且脚本读写的目录对当前用户有权限。
3) 看输出:如果你设置了 StandardOutPath / StandardErrorPath,先看这两个文件内容;另外也可以用统一日志查询(示例):log show --style syslog --last 1h --predicate 'process == "launchd"'
用 launchd 的关键是:把任务脚本当成一个可重复执行、可观察(有日志)、可回滚(可卸载)的单元。按本文模板套用,你可以很快把“整理、备份、同步、生成报告”等日常工作做成稳定自动化。