最近有个想法,就是想在MAC网络切换的时候,自动根据网络切换来判断是办公环境还是家庭环境,从而执行对应的动作
做技术的都知道,我们在linux下一般用crontab实现定时任务。
在MAC下,我们一般用launchd实现定时任务,以及其他事件触发的任务。
简单介绍下launchd,launchd存在于MAC OX的系统进程中,用户不能直接对该进程进行操作,只能通过launchctl对其进行管理。
launchctl是一个统一的服务管理框架,可以启动、停止和管理守护进程、应用程序、进程和脚本等。launchctl是通过配置文件来指定执行周期和任务的。配置文件一般是plist类型的文件。
属性列表(Property List)文件是一种用来存储序列化后的对象的文件。属性列表文件的文件扩展名为.plist,因此通常被称为plist文件。Plist文件通常用于存储用户设置,也可以用于存储捆绑的信息,plist中主要的字段和它的含义如下:
- Label用来在launchd中的一个唯一标识,如同每一个程序都有一个identifies一样。
- UserName指定运行启动项的用户,只有当Launchd 作为 root 用户运行时,此项才适用。
- GroupName指定运行启动项的组,只有当Launchd 作为 root 用户运行时,此项才适用。
- KeepAlive这个key值是用来控制可执行文件是持续运行,还是满足具体条件之后再启动。默认值为false,也就是满足具体条件之后才启动。当设置值为ture时,表明无条件的开启可执行文件,并使之保持在整个系统运行周期内。
- RunAtLoad标识launchd在加载完该项服务之后立即启动路径指定的可执行文件。默认值为false。
- Program这个值用来指定进程的可执行文件路径。
- ProgramArguments这个值用来指定可执行文件和运行的参数。
全部字段含义如下
Key | Description | Required |
Label | The name of the job | yes |
ProgramArguments | Strings to pass to the program when it is executed | yes |
UserName | The job will be run as the given user, who may not necessarily be the one who submitted it to launchd. | no |
inetdCompatibility | Indicates that the daemon expects to be run as if it were launched by?inetd | no |
Program | The path to your executable. This key can save the ProgramArguments key for flags and arguments. | no |
onDemand | A?boolean?flag that defines if a job runs continuously or not | no |
RootDirectory | The job will be?chrooted?into another directory | no |
ServiceIPC | Whether the daemon can speak IPC to launchd | no |
WatchPaths | Allows launchd to start a job based on modifications at a file-system path | no |
QueueDirectories | Similar to WatchPath, a queue will only watch an empty directory for new files | no |
StartInterval | Used to schedule a job that runs on a repeating schedule. Specified as the number of seconds to wait between runs. | no |
StartCalendarInterval | Job scheduling. The?syntax?is similar to?cron. | no |
HardResourceLimits | Controls restriction of the resources consumed by any job | no |
LowPriorityIO | Tells the kernel that this task is of a low priority when doing file system I/O | no |
Sockets | An array can be used to specify what socket the daemon will listen on for launch on demand | no |
plist脚本一般存放在以下目录:
-
/Library/LaunchDaemons
-->只要系统启动了,哪怕用户不登陆系统也会被执行 -
/Library/LaunchAgents
-->当用户登陆系统后才会被执行更多的plist存放目录:
~/Library/LaunchAgents 由用户自己定义的任务项
/Library/LaunchAgents 由管理员为用户定义的任务项
/Library/LaunchDaemons 由管理员定义的守护进程任务项
/System/Library/LaunchAgents 由Mac OS X为用户定义的任务项
/System/Library/LaunchDaemons 由Mac OS X定义的守护进程任务项一个简单的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>onnetworkchange</string>
<key>ProgramArguments</key>
<array>
<string>python</string>
<string>%s</string>
</array>
<key>StandardOutPath</key>
<string>%s</string>
<key>StandardErrorPath</key>
<string>%s</string>
<key>WatchPaths</key>
<array>
<string>/Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist</string>
</array>
</dict>
</plist>
launchd加载plist文件命令
launchctl load -w demo.plist
更多命令
#查看 launchctl使用手册, man在对mac下大部分命令通用,例如 man ifconfig
$ man launchctl
# 加载任务, -w选项会将plist文件中无效的key覆盖掉,建议加上
$ launchctl load -w zrbdemo.plist
# 删除任务
$ launchctl unload -w zrbdemo.plist
# 查看任务列表
$ launchctl list
# 开始任务
$ launchctl start zrbdemo.plist
# 结束任务
$ launchctl stop zrbdemo.plist
更多详情参见apple官方文档
由于MAC BOOK在切换Wi-Fi网络时 /Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist 文件会发生改变,利用 WatchPaths 属性即可监听该文件变化。
参照如上plist示例即可实现监听MAC网络改变事件,在触发事件时执行 ProgramArguments标签里配置的脚本文件%s
附带一个修改launchctl环境变量的办法(因为我遇到了launchctl使用的环境变量是系统默认环境变量导致python很多包找不到)
#将launchctl设置成当前用户的环境变量
launchctl setenv PATH $PATH #临时修改,电脑重启后会重置
sudo launchctl config user path $PATH #永久修改,电脑重启后不会重置
#不确定$PATH的值可以先
echo $PATH #打印PATH出来看看
以上纯属个人见解,有不足之处欢迎评论区喷博主~