macOS命令行killed问题解决
问题的发生
起初,是作者在正常的牛马生活中,完成了一个需求,正常的按流程进行工作,突然间发现 golangci-lint
版本落后了,需要更新。遂使用下面的命令重装 golangci-lint
:
rm $(which golangci-lint) # 删除现有的 golangci-lint
go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.54.2 # 编译安装 1.54.2 版本,它支持 go1.21
作者以为就如同往常一样,静待编译完成后就可以高兴使用 golangci-lint
来屎里淘金时,变故发生了(隐藏了一些无关紧要的信息):
~/.../project on branches/branch *4 !4 ?2 at 13:53:09
❯ golangci-lint version
[1] 2221 killed golangci-lint version
并且附加的表现是,无论是使用任何参数(正确的或者不正确的),都是上面的结果。
问题的探索
出现了上面的情况,遂怀疑是不是出门没看黄历,权限不够,但是加了 sudo
执行依旧如此。此时就很显然不是正常的问题了。
第一反应是去拷打 GPT 或者 GLM,它也回答了些无关痛痒的方法,即 重试重启重装 三件套,但是并不能解决问题。只能自己去探索到底发生什么事情了。不难观察到,这是被系统 killed
掉的状态,下意识就是去检查被 killed
的系统日志信息:
~/.../project on branches/branch *4 !4 ?2 at 13:58:05
❯ sudo dmesg | grep -i kill >> kill.out
输出如下:
[ 345.501730]: igmp_input_v2_report: process v2 report on ifp en0CODE SIGNING: cs_invalid_page(0x104114000): p=3004[golangci-lint] final status 0x23020200, denying page sending SIGKILL
[ 345.704416]: igmp_input_v2_report: process v2 report on ifp en0igmp_input_v2_report: process v2 report on ifp en0igmp_input_v2_report: process v2 report on ifp en0CODE SIGNING: cs_invalid_page(0x10480c000): p=3010[golangci-lint] final status 0x23020200, denying page sending SIGKILL
[ 346.528375]: igmp_input_v2_report: process v2 report on ifp en0CODE SIGNING: cs_invalid_page(0x104518000): p=3016[golangci-lint] final status 0x23020200, denying page sending SIGKILL
[ 347.469905]: CODE SIGNING: cs_invalid_page(0x10014c000): p=3022[golangci-lint] final status 0x23020200, denying page sending SIGKILL
[ 347.653755]: igmp_input_v2_report: process v2 report on ifp en0igmp_input_v2_report: process v2 report on ifp en0CODE SIGNING: cs_invalid_page(0x10452c000): p=3026[golangci-lint] final status 0x23020200, denying page sending SIGKILL
相信各位聪明的读者是看懂了吧,是吧!作者在拷打了一下 GPT 后,得到的提示信息如下:
从你的日志输出来看,golangci-lint 被 macOS 的代码签名机制(Code Signing)所阻止。这通常是因为 macOS 检测到某些代码页面无效,并因此终止了进程。
这似乎是我们的老熟人了,我的工作电脑并没有关闭 SIP 并且允许未经签名的代码运行,现在看起来似乎得退让一下了。可以用烂熟于心的下面的指令启用系统隐藏的「允许所有程序在我的电脑上运行」选项。但是随着回车的敲下,输出的内容并不如作者心中所想:
~/.../project on branches/branch *4 !4 ?2 at 13:58:30
❯ sudo spctl --master-disable
This operation is no longer supported. To disable the assessment subsystem, please use configuration profiles.
此时大大的问号从作者小小的脑袋中升起,这又是什么东西,祖宗之法失效了,再去拷打 GPT:
在 macOS 的最新版本中,Apple 已经禁用了通过 spctl 命令来禁用 Gatekeeper 的方法。你可以使用配置描述文件(Configuration Profiles)来管理这些设置。以下是如何创建和部署一个配置文件来禁用 Gatekeeper:
你需要创建一个 .mobileconfig 文件来配置 Gatekeeper 设置。
- 打开文本编辑器并创建一个新的文件,内容如下:
省略1万字
- 保存文件为 GatekeeperConfig.mobileconfig。
省略给 golangci-lint 提 issue/pr 的不过脑子的建议
看着就头疼,遂换一个思路,既然是签名问题,那么我来给它签不就完了吗:
~/.../project on branches/branch *4 !4 ?2 at 14:00:05
❯ sudo codesign --force --deep --sign - $(which golangci-lint)
.../go/bin/golangci-lint: replacing existing signature
随着回车的敲下,然后重新执行 golangci-lint
命令,您猜怎么着,问题解决了。这一问题困扰了许久,而且有预感后续也会遇到,遂记录下来供自己/互联网上有同样疑问的朋友参考。
总结
原因
- macOS 安全策略升级:新版 macOS 强化了代码签名验证机制,未签名/签名无效的二进制文件会被强制终止
- Go 编译特性:
go install
生成的二进制文件默认无有效签名(与 Homebrew 等包管理器不同) - 配置方式变更:Apple 已弃用 spctl 的全局禁用功能,转向更严格的配置描述文件管理
解决方案
通过强制代码签名绕过验证:
sudo codesign --force --deep --sign - $(which golangci-lint)