簡體   English   中英

python子進程通信凍結

[英]python subprocess communicate freezes

我有以下掛起的python代碼:

cmd = ["ssh", "-tt", "-vvv"] + self.common_args
cmd += [self.host]
cmd += ["cat > %s" % (out_path)]
p = subprocess.Popen(cmd, stdin=subprocess.PIPE,
                         stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = p.communicate(in_string)

它應該通過ssh將字符串(in_string)保存到遠程文件中。

文件已正確保存,但隨后進程掛起。 如果我使用

cmd += ["echo"] instead of
cmd += ["cat > %s" % (out_path)]

這個過程沒有掛起所以我很確定我誤解了溝通認為流程退出的方式。

你知道怎么寫這個命令所以“cat>文件”不能讓溝通掛起嗎?

-tt選項分配tty,當p.stdin.communicate()關閉p.stdin (忽略EOF .communicate()時,它會阻止子進程退出。 這有效:

import pipes
from subprocess import Popen, PIPE

cmd = ["ssh", self.host, "cat > " + pipes.quote(out_path)] # no '-tt'
p = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
stdout, stderr = p.communicate(in_string)

您可以使用paramiko - 純Python ssh庫,通過ssh將數據寫入遠程文件:

#!/usr/bin/env python
import os
import posixpath
import sys
from contextlib import closing

from paramiko import SSHConfig, SSHClient

hostname, out_path, in_string = sys.argv[1:] # get from command-line 

# load parameters to setup ssh connection
config = SSHConfig()
with open(os.path.expanduser('~/.ssh/config')) as config_file:
    config.parse(config_file)
d = config.lookup(hostname)

# connect
with closing(SSHClient()) as ssh:
    ssh.load_system_host_keys()
    ssh.connect(d['hostname'], username=d.get('user'))
    with closing(ssh.open_sftp()) as sftp:
        makedirs_exists_ok(sftp, posixpath.dirname(out_path))
        with sftp.open(out_path, 'wb') as remote_file:
            remote_file.write(in_string)

其中makedirs_exists_ok()函數模仿os.makedirs()

from functools import partial
from stat import S_ISDIR

def isdir(ftp, path):
    try:
        return S_ISDIR(ftp.stat(path).st_mode)
    except EnvironmentError:
        return None

def makedirs_exists_ok(ftp, path):
    def exists_ok(mkdir, name):
        """Don't raise an error if name is already a directory."""
        try:
            mkdir(name)
        except EnvironmentError:
            if not isdir(ftp, name):
                raise

    # from os.makedirs()
    head, tail = posixpath.split(path)
    if not tail:
        assert path.endswith(posixpath.sep)
        head, tail = posixpath.split(head)

    if head and tail and not isdir(ftp, head):
        exists_ok(partial(makedirs_exists_ok, ftp), head)  # recursive call

    # do create directory
    assert isdir(ftp, head)
    exists_ok(ftp.mkdir, path)

cat命令掛起是有意義的。 它正在等待EOF 我嘗試在字符串中發送EOF但無法使其工作。 在研究這個問題后,我找到了一個很好的模塊,用於簡化SSH對命令行任務的使用,例如你的cat示例。 它可能不是您的用例所需要的,但它確實可以滿足您的問題。

安裝fabric

pip install fabric

在一個名為fabfile.py的文件里面放

from fabric.api import run

def write_file(in_string, path):
    run('echo {} > {}'.format(in_string,path))

然后從命令提示符運行此命令,

fab -H username@host write_file:in_string=test,path=/path/to/file

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM