无需重启即可从 launchd 中删除进程

无需重启即可从 launchd 中删除进程

我有一台不想运行 Finder 的机器,所以最初我将其设置为不可执行:

sudo chmod -R a-x /System/Library/CoreServices/Finder.app

但随后意识到 launchd 仍然每秒尝试启动 finder 多次,导致生成包含数百万行内容的庞大日志文件:

com.apple.launchd.peruser.502[109] (com.apple.Finder[93799]) <Error>: posix_spawn("/System/Library/CoreServices/Finder.app/Contents/MacOS/Finder", ...): Permission denied
com.apple.launchd.peruser.502[109] (com.apple.Finder[93799]) <Warning>: Exited with exit code: 1

所以我编辑了/System/Library/LaunchAgents/com.apple.Finder.plist它,让它不再启动。我现在遇到的问题是强制 launchd 重新加载 plist,因此停止尝试启动 finder。但是,我无法重新启动机器。

我曾尝试使用 launchctl 来删除和卸载该进程,但似乎不起作用:

$ sudo launchctl unload -w /System/Library/LaunchAgents/com.apple.Finder.plist 
launchctl: Error unloading: com.apple.Finder
$ sudo launchctl remove com.apple.Finder
launchctl remove error: No such process

有什么方法可以让我停止 launchd 持续尝试加载 finder 而无需重新启动机器?

答案1

Finder 是 LaunchAgent,而不是 LaunchDaemon,这意味着它是作为登录会话的一部分加载的。要么使用launchctl unload不带sudo,要么直接注销并重新登录。

答案2

您的日志显示正在为用户 502 运行 Finder,但您正在使用 运行launchctlsudo而 root 没有运行 Finder。请尝试launchctl unload不使用sudo

答案3

正如 Gordon 所说,您需要launchctl unload ...在用户的相同 mach 引导上下文中执行命令。 launchctl 本身具有通过 bsexec 执行此操作的功能,您只需为其提供在该用户上下文中运行的任何进程的 PID,Finder 未运行,因此请选择其他进程。 用户相对根进程是loginwindow console,因此这是最有意义的:

USERNAME=yourusername;export USERNAME; sudo launchctl bsexec "$(ps auxww | grep loginwindow\ console | grep "$USERNAME" | grep -v grep | awk '{print $2}')" sudo -u "$USERNAME" launchctl unload -wF /System/Library/LaunchAgents/com.apple.Finder.plist 

yourusername用您影响的用户名替换,然后瞧。

答案4

一些评论中给出的错误信息:

Bug: launchctl.c:2325 (23930):13: (dbfd = open(g_job_overrides_db_path, O_RDONLY | O_EXLOCK | O_CREAT, S_IRUSR | S_IWUSR)) != -1

显示launchctl正在尝试打开文件但失败了。这可能是由于权限问题,但考虑到使用,这似乎不太可能sudo -u。更可能是与标志有关O_EXLOCK。大概是launchd在启动作业时锁定数据库,可能是为了检查作业是否被禁用,并且它频繁地重试作业,以至于数据库文件大部分时间都被锁定。

launchd运行一个不断尝试卸载作业的循环最终应该在文件未锁定时进入:

for ((i = 0; i < 100; i++))
do
    echo -n "$i "
    launchctl unload ... && break
done

我知道卸载作业ssh通常是可行的,因为我已经做过很多次了,所以我认为问题一定出在故障/重新加载周期的频率上。

相关内容