首页 > 解决方案 > Fabric 2.x:通过管道进行 tar 和 untar

问题描述

我想做这个shell脚本的等价物:

ssh visarend.solasistim.net tar -c /home/amoe/episodes | tar -vx -

但是使用 Fabric 2.x。这是我的尝试,但我不确定问题是什么。

remote_path = "/home/amoe/episodes"

c = fabric.Connection('visarend.solasistim.net')

with subprocess.Popen(['tar', '-vx'], stdin=subprocess.PIPE) as reader_proc:
    c.run(
        "tar -c %s" % (remote_path,),
        out_stream=reader_proc.stdin
    )

这给了我错误:

  File "/usr/local/lib/python3.5/dist-packages/invoke/runners.py", line 525, in write_our_output
    stream.write(encode_output(string, self.encoding))

TypeError: a bytes-like object is required, not 'str'

连同其他一些错误。我知道这可能是因为我从中获得的流reader_proc.stdin是字节流,而不是 unicode 流。但我不明白为什么run需要一个 unicode 流,或者正确的改变是什么才能让它工作。

标签: pythonsshtarinvokefabric

解决方案


我无法评论为什么fabric.Connection.run()假设执行的任务会产生文本流,但是,由于latin-1编码的存在,打包到文本流对象中的实际二进制流可以重新解释为二进制流而没有任何失真:

import fabric
import subprocess
from io import TextIOWrapper

remote_path = "/home/amoe/episodes"

c = fabric.Connection('visarend.solasistim.net')

with subprocess.Popen(['tar', '-vx'], stdin=subprocess.PIPE) as reader_proc:
    c.run(
        "tar -c %s" % (remote_path,),
        out_stream=TextIOWrapper(reader_proc.stdin, encoding='latin-1'),
        encoding='latin-1'
    )

推荐阅读