Mac 登录后到底自动启动了什么?怎么查出来并关掉?
用终端逐一排查 macOS 在登录时替你启动的东西——登录项、launchd 用户代理与系统守护进程——然后关掉你没同意过的那些。
快速开始
macOS 里能「自动启动」的位置其实有三处:登录项(系统替你重新打开的应用)、launchd 用户代理(你登录后加载的后台任务)、launchd 系统守护进程(开机时、还没人登录就加载的任务)。只有第一处能在「系统设置」里看到,所以「这玩意儿是什么、为什么在跑」在图形界面里才这么难查。这篇文章用终端把三处都读一遍,弄清每个任务到底是什么,再把不该留下的持久关掉——重启也不会复活。
症状
先用 System Events 列一遍所有登录项
这是 macOS 在你登录时替你重新打开的那一类程序,在「系统设置 > 通用 > 登录项」里也能看到。通过 System Events 取到的是一份纯名字列表,方便你复制、与你装过的东西比对、再决定怎么处理。列表里出现你不认识的名字,那就是第一嫌疑人。返回一串名字(或者干脆为空,说明一个登录项都没有),这一步就算成功。
osascript 通过 System Events 列出所有登录时自动启动的应用,并可按名称删除不需要的项。
$ osascript -e 'tell application "System Events" to get the name of every login item'▾ 撤销
$ osascript -e 'tell application "System Events" to delete login item "App Name"'再查 launchd:列出你当前会话里加载的任务
会自动启动的东西并不都是「登录项」。launchd 的用户代理和系统守护进程会悄悄加载,图形界面里根本看不到——只在「系统设置」里查,一定会漏。这份列表给出你会话中每个任务的 PID 和上次退出码:有 PID 说明此刻正在跑,退出码非 0 说明它一直在崩、又被反复拉起。看到一长串任务标签就算成功;重点扫一遍那些第三方前缀(com.google、com.docker 之类的厂商名),确认它们是不是你真想留着的。
用 launchctl list 列出用户域内所有代理的标签、PID 和上次退出状态,排查多余的后台程序。
$ launchctl list | head -30读懂可疑任务自己的定义文件(plist)
光看任务标签(label)几乎看不出什么,信息全在它的 plist 里:执行的是哪个可执行文件、是加载即运行还是按计划运行、以哪个用户身份运行。把它格式化打印出来,得到的就是一份能直接读的键值表,不用去啃 XML——这样才能分清它是正经的更新器还是你根本不想要的东西。重点看 ProgramArguments(到底执行了什么)和 RunAtLoad / KeepAlive。这一步是可选的:只有当某个标签已经引起你注意时才需要。
把任意属性列表以可读的键值形式输出——不用 Xcode,也不必啃 XML。
$ plutil -p ~/Library/Preferences/com.apple.TextEdit.plist顺便确认 SSH 远程登录有没有偷偷开着
Mac 上最容易被漏掉的自启项根本不是登录项:只要「远程登录」(SSH)是开的,sshd 从开机那一刻就在监听——没人登录也照跑,而图形界面的启动相关设置里什么都看不到。排查「什么会自动启动」不查这一项就是漏的。这一步要 sudo,因为这是整机级别的设置。看到明确的「Remote Login: On」或「Off」就是查到了;如果显示 On 而你根本没开过,那已经不只是自启烦人,而是安全问题。
用 systemsetup -getremotelogin 查看这台 Mac 是否允许其他机器通过 SSH 连入。
$ sudo systemsetup -getremotelogin把这个任务持久地关掉
删登录项只能管住应用。如果对方是 launchd 任务,真正管用的办法是写一条 disable 覆盖:launchd 会记住这个任务被关掉了,重启、以及厂商更新 plist 之后都依然生效——而 kill 进程、或者删一个安装程序会重新写回的 plist,都只是暂时的。改完立刻确认新状态,并把对应的 enable 命令记下来,方便反悔。只要任务不再显示为启用、重启后也没复活,这一步就算修好了。
launchctl enable/disable 会写入持久覆盖,使守护进程在重启和 plist 更新后仍保持关闭。
$ sudo launchctl disable system/com.apple.example.daemon
# Confirm current state:
sudo launchctl print-disabled system | grep example▾ 撤销
$ sudo launchctl enable system/com.apple.example.daemon用 launchctl print 确认它的真实状态
新的 print 子命令能一次性读出任务的真实状态——启用还是禁用、上次退出码、PID、启动参数——让你「确认修好了」,而不是「猜修好了」。以后真要主动重启某个任务,也是从这里下手。看到状态是 disabled(或者干脆没有在运行)、上次退出码不再是崩溃—重启的循环,就可以放心了。
现代 launchctl 用法——查看任意 launchd 任务的完整状态,并用真正有效的命令重启。
$ launchctl print gui/$(id -u)/com.apple.Finder如何确认已解决
登录项列表里那个名字消失了,launchctl print 显示任务为 disabled,完整重启后没有任何东西复活——进程、菜单栏图标、后台 CPU 占用都没有回来。
一键全部撤销
上面每一条命令都可以撤销。按此顺序执行即可全部还原。
$ sudo launchctl enable system/com.apple.example.daemon
osascript -e 'tell application "System Events" to delete login item "App Name"'执行前请先确认——部分步骤之间可能并非相互独立。
来源
- osascript — execute AppleScript and JavaScript (macOS man page)依据: Documents running AppleScript from the shell; System Events' login items class manages startup items.
- systemsetup — configure System Preferences machine-level settings (macOS man page)依据: Documents `systemsetup -getremotelogin` and `-setremotelogin on|off` for the Remote Login (SSH) service.
- launchctl - Interfaces with launchd to manage services依据: Documents `launchctl list`: 'List all of the jobs loaded in their own domain' with PID, status and label columns; run without sudo it lists your user domain.
- launchctl(1) man page依据: Man page for launchctl: the `list` subcommand prints the label, PID (or '-' if not running) and last exit status of each service in the caller's domain.
- plutil - Property List Utility依据: Documents the -p option which prints the property list in a human-readable form to the terminal.
- plutil(1) man page依据: The plutil man page describes -p: print the property list in a human-readable fashion (output format not designed for machine parsing).
最后验证: 2026-09-21