前几天我将我的 mac mini(这是我娱乐中心的一部分)更新到了索诺玛。 早就该这么做了。 我想以前还是在 High Sierra。 我在那台计算机上有一个 Node-RED 实例(在版本 v1.2.7 上更新也落后,但我怀疑这与版本无关 - 如果拥有最新版本的人可以运行我的 MRE 并确认,那就太好了这是最新 NR 中的一个问题...)。
更新后,识别提醒应用程序数据库正确 sqlite 文件的脚本(以及执行类似操作的其他脚本)不再正常工作。 我将问题归结为
bsd_glob
子例程的不同行为,该子例程是 File::Glob ':glob'
perl 模块的一部分。
问题是,它在命令行上按预期工作(即使从其他脚本调用(例如我在工作中调用它的 Apple 脚本和 SLURM 脚本))。 但更新到 Sonoma 后,它与 Node-RED 执行节点的行为不再相同,该节点不返回任何文件匹配。
这是一个 MRE 示例,运行自...
命令行返回3个文件:
[golrath:~] robleach% perl -e 'use File::Glob ":glob";print(bsd_glob("/Users/robleach/Library/Group Containers/group.com.apple.reminders/Container_v1/Stores/Data-*-*.sqlite",GLOB_CSH),"\n")'
/Users/robleach/Library/Group Containers/group.com.apple.reminders/Container_v1/Stores/Data-A0D24954-1339-494B-9E7D-9D0911C096F8.sqlite/Users/robleach/Library/Group Containers/group.com.apple.reminders/Container_v1/Stores/Data-B826F8F1-0153-4318-8666-F1C8EBBFCE96.sqlite/Users/robleach/Library/Group Containers/group.com.apple.reminders/Container_v1/Stores/Data-D8328338-F382-4E34-8C39-E1DC35D60A32.sqlite
并通过 Node-RED 执行节点,返回 0 个文件:
我的第一个想法是 perl 可执行文件、模块甚至 csh 版本一定有所不同,但我确认它们在命令行和 Node-RED 之间都是相同的:
命令行:
[golrath:~] robleach% perl -e 'use File::Glob ":glob";print("$File::Glob::VERSION\n")'
1.37
[golrath:~] robleach% csh --version
tcsh 6.21.00 (Astron) 2019-05-08 (x86_64-apple-darwin) options wide,nls,dl,bye,al,kan,sm,rh,color,filec
[golrath:~] robleach% tcsh --version
tcsh 6.21.00 (Astron) 2019-05-08 (x86_64-apple-darwin) options wide,nls,dl,bye,al,kan,sm,rh,color,filec
[golrath:~] robleach% perl --version
[golrath:~] robleach% which perl
/Users/robleach/perl5/perlbrew/perls/perl-5.36.1/bin/perl
[golrath:~] robleach% ls -halF /usr/local/bin/perl
lrwxr-xr-x 1 robleach admin 57B Jul 22 09:13 /usr/local/bin/perl@ -> /Users/robleach/perl5/perlbrew/perls/perl-5.36.1/bin/perl
唯一的区别是路径中的 perl 软链接。 这可能是导致行为差异的原因吗?我无法想象怎么会这样......
@ikegami(以及 perlmonks 上的用户 Corion)确定了导致行为差异的问题。 我不确定他们是如何得出这个结论的(也许是预感?),但我通过简单地在 Node-RED 中执行
ls
来证实了这个理论,这导致了 Operation not permitted
错误(我没有从命令行 [可能是因为终端应用程序被授予“完全磁盘访问权限”=在隐私和安全设置中])。
问题困扰我的原因是因为对
File::Glob::bsd_glob
的调用默默失败,即不会产生 Operation not permitted
错误。
错误从路径中的此时开始发生:
/Users/robleach/Library/Group Containers/group.com.apple.reminders
(及其下面的所有内容)。
我还在苹果开发者论坛上发布了有关此问题的文章,并且那里的开发者给了我非常丰富的回复,他将我链接到了有关苹果自定义权限结构的解释器(您可能需要拥有一个[免费]苹果开发者帐户查看)位于典型的 bsd 权限架构之上。 引用那篇文章:
现代版本的 macOS 有四种不同的文件系统权限机制:
- 传统 BSD 权限
- 访问控制列表 (ACL)
- 应用程序沙箱
- 强制访问控制(MAC)
前两个是很久以前引入的,很少让人们绊倒。后两个更新、更复杂并且特定于 macOS,因此是一些混乱的根源。这篇文章是我试图澄清这一点的尝试。
这篇文章详细介绍了最后两个值得一读的细节,但可以说,解决方案是找到父进程并授予其磁盘访问权限。
当然,我授予访问权限并为我解决问题的流程是
/usr/local/bin/node
。 我不需要重新启动或重新启动任何已处理的操作。 一旦我授予访问权限,通过 Node-RED 运行的命令就开始工作,没有错误。
我授予了对节点的完整磁盘访问权限,尽管它相当严厉,并且我打算在今天晚些时候有机会访问我需要的特定目录时更改它。 尽管我不知道是否或如何将其限制为仅 Node-RED(可能不是)。 因此,任何/每个
Node.js
脚本现在都可以访问系统文件,因此请自行承担风险。
为了完成这个答案,以下是如何在 MacOS Sonoma 中授予对
Node.js
的完全访问权限:
完成此操作后,您应该立即能够访问 Node-RED 中之前默默失败或导致
Operation not permitted
错误的文件。
我相信传统的读/写 bsd 权限仍然会限制访问敏感系统文件的尝试,但我尚未确认这一点。