Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python子进程通信冻结_Python_Subprocess - Fatal编程技术网

python子进程通信冻结

python子进程通信冻结,python,subprocess,Python,Subprocess,我有以下挂起的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,

我有以下挂起的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)]
进程没有挂起,因此我很确定我误解了Communication认为进程已退出的方式


您知道我应该如何编写该命令,以便“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

-tt
选项分配tty,当
.communicate()
关闭
p.stdin
EOF
被忽略)时,该选项阻止子进程退出。这项工作:

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)
您可以使用--pure 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\u存在\u ok()
函数模拟:


我认为这会有所帮助,这是一个如何使用SSHSlight切线写入远程文件的示例,但您是否考虑过类似的方法,而不是使用SSH进程来实现这一点?这意味着您只需担心写入文件,而无需维护所有这些。感谢您的想法,但我正在尝试修补现有项目(ansible),对fabric的依赖性将不被接受。欢迎。但是是的,我想它可能不适合你的需要。Kobi K的答案对你有效吗?是的,Kobi K的答案似乎有效,但我不理解沟通的问题。我发现去掉“-tt”可以让事情正常工作;这对我来说是一个误解。对于需要使用python中的-tt选项运行ssh的情况,例如需要从stdin输入的交互式会话,甚至对于需要sudo pw的远程脚本,通过os.system()执行ssh脚本可以克服这个问题。相关帖子:但是为什么它与-tt+echo一起工作呢?你的解释似乎暗示它也不应该与echo一起工作@杰罗梅瓦格纳:
echo
不希望输入标准输入。尝试任何直到所有输入(stdin)被消耗后才退出的程序。虽然我也不完全理解。这可能是一个错误链中的某个地方关闭伪tty文件描述符。它取决于平台,例如:
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)