当我点击Docker remote API的端点时,例如在Bash中使用cUrl
,我得到一个流向控制台的响应,可能看起来像
[...]
{"stream":"\u001b[91m.\u001b[0m"}
{"stream":"\u001b[91m.. .....\u001b[0m"}
{"stream":"\u001b[91m.\u001b[0m"}
{"stream":"\u001b[91m.... ...\u001b[0m"}
{"stream":"\u001b[91m.....\u001b[0m"}
{"stream":"\u001b[91m.. .... 14.2M=0.5s\u001b[0m"}
{"stream":"\u001b[91m\n\n\u001b[0m"}
{"stream":"\u001b[91m2015-08-06 09:41:20 (10.1 MB/s) - ‘workspace.zip’ saved [5063084]\n\n\u001b[0m"}
{"stream":" ---\u003e aa6d979beeec\n"}
{"stream":"Removing intermediate container fa73eeb4531d\n"}
{"stream":"Step 3 : WORKDIR ./workspace\n"}
{"stream":" ---\u003e Running in 1dc8301bfd34\n"}
{"stream":" ---\u003e 4bddbc0282c9\n"}
{"stream":"Removing intermediate container 1dc8301bfd34\n"}
{"stream":"Step 4 : EXPOSE 8080\n"}
{"stream":" ---\u003e Running in 187a95569e84\n"}
{"stream":" ---\u003e b26c7b990996\n"}
{"stream":"Removing intermediate container 187a95569e84\n"}
{"stream":"Step 5 : CMD /bin/bash some_script.sh\n"}
{"stream":" ---\u003e Running in a5027b1082c3\n"}
{"stream":" ---\u003e 276ee1506ea0\n"}
{"stream":"Removing intermediate container a5027b1082c3\n"}
{"stream":"Successfully built 276ee1506ea0\n"}
[...]
使用所有转义和unicode字符阅读时非常烦人。如何在不转义所有特殊字符的情况下以更易读的形式在控制台上打印cUrl
响应?
This answer建议将响应传递给Python并使用其json模块,再次以UTF-8转储它。但是,在以下示例中使用它时,这是从本地Dockerfile构建Docker镜像的远程API方法:
tar -cvf - Dockerfile | \
curl --silent --show-error -X POST -H "Content-Type:application/tar" --data-binary @- \
"http://myDockerHost:4243/build?t=myRepo/myImage" | \
python -c 'import json, sys; sys.stdout.write(json.load(sys.stdin)[0].encode("utf-8"))'
然后我收到类似
的错误Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/usr/lib/python2.7/json/__init__.py", line 290, in load
**kw)
File "/usr/lib/python2.7/json/__init__.py", line 338, in loads
return _default_decoder.decode(s)
File "/usr/lib/python2.7/json/decoder.py", line 369, in decode
raise ValueError(errmsg("Extra data", s, end, len(s)))
ValueError: Extra data: line 2 column 1 - line 10 column 1 (char 48 - 764)
向上看,告诉我这是因为Python的json模块只能读取单个json字符串,而不能读取来自cUrl的流式多行响应。
还有什么办法可以解决这个问题?
答案 0 :(得分:1)
您的输入是多个 json文档 - 每行一个。分别将每行馈送到json.loads()
:
>>> print(json.loads(r'{"stream":"\u001b[91m.\u001b[0m"}')['stream'])
.
它在我的屏幕上显示为红点(由于ANSI escape sequences):
>>> json.loads(r'{"stream":"\u001b[91m.\u001b[0m"}')['stream']
u'\x1b[91m.\x1b[0m'
你可以use jq
, to work with json on the command line:
$ echo '{"stream":"\u001b[91m.\u001b[0m"}' | jq -r .stream
.
无关:不要编码为utf-8,而是直接打印Unicode。不要在脚本中硬编码环境的编码。如果要更改输出编码,请改为设置PYTHONIOENCODING
envvar。
答案 1 :(得分:1)
两种建议的方法都运作良好。在installing jq之后,它可以像这样使用:
tar -C ./ -cvf - Dockerfile | curl --silent --show-error -X POST -H "Content-Type:application/tar" --data-binary @- "$DOCKERHOST/build?t=repo/imageName" | jq -r .stream
使用Python代替它,分别处理流的每一行,它看起来像这样:
tar -C ./ -cvf - Dockerfile | curl --silent --show-error -X POST -H "Content-Type:application/tar" --data-binary @- "$DOCKERHOST/build?t=repo/imageName" | python -c 'import json, sys; [sys.stdout.write(json.loads(line)["stream"]) for line in sys.stdin]'
这两种解决方案都能提供所需的“可读性”。 stdout上的输出,例如
Dockerfile
Step 0 : FROM ubuntu
---> 91e54dfb1179
Step 1 : RUN apt-get update -y
---> Using cache
---> 211dc37ab584
Step 2 : RUN apt-get install -y default-jre
---> Using cache
---> 0045a653edb9
Successfully built 0045a653edb9