使用Python Docker SDK运行容器为何与命令行输出不同?
Docker SDK执行带sed的命令输出异常
在Shell终端执行以下命令,能正确提取出主机IP:
docker run --rm --net host busybox /bin/sh -c "ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p'"
输出结果:
10.0.2.15
但使用Python Docker SDK执行相同逻辑的命令时,输出异常:
import docker client = docker.from_env() print(client.containers.run('busybox',['/bin/sh','-c','ip route get 1 | sed -n \'s/^.*src \([0-9.]*\) .*$/\1/p\''],remove=True,network="host"))
得到的输出是:
b'\x01\n'
尝试转为ASCII编码后仍无有效可打印字符,添加stdout=True参数也无法解决问题。不过去掉sed过滤部分后,命令能正常输出完整路由信息:
print(client.containers.run('busybox',['/bin/sh','-c','ip route get 1'],remove=True,network="host"))
输出:
b'1.0.0.0 via 10.0.2.2 dev enp0s3 src 10.0.2.15 \n'
问题原因
异常的核心原因是Python字符串的转义机制:代码中的\1会被Python解析为ASCII控制字符SOH(对应\x01),而不是作为sed的反向引用参数传递给容器内的命令。
解决方法
有两种方式可以避免Python转义\1:
方案1:使用原始字符串
在命令字符串前添加r标记,让Python不对字符串内的转义字符进行解析:
import docker client = docker.from_env() # 使用原始字符串保留sed的反向引用格式 result = client.containers.run( 'busybox', ['/bin/sh','-c',r'ip route get 1 | sed -n \'s/^.*src \([0-9.]*\) .*$/\1/p\''], remove=True, network="host" ) # 解码为字符串并去除换行符 print(result.decode('utf-8').strip())
方案2:双重转义反斜杠
对\进行双重转义,让Python最终传递给sed的是\1:
import docker client = docker.from_env() # 用\\1替代\1,避免Python转义 result = client.containers.run( 'busybox', ['/bin/sh','-c','ip route get 1 | sed -n \'s/^.*src \([0-9.]*\) .*$/\\1/p\''], remove=True, network="host" ) # 解码为字符串并去除换行符 print(result.decode('utf-8').strip())
内容的提问来源于stack exchange,提问作者Dimitrios Desyllas
相关产品推荐
相关产品推荐

