Launchd状态78是什么意思?为什么我的用户代理程序没有运行?

55

我希望每次登录时都能运行一个后台同步服务。但是我的代理状态码是78,我不知道为什么,我尝试了一些在线修复方法,但它们都不起作用。

问题出在哪里?下面是我的服务的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>syncmyproject</string>
    <key>StandardOutPath</key>
    <string>/var/log/syncmyproject.log</string>
    <key>StandardErrorPath</key>
    <string>/var/log/syncmyproject.log</string>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <true/>
    <key>Debug</key>
    <true/>
    <key>EnableGlobbing</key>
    <true/>
    <key>ProgramArguments</key>
    <array>
      <string>/usr/local/bin/unison</string>
      <string>-auto</string>
      <string>-batch</string>
      <string>-repeat watch</string>
      <string>~/home/project</string>
      <string>~/project</string>
    </array>
</dict>
</plist>

7
你可以使用 grep 命令在文件 /var/log/system.log 中查找可能指出问题的线索。 - Nick
10个回答

65

我读了 man launchctl,发现78表示函数未实现。这并没有太大帮助。

最终我让它工作了,实际上plist中有错误,我建议安装 brew install --cask launchcontrol,它是一个用于launchctl的GUI工具,可以帮助检测错误和故障排除。


8
谢谢这个。launchcontrol帮助解决了我的问题。记录一下,我遇到了78状态,问题是我的脚本没有以解释器开头,例如#!/bin/sh - gooddadmike
5
问题在于,当前用户无法访问日志目录。 - d4Rk
1
在我的情况下,问题是目标应用程序没有执行权限。 - Preston
1
一个无效的“工作目录(WorkingDirectory)”也可能导致状态码为“78”。 - EpicVoyage
1
现在对于任何遇到这个问题的人来说,可以使用“brew install --cask launchcontrol”命令。我也已经提交了一份编辑。 - Robin van Baalen
显示剩余8条评论

16

我发现错误与权限有关。

我试图将错误和日志重定向到/var/log目录,但我的用户无法写入该目录。

将路径更改为我的用户具有适当读写权限的地方可以解决这个问题。

此外,在加载您的LaunchAgents时要小心。如果您在~/Library/LaunchAgents目录中,请勿使用sudo加载plist文件。


2
天啊,这也是我的错误!将日志更改为不同的文件夹可以解决它。 - Matt
2
在加载LaunchAgents时要小心。如果您位于~/Library/LaunchAgents目录中,请勿使用sudo加载plist。 哦,我的天啊。这...你是我的英雄。 - c4sh

13

要查看所有错误代码的描述,请输入

launchctl error <插入数字错误代码>

例如:

% launchctl error 77 77:没有可用的锁定


7
我也遇到了这个问题,所以记录下我找到的内容。 在你运行的作业中,“78”是最后的退出代码。从man launchctl得知:
没有参数时,在三列中列出所有加载到launchd中的作业。如果作业正在运行,则第一列显示作业的PID。 第二列显示作业的最后退出状态。如果该列中的数字为负数,则表示停止作业的信号的负数。 因此,“-15”表示使用SIGTERM终止了作业。 第三列是作业的标签。如果指定了[label],则打印有关所请求作业的信息。
也就是说,您需要阅读您启动的任何作业的文档(或源代码)。 (在我的情况下,是mysqld)
值得注意的是,在Linux上,“78”被提及为标准退出代码,表示配置错误。 因此,请查看您的作业配置(和错误日志),看看是否有某些配置错误。

2
在我的情况下,我忘记了对shell脚本进行chmod +x操作 :) - Edoardo
在我的情况下,日志轮换器(newsyslog)没有配置为还原标准输出和标准错误文件的先前所有者,导致当前用户无法写入它们。 - JamesKingston
我认为,在非 root 用户模式下,可以使用“/tmp/demo.stderr”作为“StandardErrorPath”的值。但是,“Console.app”日志并没有抱怨任何权限问题。删除 plist 中的这些“StandardPath”值会使服务 PID 状态返回到 0。 - zionpi

4

以下是引起我的注意的内容:在Mac OS X中,即使文件中只有“脚本”,你也可以从命令行运行shell脚本。然而,当你从launchd运行它们时,你必须告诉哪个二进制文件应该运行该脚本。我想当你从命令行运行时,它只使用当前所在的shell(在我的情况下是bash),但是当从launchd运行时,没有“周围的脚本”。

#!/bin/sh

在脚本文件的第一行加上这句话,然后它就能正常工作了。


我之前在文件头部添加了 #! 之前的注释,这导致了错误。脚本在 #! 之前不应该有任何注释。 - panc
@dan-bergh-johnsson,你可以告诉我 #!/bin/sh 应该放在哪里吗?能给个例子吗?谢谢。 - atreeon
1
@atreeon 在文件的确切开头必须有 #!/bin/sh。在第一行,不要缩进。实际上,在磁盘上,#! 必须是文件的前两个字节。 - Gordon Davisson

3
在我的情况下,<ProgramArguments> 标签中的脚本不可执行,因此出现了 78 function not implemented. 错误。

这是我的问题。升级到Catalina后,所有的代码都停止工作了,错误代码为78!原因是Catalina在我不知情的情况下执行了chmod 700 ~/Documents - Sukima
我无法为此点赞足够多。你救了我 :pray: :bow: - Sukima

2
类似于上文,我因为在脚本路径中有符号链接而得到了状态 78。解决方法是使用绝对路径。

1

我在尝试运行mono启动本地web服务器时遇到了这个错误。结果发现解决方法是不要使用"which mono"给出的mono路径(它是一个符号链接:/Library/Frameworks/Mono.framework/Versions/Current/Commands/mono),而是使用实际的exe位置(在我的情况下是/Library/Frameworks/Mono.framework/Commands/mono)。


0

我花了很长时间追寻状态78错误。

我的LaunchDamon能够通过手动启动并具有状态0,但在系统重新启动后却出现了状态78。有时守护进程正在运行,有时则没有。

使用应用程序 LaunchControl(顺便说一句,这个应用非常棒) 在这种情况下没有帮助。标准输出和错误文件中没有任何输出。

我可以通过将KeepAlive条件添加到守护进程的plist文件中来解决问题,引用一个挂载的文件系统,其中守护进程可执行文件驻留。

<key>KeepAlive</key>
<dict>
    <key>PathState</key>
    <dict>
    <key>/Volumes/MountedFileSystem</key>
    <true/>
    </dict>
</dict>

我希望这个技巧能对某些人有所帮助。


0

我一直得到代码 78,这是由于 xml 格式问题:

起初,我的 Emacs 自动重新格式化了我的 xml,如下所示:

<?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>user.eric.g.autosyncdropbox.agent</string>
    <key>ProgramArguments</key>
    <array>
      <string>/Users/eric/G/bin/fswatchG.sh</string>
    </array>
    <key>KeepAlive</key>
    <true />
    <key>StandardOutPath</key>
    <string>
    /Users/eric/.tmp/user.eric.g.autosyncdropbox.out.log</string>
    <key>StandardErrorPath</key>
    <string>
    /Users/eric/.tmp/user.eric.g.autosyncdropbox.error.log</string>
  </dict>
</plist>

我找不到这两行代码的返回值...

    <string>
    /Users/eric/.tmp/user.eric.g.autosyncdropbox.out.log</string>
    <key>StandardErrorPath</key>
    <string>
    /Users/eric/.tmp/user.eric.g.autosyncdropbox.error.log</string>

那真是太糟糕了,完全浪费了生命...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接