ByteNoteByteNote
命令行查看和删掉 Mac 登录项
字

字节笔记本

2026年10月7日 · 约 10 分钟读完

命令行查看和删掉 Mac 登录项

API中转
¥120

Mac 开机变慢,先看登录之后自动打开了什么,而不是先去重装系统。会自动跑起来的东西不止系统设置里那一列登录项。Launch Agent、Launch Daemon、旧的 Startup Items,以及用户自己的 crontab,都会在开机或登录时插一脚。命令行能把这几处分开看,也能删掉某一个登录项,但名字必须和系统里的完全一致。

启动项分目录看,登录项单独读

先看清四类启动,再决定删谁

Launch Agent 和 Launch Daemon 是后台服务的主要入口。当前已经加载的,用:

bash
launchctl list

这一屏同时有系统级和当前用户的。想知道文件在哪,再列目录,不要从 launchctl list 的进程号反推路径:

bash
ls /Library/LaunchDaemons
ls /Library/LaunchAgents
ls ~/Library/LaunchAgents

系统级目录影响所有用户,用户目录只影响自己。看到不认识的 plist,先查它属于哪个应用,再决定卸载应用还是只移走 plist。直接删系统目录里的文件,应用更新时可能装回来,也可能让那个应用启动失败。

登录项是另一份名单,就是登录后要打开的那些应用。读取当前用户的登录项:

bash
osascript -e 'tell application "System Events" to get the name of every login item'

输出是一串用逗号隔开的应用名。后面的删除命令用的就是这些名字,大小写和空格都要一致,差一个字就会删不到。

更老的 /Library/StartupItems 在新系统上已经少见,仍可以看一眼目录在不在。定时任务用 crontab -l 看当前用户,sudo cat /etc/crontab 看系统范围。它们不是登录项,但会在你以为“登录项已经空了”的时候继续跑脚本。

自动登录的账户可以用 systemsetup -getautoLoginUser 看。这只说明开机后会不会自动进某个用户,不说明那个用户登录后又开了哪些应用。

删除和添加都走 osascript

系统设置里能点掉的登录项,命令行用 AppleScript 对 System Events 说同一句话。删除某一个名字:

bash
osascript -e 'tell application "System Events" to delete login item "应用名"'

应用名换成上一条 get the name 打出来的原文。要删多个,就写多行,或者放进一个脚本:

bash
#!/bin/bash
osascript -e 'tell application "System Events" to delete login item "应用名甲"'
osascript -e 'tell application "System Events" to delete login item "应用名乙"'
echo "指定的登录项已被删除。"

脚本保存之后 chmod +x,再执行。某一行名字对不上时,那一行失败,后面的行仍会继续,所以跑完再执行一次 get the name of every login item,用名单差集确认,而不是只看脚本有没有打印最后一句。

添加没有单独的专用命令,同样用 osascript。对话里的例子是把 Visual Studio Code 加进登录项,窗口不隐藏:

bash
osascript -e 'tell application "System Events" to make login item at end with properties {path:"/Applications/Visual Studio Code.app", hidden:false}'

path 是应用包的完整路径,hidden 为 true 时登录后不把窗口摆到前面。路径写错不会去搜索 /Applications,命令会失败,登录项名单也不会多出一行。

不要把登录项和 LaunchAgent 当成同一份名单

从登录项里删掉一个应用,不会自动卸掉它装在 ~/Library/LaunchAgents 里的 plist。有的工具两边都登记:登录项负责打开窗口,Agent 负责托盘或更新检查。只清一边,开机时另一个仍会起来。

反过来,launchctl list 里的系统守护进程也不要按登录项的方式去 osascript 删除。那份名单里没有它们的应用名。停用 Agent 要针对对应的 plist,用 launchctl 卸载或把 plist 移出目录,而不是对 System Events 说一个它不认识的名字。

看自动登录、看 crontab、看三个 Launch 目录、看登录项名单,这四步都做完,再谈开机慢是不是磁盘或内存的问题。很多时候名单里已经有一长串登录后要打开的应用,把不需要窗口的那些删掉,比改内核参数直接。

删完再读一遍名单

管理登录项的闭环就三步:osascript 读出准确名字,按原名删除或按包路径添加,然后再读一次名单。名字不完全一致,删除命令不会有一个明显的“已删除”界面,只会在下一次登录时发现那个应用还在。Launch Agent 的目录要单独看,它不出现在登录项那一串逗号里面。

删除必须用名单里的原名

名单太长时怎么删才不会误伤

登录项名单一长,就有人想写一个脚本把不认识的名字全删掉。不要这么做。get the name of every login item 打出来的是显示名,有的带空格,有的就是应用包名。脚本里每行写死一个你确认要去掉的名字,跑完再读一遍。对不上的那一行,AppleScript 会报找不到这个登录项,下一次登录时它还在。把报错当成“已经没有了”,是这条命令最常见的误读。

hidden 只影响添加时要不要隐藏窗口,不会把应用从后台服务里卸掉。一个应用可以没有登录项,但仍有用户级的 Launch Agent,登录后照样驻留。反过来,登录项里有它,Agent 目录里也可以没有对应 plist,它只是登录时被打开一次。所以优化开机要看两份清单,删完登录项再看 ~/Library/LaunchAgents 里有没有同名应用留下的文件。

系统级的 /Library/LaunchDaemons 和 /Library/LaunchAgents 需要管理员权限才改得动。那里的条目常常是驱动、安全和同步工具,不在“登录后弹出的窗口”这一类里。launchctl list 能看到它们已被加载,不代表你应该用删除登录项的脚本去碰它们。先在用户自己的登录项和用户自己的 Agent 目录里减,开机时间如果已经下来,就停手。

crontab 里的任务更隐蔽。crontab -l 为空,只说明当前用户没有。系统的 /etc/crontab 以及各用户的表要分开看。登录项脚本不会列出这些定时任务。开机变慢如果发生在登录界面出现之前,更要看 Daemon 和系统 crontab,而不是只看登录后才打开的应用。

systemsetup -getautoLoginUser 用来确认有没有自动登录。自动登录会把“登录项”提前到开机过程里,让人觉得是开机慢,其实是登录后的应用提前开了。关掉自动登录不需要删登录项。两件事在命令上也不共用一套语法。

旧目录 /Library/StartupItems 可以列一下。新系统上它经常不存在或是空的。空的就不要为了对称去创建。笔记里把它和 Launch 目录放在一起,是为了排查遗留,不是为了鼓励继续往里面放脚本。

最后仍用同一条 osascript 读回名单,和删除前的输出做对比。少掉的名字应该正好是脚本里写的那些。多删了就按应用路径再 make login item 加回去,path 必须指向 .app 包。加错路径不会自动纠正成另一个应用。 launchctl list 的每一行至少能看到三列里你真正用得上的信息:进程号、上次退出状态、以及服务标签。标签通常就是 plist 的文件名去掉扩展名。退出状态不是 0,说明它加载过但没留住,值得打开对应 plist 看程序路径是否还在。进程号是空的,很多 Agent 是按需启动,不代表坏了。不要因为这一列是空的就把 plist 删掉。

用户目录里的 Agent 和登录项可以同一天都清理,但命令不同。登录项用 System Events 的 delete login item,Agent 是把 plist 移走或让 launchctl 卸载这个标签。混用的结果是:脚本报成功,重启后菜单栏图标还在,因为你删的是登录项,留下的是 Agent。

添加登录项时 hidden:false 表示不隐藏。想让它登录后只在后台,把这个值改成 true,路径仍然指向同一个 .app。这不会减少它的内存占用,只是不把窗口带到最前。开机变慢如果来自这个应用本身要做的索引或同步,隐藏窗口解决不了,需要从登录项和 Agent 两边一起去掉。

读名单、改名单、再读名单,三次都用同一条 osascript。中间不要夹带会重启系统事件的操作。三条输出放在一起对,比凭记忆回忆“刚才删了谁”可靠。脚本末尾那句“已被删除”只说明脚本执行到了最后一行,不说明每一行 AppleScript 都成功。

相关文章

分享: