电子应用程序无法仅访问一个网络驱动器上的文件
Electron app can't access files on only one network drive
我正在构建一个 Electron 应用程序来管理 NAS 上的照片集。该 NAS 有两个逻辑卷,名为“alpha”和“beta”。出于我想了解(并修复!)的原因,我的应用程序在尝试针对 Beta 版文件使用 运行 CLI 工具时会收到 ENOENT 错误,但当它针对 Alpha 版文件时 运行s CLI 工具则不会。此外, 允许对两个卷上的文件执行常规 FS 操作(例如 readdir、stat,甚至重命名)而不会出错。例如:应用程序首先了解测试版中的文件,因为它使用 find
扫描文件系统;扫描成功。
我正在使用 CLI 工具 exiftool
从所有这些文件中提取图像元数据(例如尺寸、捕获设备等)。这是我的应用 运行s 的命令,使用 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
}
如果我 运行 从命令行使用节点,无论目标文件在哪里,它都可以工作。如果 Electron 运行s 它,它将对 alpha 有效但对 beta 无效。如果我 运行 它来自 VS Code 中的集成终端,我拒绝了网络文件夹权限,它可以预见地抛出 alpha 和 beta;无论我使用 node 还是 Electron 都是如此,只要它来自 VS Code。
这是 console.log(error)
当 运行 作为打包的 Electron 应用程序时:
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'
]
}
我通过实验验证的事情:
- 如果我 运行 从命令行逐字输入命令,它就可以工作;所以,我的用户 可以 读取这些文件,
exiftool
也可以
- 将文件从 alpha 版移动到 beta 版(使用 Finder)会导致我的应用程序无法读取它,反之亦然
- 我的实现很好:如果我从终端使用节点到 运行 导入
readExif
的微型 test.js
,并手动提供测试版文件的路径,它作品
以上所有让我认为这是一个权限问题,但还有很多其他证据表明权限没问题:
- 在文件上使用
exiftool
之前,我的应用 stat
单独使用 FS.stat
获取文件的大小和时间戳;此统计调用适用于两个卷(注意:应用程序不会 运行 按直接顺序调用这些调用:今天 stat
文件,然后将文件添加到 exiftool
扫描队列可能会在几天后处理)
- 我第一次 运行 应用程序的每个新版本,MacOS 要求我重新确认授予网络文件夹权限;我总是授予他们
- 作为实验,我为我的应用程序提供了完全磁盘访问权限(它确实不需要),但这没有任何效果;我专门尝试过这个,因为我的终端应用程序 iTerm2 具有完整的磁盘访问权限,我认为这可能是与“生产”
不同的行为的原因
- 我的应用程序 UI 让我可以打开单个文件(使用
Electron.shell.openPath(PATH_TO_FILE)
),这对任一卷上的文件都成功
我也尽我所能检查基本文件权限,但我看不出有什么不同。这些卷由用户通过 Finder 安装,将它们放置在 /Volumes/alpha
和 /Volumes/beta
。挂载时,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 -> /
我也亲手检查过个别照片的烫发,但它们的权限是一样的。我已经使用 NAS 管理工具来验证我的用户帐户是否可以不受限制地访问这两个卷;确实如此,否则我的手动实验中的 none 会起作用。
并且,作为最后的努力,我将自己的 uid 和 gid 硬编码到 spawn 调用中,让 Electron 像我一样执行命令,但这也没有效果:我仍然得到 ENOENT
当 Electron 运行s exiftool
对抗任何处于测试阶段的文件时,仅仅是因为该文件处于测试阶段。 beta,再次,我有完全访问权限的网络卷,我已经多次授予该应用程序完全访问权限,该应用程序已经以其他几种方式良好地交互,并且在我认为的任何方面都与 alpha 没有明显不同尽管在两个设备上都有 root,但仍可以检测到。
我什至大喊“是的,那里是耳鼻喉科!”在它。我完全没有想法。
为什么这两种情况不同,我该如何解决?或者失败了,我该如何进一步调试它?
非常欢迎任何建议。
我的包版本:
- 电子:9.2
- 电子包装商:14.2
- 节点:14.13
电子运行宁Mac运行宁MacOS11.2.3
NAS 运行在 Linux.
的某种风格上使用 ext4 文件系统
指定有效命令的完整路径:
const process = ChildProcess.spawn(
'/usr/local/bin/exiftool',
['-json', '-n', PATH_TO_FILE]
)
我不知道为什么当目标处于 alpha 阶段时不需要这样做,但事实并非如此。
此版本适用于打包的应用程序。
我正在构建一个 Electron 应用程序来管理 NAS 上的照片集。该 NAS 有两个逻辑卷,名为“alpha”和“beta”。出于我想了解(并修复!)的原因,我的应用程序在尝试针对 Beta 版文件使用 运行 CLI 工具时会收到 ENOENT 错误,但当它针对 Alpha 版文件时 运行s CLI 工具则不会。此外, 允许对两个卷上的文件执行常规 FS 操作(例如 readdir、stat,甚至重命名)而不会出错。例如:应用程序首先了解测试版中的文件,因为它使用 find
扫描文件系统;扫描成功。
我正在使用 CLI 工具 exiftool
从所有这些文件中提取图像元数据(例如尺寸、捕获设备等)。这是我的应用 运行s 的命令,使用 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
}
如果我 运行 从命令行使用节点,无论目标文件在哪里,它都可以工作。如果 Electron 运行s 它,它将对 alpha 有效但对 beta 无效。如果我 运行 它来自 VS Code 中的集成终端,我拒绝了网络文件夹权限,它可以预见地抛出 alpha 和 beta;无论我使用 node 还是 Electron 都是如此,只要它来自 VS Code。
这是 console.log(error)
当 运行 作为打包的 Electron 应用程序时:
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'
]
}
我通过实验验证的事情:
- 如果我 运行 从命令行逐字输入命令,它就可以工作;所以,我的用户 可以 读取这些文件,
exiftool
也可以
- 将文件从 alpha 版移动到 beta 版(使用 Finder)会导致我的应用程序无法读取它,反之亦然
- 我的实现很好:如果我从终端使用节点到 运行 导入
readExif
的微型test.js
,并手动提供测试版文件的路径,它作品
以上所有让我认为这是一个权限问题,但还有很多其他证据表明权限没问题:
- 在文件上使用
exiftool
之前,我的应用stat
单独使用FS.stat
获取文件的大小和时间戳;此统计调用适用于两个卷(注意:应用程序不会 运行 按直接顺序调用这些调用:今天stat
文件,然后将文件添加到exiftool
扫描队列可能会在几天后处理) - 我第一次 运行 应用程序的每个新版本,MacOS 要求我重新确认授予网络文件夹权限;我总是授予他们
- 作为实验,我为我的应用程序提供了完全磁盘访问权限(它确实不需要),但这没有任何效果;我专门尝试过这个,因为我的终端应用程序 iTerm2 具有完整的磁盘访问权限,我认为这可能是与“生产” 不同的行为的原因
- 我的应用程序 UI 让我可以打开单个文件(使用
Electron.shell.openPath(PATH_TO_FILE)
),这对任一卷上的文件都成功
我也尽我所能检查基本文件权限,但我看不出有什么不同。这些卷由用户通过 Finder 安装,将它们放置在 /Volumes/alpha
和 /Volumes/beta
。挂载时,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 -> /
我也亲手检查过个别照片的烫发,但它们的权限是一样的。我已经使用 NAS 管理工具来验证我的用户帐户是否可以不受限制地访问这两个卷;确实如此,否则我的手动实验中的 none 会起作用。
并且,作为最后的努力,我将自己的 uid 和 gid 硬编码到 spawn 调用中,让 Electron 像我一样执行命令,但这也没有效果:我仍然得到 ENOENT
当 Electron 运行s exiftool
对抗任何处于测试阶段的文件时,仅仅是因为该文件处于测试阶段。 beta,再次,我有完全访问权限的网络卷,我已经多次授予该应用程序完全访问权限,该应用程序已经以其他几种方式良好地交互,并且在我认为的任何方面都与 alpha 没有明显不同尽管在两个设备上都有 root,但仍可以检测到。
我什至大喊“是的,那里是耳鼻喉科!”在它。我完全没有想法。
为什么这两种情况不同,我该如何解决?或者失败了,我该如何进一步调试它?
非常欢迎任何建议。
我的包版本:
- 电子:9.2
- 电子包装商:14.2
- 节点:14.13
电子运行宁Mac运行宁MacOS11.2.3
NAS 运行在 Linux.
的某种风格上使用 ext4 文件系统指定有效命令的完整路径:
const process = ChildProcess.spawn(
'/usr/local/bin/exiftool',
['-json', '-n', PATH_TO_FILE]
)
我不知道为什么当目标处于 alpha 阶段时不需要这样做,但事实并非如此。
此版本适用于打包的应用程序。