我有一个由Jenkins直接执行的Python程序。这个程序通过这个函数使用sh
库来执行一个停靠容器。请注意,此函数的一个重要特性是,它在执行时显示子进程的输出:
def run_command(*args, **kwargs):
# pass the parent stream 'tty' state to the command:
tty_in = sys.stdin.isatty()
tty_out = sys.stdout.isatty()
run = sh.Command(args[0])
try:
for line in run(args[1:], _err=sys.stdout, _iter=True, _tty_in=tty_in, _tty_out=tty_out):
sys.stdout.write(line)
sys.stdout.flush()
根据注释,docker run
需要一个TTY作为输入,因此关键字参数_tty_in
被设置为匹配stdin
的任何状态。然而,在Jenkins下运行时,它是False
。
然而,这个问题是关于来自容器内运行的程序的UTF8编码的错误消息,比如cp
。这会导致错误,例如:
cp: cannot stat \xe2\x80\x98filename...
事实证明,这三个字节是UTF-8编码,表示当区域设置为UTF-8时cp喜欢使用的特殊“引号”字符。如果我在直接运行cp
之前手动将语言环境设置为"C“,我可以看到它使用的是普通的ascii。
当我的Python脚本遇到这些错误时,它会死于以下代码:
Exception in thread Thread-10:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 763, in run
self.__target(*self.__args, **self.__kwargs)
File "/usr/local/lib/python2.7/dist-packages/sh.py", line 1484, in output_thread
done = stream.read()
File "/usr/local/lib/python2.7/dist-packages/sh.py", line 1974, in read
self.write_chunk(chunk)
File "/usr/local/lib/python2.7/dist-packages/sh.py", line 1949, in write_chunk
self.should_quit = self.process_chunk(chunk)
File "/usr/local/lib/python2.7/dist-packages/sh.py", line 1847, in process
handler.write(chunk)
File "/usr/lib/python2.7/codecs.py", line 351, in write
data, consumed = self.encode(object, self.errors)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 16: ordinal not in range(128)
这表明sh
模块期望从子进程获得ascii输出,但是正在接收UTF8,并且无法对其进行解码。
我发现了sh
的_encoding
和_decode_errors
选项,虽然这些选项似乎确实会影响cp
在直接由sh
运行时看到的区域设置,但对于在docker容器中运行的程序,它们似乎不能正确转换。然而,它确实允许程序继续,因为解码错误被跳过,而不是引发异常。
我更愿意更好地了解情况,并实施适当的解决方案。有人能一步一步地解释这里到底发生了什么吗(Jenkins > Python > sh > Docker > Bash)
我使用的是Python 2.7.12和Jenkins 2.33。
发布于 2017-10-29 19:50:26
在docker容器中运行python脚本时,我遇到了类似的问题。
我解决了以下过程。
(步骤1)在运行python命令之前,在Dockerfile中添加以下行
ENV LANG C.UTF-8
https://stackoverflow.com/questions/41991898
复制相似问题