【问题标题】:How to know a specific launchd.plist file location?如何知道特定的 launchd.plist 文件位置?
【发布时间】:2013-09-01 09:36:43
【问题描述】:

是否可以知道加载到launchctl命令中的.plist文件位置?

标签名称以“launchctl list”列出,其内容可以通过“launchctl list LABEL”查看,但我找不到.plist文件位置。

我知道它将位于 /Library/LaunchAgent 或 ~/Library/LaunchAgent 或其他地方, 但我不想在使用 launchctl 命令列出所有作业时搜索路径。

【问题讨论】:

  • 谢谢特洛伊木马,我不知道这个网站!

标签: macos launchd


【解决方案1】:

这个问题经常出现,不幸的是locatemdfind 都没有显示来自我系统上相应目录的结果。我将以下函数放在我的.bashrc 中,这样我就可以快速搜索launchctl 查找plist 文件的目录。

launchctlFind () {
    LaunchctlPATHS=( \
        ~/Library/LaunchAgents \
        /Library/LaunchAgents \
        /Library/LaunchDaemons \
        /System/Library/LaunchAgents \
        /System/Library/LaunchDaemons \
    )

    for curPATH in "${LaunchctlPATHS[@]}"
    do
        grep -r "$curPATH" -e "$1"
    done
    return 0;
}

请注意,这只会检查launchctl 在启动和登录时查找文件的目录。它可能无法找到所有内容,因为作业可以由用户和/或其他进程手动加载。

更新:对于那些运行 macOS 10.12.6 或更高版本的用户,我建议使用 Joel Bruner 的解决方案。

【讨论】:

  • 最好将“grep -r”改为“grep -R”,让grep命令跟随符号链接。
【解决方案2】:

从 macOS 10.12.6(不确定早期版本)开始,可以调用:launchctl dumpstate,您将获得有关所有正在运行的进程的大量信息

查找<LABEL> = { 作为与该工作有关的第一行信息

这是获取所有活动守护进程及其 plist 路径的单一方法:

grep -B 1 -A 4 "active count = 1$" <<< "$(launchctl dumpstate)"

更新:自 10.12 起,macOS 添加了其他值,因此 grep -A n 已增加到 4 行

【讨论】:

  • 无论如何在我的机器上这不起作用。它只提供部分转储,然后在恰好 20mb 的数据后停止,没有错误消息或随机服务中间的任何内容
【解决方案3】:

在 Catalina 上,我设计了这个脚本来打印在 system 域或登录用户中找到的所有正则表达式匹配对象的 plist。请注意,这是一个 BASH 脚本,但也适用于我的 ZSH 测试。

用法:find_loaded_plist [ regex ]

请在下面的 cmets 中报告错误/建议。

find_loaded_plist() {
     launchctl list  | 
     awk "NR>1 && /${1:-^}/  { print \$3 }"  | 
     while read name; do
             launchctl print system/$name 2>/dev/null | 
                sed -n 's/^[[:space:]]*path = //p'
             for u in $(users |xargs id -u ) ; do                                 
                  launchctl print uid/$u/$name 2>/dev/null |
                     sed -n 's/^[[:space:]]*path = //p'
             done;
     done; 
}

【讨论】:

    【解决方案4】:

    在最新版本的 macOS 中,您可以使用 launchctl print 命令。您必须知道它在哪个域下运行,例如systemgui/<uid>。您可以在手册页中找到其他一些域,但到目前为止,我只看到在这两个域下运行的服务。例子:

    % launchctl print gui/$(id -u)/com.apple.cloudphotod  | grep path
        path = /System/Library/LaunchAgents/com.apple.cloudphotod.plist
    
     % launchctl print system/com.openssh.sshd | grep path 
        path = /System/Library/LaunchDaemons/ssh.plist
        stderr path = /dev/null
    

    我相信这个命令是在 High Sierra 或附近实施的。

    【讨论】:

      【解决方案5】:

      这个问题可能没有答案!似乎launchctl list 中的所有内容都不会有 plist 文件。

      如前所述,launchctl dumpstate 将为您提供大量信息,包括 plist 路径(如果存在)。

      您可以运行此命令以大致查看正在运行的所有内容及其 plist 路径的列表。

      launchctl dumpstate | grep -A4 " = {" | grep -B 3 -A 3 -E "active count = [1-9]"
      

      (虽然这似乎也包括其他运行的程序不是由 launchd 管理的守护进程?)

      代理/守护程序将在其标识符下方有一个路径字段。通常,路径指向Reed's answer 描述的标准 5 个位置中的 plist 文件。但是,它不一定是。例如,Steam 从非标准位置加载 launchctl 服务。

      ➜ launchctl dumpstate | grep -A4 " = {" | grep -B 3 -A 3 -E "active count = [1-9]"  | grep valve
      com.valvesoftware.steam.ipctool = {
          path = /Users/chris/Library/Application Support/Steam/com.valvesoftware.steam.ipctool.plist
      

      幸运的是,这种做法并不太流行,因此搜索标准位置通常就足够了。

      但这还不是最棘手的事情。我不知道具体细节,但似乎launchctl 服务可以在没有相应的 plist 文件的情况下加载。例如,这就是 dumpstate 对 1Password 助手守护进程所说的内容。

      ➜ launchctl dumpstate | grep -A4 " = {" | grep -B 3 -A 3 -E "active count = [1-9]"  | grep -A4 "onepassword7-helper = {"
      2BUA8C4S2C.com.agilebits.onepassword7-helper = {
          active count = 5
          path = (submitted by smd.1154)
          state = running
      

      我不知道“由 smd 提交”的真正含义,但归结为即使我在 launchctl list 中看到了帮助程序,文件系统上也可能没有任何 plist。因为这个我不知道如何launchctl unload这个服务因为卸载需要一个plist路径!而且由于这个进程是由launchd 管理的,即使我pkill -9 onepassword7-helperlaunchd 看到进程停止并重新启动它。

      (幸运的是,对于这个特定的 1Password 示例,如果您在单击退出 1Password 时按住 ^,则会出现一个特殊的“完全使用 1Password”选项)

      【讨论】:

      • 有趣的旁注,但我多年来一直在使用grep,直到我读到这篇文章才知道-B-A 标志。这非常有用。谢谢!
      【解决方案6】:

      这里是列出所有加载的.plist文件及其对应文件的命令:

      find /System/Library/Launch* /Library/Launch* ~/Library/Launch* -name '*.plist' -exec sh -c '/usr/libexec/PlistBuddy -c "Print Label" {} && echo {}' ';' | grep -wf <(launchctl list | grep -o "\S\+\..*$") -A1 | strings

      或其他版本:

      find /System/Library/Launch* /Library/Launch* ~/Library/Launch* -name '*.plist' -exec /usr/libexec/PlistBuddy -c "Print Label" {} ';' -print | grep -wf <(launchctl list | grep -o "\S\+\..*$") -A1 | strings

      解释:

      • find 所有.plist 文件位于以下位置:/System/Library/Launch* /Library/Launch* ~/Library/Launch*
      • 使用PlistBuddy 命令打印所有找到的.plist 文件中的Label
      • 使用find-print 参数打印该文件的路径。
      • 获取加载到launchd 的所有作业的另一个列表,并用作grep -f 的模式文件。
      • 过滤两个列表并找到共同的元素并打印其标签及其路径 (-A1)。
      • 通过strings 过滤以避免打印二进制文件。

      【讨论】:

      • 请注意,可以将 plist 加载到不在这些默认位置的 launchctl 中。 Steam 和 1Password 就是这样做的。所以这不会找到所有东西。
      【解决方案7】:

      由于launchctl list列出PID,一种方法是使用lsof命令查看进程所有加载的文件,例如

      launchctl list | grep -o '^[0-9]\+' | xargs -n1 lsof -p | grep plist$
      

      另一种方法是运行fs_usage 命令并重新加载.plist 文件,例如

      sudo fs_usage | grep -w launchd | grep -w plist
      

      【讨论】:

      • 至少在 Catalina 上,plist 没有被启动的进程打开,所以这个解决方案不起作用。很遗憾。不过好主意
      【解决方案8】:

      launchctl list 中使用的进程名称在 plist 中声明。虽然 plist 应该在上面提到的位置,但它们几乎可以在任何地方。

      我找到了我正在寻找的 plist 和'locate。我在找 org.postgresql.postgres locate *.plist | grep org.postgresql.postgres 将其缩小到 4 个文件

      【讨论】:

        猜你喜欢
        • 2014-12-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多