[英]Electron app can't access files on only one network drive
I'm building an Electron app that manages a collection of photographs on an NAS.我正在构建一个 Electron 应用程序来管理 NAS 上的照片集合。 That NAS has two logical volumes, named "alpha" and "beta".
该 NAS 有两个逻辑卷,名为“alpha”和“beta”。 For reasons I want to understand (and fix,), my app gets an ENOENT error whenever it tries to run CLI tools against files on beta.
由于我想了解(并修复)的原因,我的应用程序在尝试针对 beta 上的文件运行 CLI 工具时会收到 ENOENT 错误。 but not when it runs CLI tools against alpha, Additionally, it is permitted to perform regular FS operations (eg readdir, stat, even rename) against files on both volumes without error.
但不是当它针对 alpha 运行 CLI 工具时,此外,它允许对两个卷上的文件执行常规 FS 操作(例如 readdir、stat 甚至重命名)而不会出错。 For example: the app first learns about the files on beta because it scans the filesystem using
find
;例如:应用程序首先了解 beta 版本的文件,因为它使用
find
扫描文件系统; that scan succeeds.该扫描成功。
I'm using the CLI tool exiftool
to extract image metadata from all these files (eg dimensions, capture device, etc).我正在使用 CLI 工具
exiftool
从所有这些文件(例如尺寸、捕获设备等)中提取图像元数据。 Here's the command my app runs, using child_process.spawn:这是我的应用程序使用 child_process.spawn 运行的命令:
# as a shell command
exiftool -json -n PATH_TO_FILE
// as a node module usable by Electron
const ChildProcess = require('child_process')
module.exports = async function readExif( PATH_TO_FILE ) {
if (typeof PATH_TO_FILE !== 'string') throw new TypeError('PATH_TO_FILE must be a string')
let exifStdout = await new Promise(( resolve, reject ) => {
let stdout = ''
let stderr = ''
const process = ChildProcess.spawn(
'exiftool',
['-json', '-n', PATH_TO_FILE],
{ uid: 501, gid: 20 }
)
process.on('error', ( error ) => reject(error)) // couldn't launch the process
process.stdout.on('data', ( data ) => stdout += data)
process.stderr.on('data', ( data ) => stderr += data)
process.on('close', () => stderr ? reject(stderr) : resolve(stdout))
})
let exifData = JSON.parse(exifStdout)
return exifData[0] // exiftool always returns an array; unwrap it so our return mirrors our input
}
If I run that using node from the command line, it works no matter where the target file is.如果我从命令行使用 node 运行它,无论目标文件在哪里,它都可以工作。 If Electron runs it, it'll work against alpha but throw against beta.
如果 Electron 运行它,它将对 alpha 有效,但对 beta 无效。 And if I run it from the integrated terminal inside VS Code, to which I have denied Network Folders permissions, it predictably throws against alpha and beta;
如果我从 VS Code 内的集成终端运行它,我拒绝了网络文件夹权限,它可以预见地抛出 alpha 和 beta ; that's true whether I use node or Electron, so long as it's from inside VS Code.
无论我使用 node 还是 Electron 都是如此,只要它来自 VS Code 内部。
Here's console.log(error)
when run as a packaged Electron app:这是作为打包的 Electron 应用程序运行时的
console.log(error)
:
Error: spawn exiftool ENOENT
at Process.ChildProcess._handle.onexit (internal/child_process.js:264:19)
at onErrorNT (internal/child_process.js:456:16)
at processTicksAndRejections (internal/process/task_queues.js:81:21) {
errno: 'ENOENT',
code: 'ENOENT',
syscall: 'spawn exiftool',
path: 'exiftool',
spawnargs: [
'-json',
'-n',
'/Volumes/beta/photographs/IMG_9999.jpg'
]
}
Things I've verified experimentally:我通过实验验证的事情:
exiftool
exiftool
也可以test.js
that imports readExif
, and manually provide the path to a file on beta, it worksreadExif
的小test.js
,并手动提供 beta 文件的路径,它就可以工作All of the above makes me think this is a permissions issue, but there are so many other proofs that permissions are fine:以上所有让我认为这是一个权限问题,但还有很多其他证据表明权限很好:
exiftool
on a file, my app stat
s the file individually using FS.stat
to get its size & timestamps;exiftool
之前,我的应用程序stat
使用FS.stat
单独获取文件的大小和时间戳; this stat call works against both volumes (note: the app doesn't run these calls in direct sequence: it stat
s the file today, then adds the file to the exiftool
scan queue which may be processed days later)stat
文件,然后将文件添加到exiftool
扫描队列中,可能会在几天后处理)Electron.shell.openPath(PATH_TO_FILE)
), which succeeds for files on either volumeElectron.shell.openPath(PATH_TO_FILE)
),这对于任一卷上的文件都成功I've also done what I can to inspect basic file permissions, but I can see no differences.我也尽我所能检查基本文件权限,但我看不出有什么区别。 These volumes get mounted by the user through the Finder, which places them at
/Volumes/alpha
and /Volumes/beta
.这些卷由用户通过 Finder 安装,将它们放置在
/Volumes/alpha
和/Volumes/beta
中。 While mounted, ls
shows that those two nodes have the same perms:挂载时,
ls
显示这两个节点具有相同的权限:
/Volumes $ ls -lht
total 64
drwx------ 1 Tom staff 16K Mar 25 18:46 alpha
drwx------ 1 Tom staff 16K Mar 25 02:00 beta
lrwxr-xr-x 1 root wheel 1B Dec 31 2019 Macintosh HD -> /
I've also hand-checked the perms on individual photos, but their permissions are the same.我还手动检查了单张照片的权限,但它们的权限是相同的。 I've used the NAS admin tools to verify that my user account has unrestricted access to both volumes;
我已经使用 NAS 管理工具来验证我的用户帐户是否可以不受限制地访问两个卷; it does, or none of my manual experiments would work.
确实如此,否则我的手动实验都行不通。
And, as a last-ditch effort, I hard-coded my own uid and gid into the spawn call to make Electron execute the command as myself, but that also had no effect: I still get ENOENT
when Electron runs exiftool
against any file on beta, simply because the file is on beta.而且,作为最后的努力,我将自己的 uid 和 gid 硬编码到 spawn 调用中,以使 Electron 像我自己一样执行命令,但这也没有效果:当 Electron 对上的任何文件运行
exiftool
时,我仍然得到ENOENT
测试版,仅仅是因为该文件是测试版。 beta, again, a network volume to which I have full access, to which I have repeatedly granted the app full access, that this app already interacts with fine in several other ways, and that is not visibly different from alpha in any way that I can detect despite having root on both devices.再次,我拥有完全访问权限的网络卷,我已多次授予应用程序完全访问权限,该应用程序已经以其他几种方式与之交互良好,并且在任何方面与 alpha 没有明显不同,我尽管在两台设备上都有 root 权限,但仍然可以检测到。
I have even shouted "Yes, there is ENT."我什至喊过“是的,有耳鼻喉科”。 at it.
在它。 I'm completely out of ideas.
我完全没有想法。
Why are these two scenarios different, and how can I fix it?为什么这两种情况不同,我该如何解决? Or failing that, how can I further debug it?
或者失败了,我该如何进一步调试它?
Any suggestions are very welcome.任何建议都非常受欢迎。
My package versions:我的 package 版本:
Electron running on a Mac running MacOS 11.2.3 Electron 在运行 MacOS 11.2.3 的 Mac 上运行
NAS is running an ext4 filesystem on some flavor of Linux. NAS 在 Linux 上运行 ext4 文件系统。
Specifying the full path of the command worked:指定命令的完整路径有效:
const process = ChildProcess.spawn(
'/usr/local/bin/exiftool',
['-json', '-n', PATH_TO_FILE]
)
I don't know why this isn't necessary when the target is on alpha, but it isn't.我不知道为什么当目标处于 alpha 时不需要这样做,但事实并非如此。
This version works from the packaged app.此版本适用于打包的应用程序。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.