Mac特定通知触发脚本钩子咨询:iCal/GCal事件联动需求
嘿,针对你的两个核心需求——监控特定通知触发脚本,以及让iCal/GCal事件触发系统行为,我整理了几个实用的原生/轻量方案,完全符合你“通知触发脚本而非反向”的要求:
一、监控特定系统通知触发脚本
Mac的Notification Center本身没有原生的钩子API,但我们可以通过轮询的方式实现可靠监控,完全用系统自带工具就能搞定:
方案1:AppleScript + LaunchAgent 后台监控
写一个AppleScript脚本,定时检查Notification Center里的通知,匹配你指定的标题/内容,一旦命中就触发目标脚本,还能删除已处理的通知避免重复触发:repeat tell application "System Events" set allNotifications to every notification of notification center repeat with n in allNotifications -- 这里替换成你要监控的通知标题/关键词,比如日历事件的通知 if title of n contains "团队会议" and subtitle of n contains "即将开始" then -- 替换成你的脚本路径 do shell script "/Users/you/scripts/start-meeting.sh" -- 删除已处理的通知,防止重复触发 delete n end if end repeat end tell delay 5 -- 每5秒检查一次,可根据需求调整间隔 end repeat把脚本保存为
notification-watcher.scpt,然后创建一个LaunchAgent让它后台自动运行:
在~/Library/LaunchAgents/目录下新建com.yourname.notificationwatcher.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.yourname.notificationwatcher</string> <key>ProgramArguments</key> <array> <string>osascript</string> <string>/Users/you/scripts/notification-watcher.scpt</string> </array> <key>RunAtLoad</key> <true/> <key>KeepAlive</key> <true/> <key>StandardErrorPath</key> <string>/tmp/notification-watcher.err</string> <key>StandardOutPath</key> <string>/tmp/notification-watcher.out</string> </dict> </plist>最后加载这个LaunchAgent:
launchctl load ~/Library/LaunchAgents/com.yourname.notificationwatcher.plist方案2:自定义通知绑定脚本(仅适用于你自己发送的通知)
如果你是用脚本发送通知,可以用terminal-notifier的-execute参数直接绑定触发脚本,但这个方法只适用于你自己生成的通知,系统自带的日历通知没法直接用。
二、iCal/GCal事件触发系统行为(更可靠的替代方案)
其实处理日历事件的话,我更推荐直接监控事件时间,而不是依赖通知——毕竟通知可能被屏蔽、延迟,直接对接日历数据更稳定:
方案1:AppleScript + LaunchAgent 定时检查日历
写一个AppleScript脚本,定时扫描日历里即将开始/结束的事件,匹配关键词后触发脚本:set currentTime to current date tell application "Calendar" -- 检查接下来1分钟内开始的事件 set upcomingEvents to every event of every calendar where start date is greater than currentTime and start date is less than (currentTime + 60 seconds) repeat with evt in upcomingEvents if summary of evt contains "团队会议" then do shell script "/Users/you/scripts/start-meeting.sh" end if end repeat -- 检查接下来1分钟内结束的事件 set endingEvents to every event of every calendar where end date is greater than currentTime and end date is less than (currentTime + 60 seconds) repeat with evt in endingEvents if summary of evt contains "团队会议" then do shell script "/Users/you/scripts/end-meeting.sh" end if end repeat end tell同样用LaunchAgent定时运行这个脚本,比如每60秒一次——只需要在plist里添加:
<key>StartInterval</key> <integer>60</integer>方案2:用
icalBuddy命令行工具(更灵活的文本处理)icalBuddy是个强大的开源日历命令行工具,能快速输出日历事件的文本信息,方便用shell脚本处理:
先安装(需要Homebrew):brew install ical-buddy然后写一个shell脚本:
#!/bin/bash # 获取接下来1分钟内开始的事件 UPCOMING=$(icalBuddy -n -e 1 eventsToday | grep -A 2 "Start:") if [[ "$UPCOMING" == *"团队会议"* ]]; then /Users/you/scripts/start-meeting.sh fi # 获取接下来1分钟内结束的事件 ENDING=$(icalBuddy -n -e 1 eventsToday | grep -A 2 "End:") if [[ "$ENDING" == *"团队会议"* ]]; then /Users/you/scripts/end-meeting.sh fi同样用LaunchAgent定时运行这个脚本即可。
小提示
如果你的核心需求是响应日历事件,优先选择直接监控日历的方案;如果必须响应系统弹出的特定通知(比如来自其他应用的通知),再用Notification Center轮询的方案。
内容的提问来源于stack exchange,提问作者RenaissanceBug

