当我运行ansible dnf模块时,通过logging
模块写入的消息dnf似乎无处可去。为什么会这样?
我有一个类似的调用链:
ansible(python3) - > ansible dnf module - > import dnf
... - > dnf plugin etckeeper-dnf
当前版本的etckeeper-dnf继续运行etckeeper
,使用os.system()
。所以它写入stdout和confuses ansible。我认为这是etckeeper-dnf中的错误。我相信ansible被允许使用import dnf
等。我遇到了另一个修复dnf插件,说dnf cli
对象不一定可用,这听起来像一个类似的场景。
Ansible想要能够控制stdout / stderr,而不是让它们受到库代码的干扰似乎是合理的。
所以我修补了etckeeper-dnf,我实际上将它的stdout + stderr用于python logging
模块。这正是我想要的。它修复了Ansible。并且dnf
命令仍然显示所有etckeeper消息。 (他们现在也被复制到/var/log/dnf.log
)。
但现在我有一个阅读理解问题。
当我运行ansible dnf模块时,通过logging
模块写入的消息dnf,包括来自etckeeper-dnf的消息,似乎没有去任何地方。
这不是我的改变,不是我的错,而且这不是我需要的。我甚至测试了如果etckeeper失败会发生什么:etckeeper-dnf只是继续,所以Ansible不会显示任何关于它的警告(除非我故意破坏Ansible)。
但我不禁对任何警告信息都会丢失的想法感到不安。
我确保使用dnfpluginscore.logger.error()
以及.info()
测试,但在任何一种情况下我都看不到消息。
logging
模块的默认配置是写入stderr。 dnf
模块没有做任何配置,除非你使用dnf.cli.BaseCli
。 Ansible模块dnf.py
不使用dnf.cli
中的任何内容,并且不对logging
做任何事情。基类AnsibleModule
也不使用python logging
;它有自己独立的.log()
方法。
那么为什么用.error()
写的消息不会出现在Ansible模块输出管道上,又会再次破坏Ansible?
最初的etckeeper-dnf
打破了Ansible,因为它写信给stdout。而我们确定python logging
模块写入stderr。
如果查看链接中的输出,Ansible会分隔module_stdout
和module_stderr
。通常它只是忽略module_stderr
;它只在MODULE FAILURE
的情况下显示它。 (虽然其他一些模块并不总是分开stdout / stderr,e.g. the Ansible script
module)。
所以我仍然认为在etckeeper-dnf中提议的更改是合理的。无论Ansible dnf模块是如何刻意设计的,依靠这种特定的行为似乎是合理的。 Ansible dnf模块中的未来更改不太可能破坏更改的代码。
我会注意到,当你点击MODULE FAILURE
时,module_stderr
只显示dnf的错误消息。您没有看到来自loglevel INFO或更低版本的任何消息,即dnf通常的非错误,非交互式输出。
(如果在使用etckeeper-dnf时将etckeeper故障视为致命,那么使用.info()
记录所有etckeeper输出可能不是一个好主意.Ansible会错过来自etckeeper的原始错误消息(并且错误消息不会记录在任何地方其他)。
但是,我在黑客等命令后测试系统返回EXIT_FAILURE
。 IIRC,dnf继续,不管任何etckeeper失败。总体效果是Ansible不会向您提供有关无法运行etckeeper的任何信息,无论我如何记录错误。一般来说,分别处理stdout
和stderr
消息更复杂,并且对消息的顺序做了奇怪的事情。所以我跟着K.I.S.S.原则:-)。
或者更普遍地说:
默认情况下,在loglevel INFO及以下写入的logging
消息将无处可寻。 loglevel警告及以上的消息将转到stderr。它们不会干扰正常的Ansible模块操作。在正常的Ansible模块操作中,即使这些消息也不会去任何地方。
如果有一个MODULE FAILURE
- 即模块崩溃或不生成Ansible可以按预期解析的JSON输出 - Ansible将显示module_stderr
,其中包括仅在loglevel WARNING或以上的logging
消息。