macOS 下的 systemd —— launchd

背景

在 macOS 中,Launchd 是一个系统级别的进程管理工具,用于启动、停止和管理系统和用户级别的进程。Launchd 进程本身是由内核启动的,并负责启动其他进程,包括系统服务和用户级别的进程。

Launchd 启动的进程通常会将输出日志写入系统日志,我们可以使用 macOS 提供的 Console 应用程序来查看这些日志。

编写 launchd 配置文件

launchd 的配置文件是通过一个 plist 文件来定义的(plistproperty list 的缩写),一个典型的格式如下:

<?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>  
  <!-- Label 可以看作是守护进程的名称,key 是配置的名称,key 的下一行就是它的值,string 标签表示值的类型是字符串 -->  
  <key>Label</key>  
  <string>com.example.app</string>  
  <key>Program</key>  
  <string>/Users/Me/Scripts/cleanup.sh</string>  
  <key>RunAtLoad</key>  
  <true/>  
</dict>  
</plist>  

说明:

  • 配置文件中,除了 dict 里面的那一部分,其他的都是固定的,不需要修改。
  • 三个字段说明:
  • Label:也就是服务的名字,可以随便取,但是不能重复。我们通过 launchctl list 来查看的时候,列出的就是这个名字。上述例子是 com.example.app
  • Program:要启动的程序的路径,需要填写绝对路径。上述例子是 /Users/Me/Scripts/cleanup.sh如果需要加参数的话,需要使用 ProgramArguments 来代替 Program
  • RunAtLoad:是否在配置被加载的时候就运行,默认是 false,如果需要在启动的时候就运行,需要设置为 true。上述例子是 true
  • 标签说明:key 就是属性的名称,紧跟着 key 的下一行就是属性的值,属性的值的类型通过其标签反映出来,比如上面的 <string> 表示包裹的是一个字符串类型,而 <true/> 表示是一个布尔类型,而且它的值是 true

mac 中很多配置都是通过 plist 来定义的,

macOS 中有两种类型的守护进程,一种是系统级别的(Daemons),一种是用户级别的(Agents),它们的配置文件放的位置是不一样的。

下面是 launchd 配置文件的路径:

  • ~/Library/LaunchAgents:用户级别的守护进程配置文件路径。这里保存特定用户的 Agents 配置。(一般情况都是放这里
  • /Library/LaunchAgents:用户级别的守护进程配置文件路径。这里保存所有用户共用的 Agents 配置。
  • /Library/LaunchDaemons:全局的 Daemons 配置。
  • /System/Library/LaunchAgents:所有登录用户共用的 Agents 配置。
  • /System/Library/LaunchDaemons:全局的 Daemons 配置。

常用命令

列出所有 launchd 管理的服务

launchctl list
  • 第一列是进程 id,如果是 0 说明没有在运行状态。
  • 第二列的 0 表示的是进程上一次的退出状态码,0 一般表示成功。
  • 第三列表示的是我们在 plist 配置文件中配置的 Label 的值。

开机启动/不启动

launchctl load ~/Library/LaunchAgents/com.example.app.plist  
launchctl unload ~/Library/LaunchAgents/com.example.app.plist  

相当于systemctl enable xxxsystemctl disable xxx

启动/停止

launchctl start com.example.app 
launchctl stop com.example.app

相当于 systemctl start xxxsystemctl stop xxx

案例frps

文件 ~/Library/LaunchAgents/frpc.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>KeepAlive</key>
  <true/>
  <key>Label</key>
  <string>frpc</string>
  <key>ProgramArguments</key>
  <array>
    <string>/Users/kelu/Workspace/bin/frp_0.52.3_darwin_arm64/frpc</string>
    <string>-c</string>
    <string>/Users/kelu/Workspace/bin/frp_0.52.3_darwin_arm64/tmp.toml</string>
  </array>
  <key>RunAtLoad</key>
  <true/>
</dict>
</plist>

KeepAlive,指定后台保持运行

这个配置文件的作用是,以守护进程的方式来启动命令。

launchctl load ~/Library/LaunchAgents/frpc.plist  

image-20231211094334367

确认已经运行

ps aux | grep frpc

查看日志,目前我用 console 查不出来 frpc 的日志,先放着了。

某些网络会对长时间的udp连接做重置,所以我们本地耶可以设置定时任务杀掉frpc。

参考资料


置身事内:中国政府与经济发展 摘抄 macOS 使用 homebrew 切换不同 nodejs 版本