使用 launchctl 管理 MacOS 服務

語言: CN / TW / HK

在 Linux 上有一個大家用慣的 systemd,在 MacOS 上有一個與之相對應的工具,launchd。

Linux 下,systemd 的 pid 是 1,系統啟動後,它是第一個被拉起來的,其它程序都是它的子程序。所以在 Linux 下,用 systemd 來做 supervisor 是最穩妥的辦法。因為如果 systemd 掛掉了,整個系統都 crash 了。

MacOS 下面也有一個這樣的超級程序,所有的其它程序都是它產生的,掛為它的子程序、孫子程序…… 它就是 launchd。launchd 對應的管理工具就是 launchctl。

1. 原理

通過後綴名為 .plist 的配置檔案追加 launchd 的管理項。新增和刪除,都是用 .plist 檔案來完成的。

.plist 檔案存在於下面的資料夾中,分別是。

型別 路徑 說明
User Agents ~/Library/LaunchAgents 為當前登入使用者啟動
Global Agents /Library/LaunchAgents 為當前登入使用者啟動
Global Daemons /Library/LaunchDaemons root 或者通過 UserName 配置指定的使用者
System Agents /System/Library/LaunchAgents 當前登入使用者
System Daemons /System/Library/LaunchDaemons root 或者通過 UserName 配置指定的使用者

按照需要將你要監控的程式放到不同等級的目錄中。

2. 配置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>com.simonkuang.macos.coredns</string>
    <key>Disabled</key>
    <false/>
    <key>KeepAlive</key>
    <true/>
    <key>ProcessType</key>
    <string>Background</string>
    <key>ProgramArguments</key>
    <array>
      <string>/usr/local/bin/coredns</string>
      <string>-conf</string>
      <string>/usr/local/etc/Corefile</string>
    </array>
    <key>UserName</key>
    <string>root</string>
    <key>GroupName</key>
    <string>wheel</string>
  </dict>
</plist>

上面的例子是啟動一個 coredns 程序。啟動的命令如下。

/usr/local/bin/coredns -conf /usr/local/etc/Corefile

配置中的專案包括。

  • Label: 應該是唯一的 package name。
  • Disabled: 是否不生效(launchd 忽略,不執行)
  • KeepAlive: 意外掛掉的話,是否由 launchd 重新拉起。
  • ProcessType: 程序型別。
  • ProgramArguments: 程式引數。
  • UserName: 啟動程序的使用者。
  • GroupName: 啟動程序的使用者組。

因為 coredns 會啟動 53/udp 埠的監聽,53 < 1024,因此我們需要給它 root 使用者的許可權。因為 dns 是基礎網路服務,因此以系統程序的方式啟動。所以該配置檔案按下面的路徑儲存。

/Library/LaunchDaemons/com.simonkuang.macos.coredns.plist

請注意,檔名和 Label 保持一致。

3. 操作

# 載入配置
launchctl load -w /Library/LaunchDaemons/com.simonkuang.macos.coredns.plist

# 解除安裝配置
launchctl unload /Library/LaunchDaemons/com.simonkuang.macos.coredns.plist

# 修改配置後重載配置
launchctl unload /Library/LaunchDaemons/com.simonkuang.macos.coredns.plist && \
launchctl load -w /Library/LaunchDaemons/com.simonkuang.macos.coredns.plist

-w 引數的意思是,無論配置中 Disabled 項是 true 還是 false,都啟動程序。這個引數對除錯配置和程序特別有效。

載入成功的服務,系統重啟後會按照配置執行,達到 supervisor 的目的。

4. 更多

# 檢視所有的 plist 服務
launchctl list

# 禁用服務
launchctl disable /Library/LaunchDaemons/com.simonkuang.macos.coredns.plist

# 啟用服務
launchctl disable /Library/LaunchDaemons/com.simonkuang.macos.coredns.plist

# 殺死程序(不優雅地殺,直接殺程序)並重啟服務。對一些停止響應的服務有效。
launchctl kickstart -k /Library/LaunchDaemons/com.simonkuang.macos.coredns.plist

# 在不修改 Disabled 配置的前提下啟動服務
launchctl start /Library/LaunchDaemons/com.simonkuang.macos.coredns.plist

# 在不修改 Disabled 配置的前提下停止服務
launchctl stop /Library/LaunchDaemons/com.simonkuang.macos.coredns.plist