kdb set user/tests/hello world
#> Create a new key user/tests/hello with string "world"
kdb export user/tests/hello mmapstorage > test.mmap
创建了名为test.mmap
的文件,可以使用kdb import
重新导入该文件。
将创建一个名为test.mmap
的空文件,并显示以下消息(包括ENABLE_LOGGER
日志):
src/plugins/mmapstorage/mmapstorage.c:944:libelektra_mmapstorage_LTX_elektraPluginset: could not unlink
src/plugins/mmapstorage/mmapstorage.c:1003:libelektra_mmapstorage_LTX_elektraPluginset: strerror: Permission denied
Sorry, the error (#9) occurred ;(
Description: Insufficient permissions to open configuration file for writing. You might want to retry as root.
Reason: Permission denied
Ingroup: kdb
Module:
At: /home/klemens/data/bsc/libelektra/src/plugins/mmapstorage/mmapstorage.c:1004
Mountpoint: user
Configfile: /dev/stdout
〜工程时, kdb export
称为根〜。(编辑:见下面的评论) kdb export user/tests/hello mmapstorage test.mmap
也可以,但是是完全无证功能kdb export
。 因此,我们可能需要更好的错误消息和更新的文档。
感谢您尝试此操作以及此详细报告!
因此,我们可能需要更好的错误消息和更新的文档。
是的,我完全同意。
也许我们甚至应该在serializable
infos / status#666中有一个@mpranj还是有办法检测文件是否不可映射?它确实等同于被拒绝的权限吗?)
查看代码(和错误消息),我认为当前的问题是,在没有root用户访问权限的情况下,我们无法在stdout
上调用unlink
。 同样open
也可能会失败,因为stdout
已经打开。 stdout
是否可映射取决于我认为连接的stdout
。
使用fstat(fileno(stdout), &stat)
检查它是否为常规文件可能有效。 也许isatty(3)
也可以。
在任何情况下,我们都可以简单地检查输出文件是否为/dev/stdout
(或CON
的_WIN32
)并创建一个供mmap使用的临时文件,然后将其复制到stdout
。 这当然会慢一些,但是我们将保留管道输出kdb export
的可能性。
也许我们甚至应该在
serializable
infos / status#666中有一个
如果有的话,如果格式不是人类可读的,那么我的状态humanreadable
并拒绝导出到tty stdout。
当
kdb export
被称为root时有效。
我拿回去...不要尝试! 以root用户身份调用kdb export <something> mmapstorage
(即使重定向了stdout)也会破坏/dev/stdout
。 使用/dev/stdout
(例如,通过fopen
)在您的系统上不起作用,直到您使用sudo rm /dev/stdout && sudo ln -s /dev/stdout /proc/self/fd/1
重新创建默认的符号链接。
我认为最好的解决方案是kdb export
和kdb import
始终可用于临时文件。 那么kdb export
将与KDB更加相似。 这将解决未链接的问题(这对于mmaped文件是必需的。)缺点仅在于性能下降(需要复制所有内容),然后导入/导出将与所有存储插件一起使用,这是非常重要的。
我认为最好的解决方案是
kdb export
和kdb import
始终可用于临时文件。
我认为,如果需要,插件应自行创建临时文件。 这样,我们避免了直接输出到TTY的插件的性能损失。 AFAIK mmapstorage
当前是唯一不支持TTY的插件。 我们还可以添加一个简单的shell测试,以确保可以通过kdb export /some/key plugin > export.file
调用所有存储插件。 逻辑也更加独立,因为知道如何产生期望的输出确实是插件的责任。
另外,对于kdb import
,不需要临时文件,因为即使对TTY(如果您具有正确的权限),读取文件也应始终有效。
我认为,如果需要,插件应自行创建临时文件。
然后,插件(或更具体地说是mmap)将需要知道它是在KDB还是kdb export
。
@mpranj您的意见是什么? 可以在mmap插件中解决此问题吗?
这样,我们避免了直接输出到TTY的插件的性能损失。
在哪种情况下,性能下降会成为问题? 也许在每个测试用例的备份/还原中?
AFAIK mmapstorage是当前唯一不能与TTY一起使用的插件。
出口是的。 但是对于导入,我们有几个无效的插件。 如果插件使用fseek或类似工具,则显然无法工作,例如csvstorage或mozprefs。 (转储现在应该已修复)
我们还可以添加一个简单的shell测试,以确保可以通过kdb export / some / key plugin> export.file调用所有存储插件。
您是说tests / shell / check_export.sh第46行?
在哪种情况下,性能下降会成为问题?
实际上,可能永远不会。 只要您使用导出/导入的3个参数版本而不是管道。 请参阅下面的提案。
您是说tests / shell / check_export.sh第46行?
是的,但这是无效的,因为is_not_rw_storage
不起作用。 甚至dump
都不被视为存储插件。
我认为要快速轻松地解决此问题,我们应该执行以下操作:
include_common.sh.in
tests/shell/check_export.sh
修复is_not_rw_storage
,以便将来我们能发现类似的问题。kdb export
创建一个临时文件。 在kdbSet
调用中使用此文件,然后将其内容复制打印到stdout(在C ++中不应超过一两行)。kdb import
如果使用stdin,则创建一个临时文件。 将所有stdin复制到临时文件中,并使用该文件调用kdbGet
。kdb import
和kdb export
的文档以声明第三个参数存在。 还声明如果使用两个参数版本,我们将创建一个临时文件。PS。 这可能是good first issue
感谢您报告is_not_rw_storage损坏,我打开了#2423
抱歉,我已经离开了一个星期,所以我无法对其进行调查。
mmap错误消息可能会引起误解。 尝试映射非常规文件时, mmap()
失败,并带有EACCES
。 据我所知,它在stdout上不起作用。 如#2209中所述,它也不适用于管道。
从POSIX:
以下存储对象应支持mmap()函数:
- 常规文件
- [SHM]共享内存对象
- [TYM]类型的内存对象
至于mmapstorage中的解决方案,我们可以检查它是否是带有stat
的常规文件,然后:
我也欢迎其他解决方案。 上面的解决方案并没有改变很多毫微存储逻辑。 重新构造mmapstorage以直接使用管道或stdout对我来说没有太大意义。
感谢你的回复!
mmap错误消息可能会引起误解。
请改善错误消息。
据我所知,它在stdout上不起作用。 它也不适用于管道
请将该信息添加到错误消息中。
上面的解决方案并没有改变很多毫微存储逻辑。
由于您的插件是目前唯一受影响的插件,因此您有必要进行统计并根据需要复制所有内容。 然后,我们可以在不对框架进行较大更改的情况下解决此问题。
然后,我们可以在不对框架进行较大更改的情况下解决此问题。
我们还应该将手册页更新为kdb import
和kdb export
。 当前,他们没有提到不依赖于stdin / stdout的3个参数版本。
感谢您报告问题和提供意见!
不幸的是, strerror
打印这些误导性错误消息。 在这种情况下,我可以添加一个提示。
我将在本周的PR中进行要求的更改。
我们还应该更新kdb导入和kdb导出的手册页。 当前,他们没有提到不依赖于stdin / stdout的3个参数版本。
也许我们不需要参数来指定文件? 一旦kdb import/export
支持多个插件,该参数将发生冲突。
我将在本周的PR中进行要求的更改。
谢谢!
也许我们不需要参数来指定文件?
然后,我们必须在所有插件中支持stdin
和stdout
(重定向到常规文件)。 否则,它们将无法与kdb import/export
。 这对于mmapstorage
来说是明智的,因为它不可移植,但是其他可移植的插件(甚至是人类可读的)也可能需要常规文件(例如,如果他们使用fseek
)。
一旦
kdb import/export
支持多个插件,该参数将发生冲突。
当我们切换到使用elektraGetOpts
时,我们可以轻松地使用选项-i FILE, --input=FILE
, -o FILE, --ouput=FILE
elektraGetOpts
。
是的,我们可以添加-i,-o选项。 但是修复插件(或导入/导出框架),使stdin / stdout也可以正常工作。
要使用kdb export
解决此问题,
现在可以使用: kdb import user/tests/ mmapstorage < test.mmap
,
但这不是: cat test.mmap | kdb import user/tests/ mmapstorage
,因为mmap再次无法处理它。
为了使解决方案保持一致(从而与非常规文件完全兼容),也需要针对kdbGet()函数进行解决。 大约有三种解决方案:
这是可取的还是我们忽略了它?
我想我们现在可以忽略它,因为我们已经有了快速转储。 只需将其记录为不适合序列化即可。 现在,我们将重新修改导入/导出框架,然后我们将找到一个合适的解决方案。 @mpranj我
实际上,如果#2639解决此问题,然后@mpranj您为cat ...
问题创建一个新对象,则可能会更好。
我有一个非常不错的解决方案(使用realpath
和stat
),不幸的是,该解决方案在BSD上不起作用。 在其中投入更多时间是没有意义的。
我决定将其丢弃,因此不能使mmapstorage与非常规文件完全兼容。 它仅适用于kdb导入/导出。 通过检查文件是“ /dev/stdin
”还是“ /dev/stdout
”,新的解决方案将简单地检查是否使用了kdb import / export。 同样在quickdump
。
我有一个非常好的解决方案(使用realpath和stat),不幸的是,该解决方案无法在BSD上使用。
这是注释掉的解决方案吗?
在其中投入更多时间是没有意义的。
没错,框架应处理此问题。 我创建了#2640。
仅适用于kdb导入/导出
还可以使用cat | kdb import
变体吗?
在quickdump中也是如此。
区别在哪里?
可以将此代码移至导入/导出框架吗?
这是注释掉的解决方案吗?
我将其保留在历史记录中,但后来删除了这些行。 imho更好的解决方案一直持续到https://github.com/ElektraInitiative/libelektra/pull/2639/commits/a523f9b38b56687d532f5101c7ef44c078e2308d。 请注意,它在Linux上效果很好,但在BSD上效果不好。
我遇到的一个问题是stdin / stdout无法在BSD上打开()ed。 另一个是您确实必须使用realpath来对文件进行stat()并确定它是否为常规文件。 否则,stat只能为我解决一级符号链接。 对于我而言,这种方法在BSD上失败了,因为realpath以某种方式解析为不存在的文件。
还带猫| kdb导入变体?
是!
区别在哪里?
相关部分相同,对于造成的混乱,我们深表歉意。 我的意思是我们为/ dev / stdin strcmp而不是使用stat来确定它是否是常规文件。 这意味着如果我们使用/ dev / fd /,它仍然会失败
编辑:
可以将此代码移至导入/导出框架吗?
是的,我认为代码几乎完全在那里,但是我没有时间正确解决BSD问题。
最有用的评论
感谢你的回复!
请改善错误消息。
请将该信息添加到错误消息中。
由于您的插件是目前唯一受影响的插件,因此您有必要进行统计并根据需要复制所有内容。 然后,我们可以在不对框架进行较大更改的情况下解决此问题。