Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.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 使用伪tty启动多个ssh会话时输出混乱(ssh断开连接/终止时需要远程进程退出)_Python_Ssh - Fatal编程技术网

Python 使用伪tty启动多个ssh会话时输出混乱(ssh断开连接/终止时需要远程进程退出)

Python 使用伪tty启动多个ssh会话时输出混乱(ssh断开连接/终止时需要远程进程退出),python,ssh,Python,Ssh,我有一个python脚本,它可以向服务器打开多个并发的伪tty ssh会话。我的问题是输出有误: for i in range(0, 3): subprocess.Popen( "ssh -tt -q myserver 'echo 11; echo 22; echo 33; echo 44;'", shell=True ) 输出: 11 22 33 44 11

我有一个python脚本,它可以向服务器打开多个并发的伪tty ssh会话。我的问题是输出有误:

for i in range(0, 3):
    subprocess.Popen(
        "ssh -tt -q myserver 'echo 11; echo 22; echo 33; echo 44;'",
        shell=True
    )
输出:

    11
      22
        33
          44
            11
    22
    33
    44
    11
    22
    33
    44
产量各不相同。有时它是有效的,但大多数时候我都会看到那些奇怪的凹痕。实际上,我希望启动远程python进程(一个Hocust load gen从属进程),但我已经将其简化为只使用echo

我尝试过的事情:

  • universal_newlines=True,bufsize=1(没有帮助)
  • remove-tt(修复了输出,但是如果python/ssh终止,远程进程不会立即消失,这是不希望的副作用)
  • 管道连接到cat-e以获取隐藏字符(用于调试):
我不确定这到底是python问题还是SSH问题。我猜我需要使用某种行缓冲,但我不知道如何:-/

我在MacOS Mojave上,我在iTerm2和Term上都试过,如果有必要的话

编辑:我不确定它是否相关,但是如果我确保python一直运行直到ssh会话终止(通过在脚本末尾添加time.sleep(10))的话,问题似乎会更频繁地出现

编辑2:我尝试了@FLemaitre的解决方案(没有明确使用-tt和killing),它在简单的情况下有效,但在繁殖蝗虫时无效:

proc = subprocess.Popen(
    "ssh servername 'locust --slave --master-port 7777 --no-web -f locustfile.py & read; kill $!'",
    shell=True,
    stdin=subprocess.PIPE,
)
time.sleep(10)
proc.kill()
proc.wait()

在远程服务器上,启动一个
bash-chocust--slave…
进程。当ssh被杀死时,它就会死亡,但蝗虫本身(上述过程的子进程)不会:-/

我用以下脚本系统地重现了这个问题:

import subprocess
import time

if __name__ == "__main__":
    for i in range(0, 10):
        proc = subprocess.Popen(
            "ssh -tt -q localhost 'echo 11; echo 22; echo 33; '",
            shell=True
        )
    time.sleep(4)
我认为这个问题与Python无关。这些带有伪TTY的多个ssh似乎相互冲突。最终,用于运行此脚本的终端也出现了故障(但它没有来源):

我查看了文档,这个-t选项似乎比您实际想要实现的要多得多。当我删除第二个t和-q选项时,我有时(不经常)会收到一条神秘的错误消息,说明出现了问题(但我不再设法重现它)。我和谷歌联系过,但没有多大成功。尽管如此,我相信这个选择是过分的,我更愿意关注永恒的过程。这一问题众所周知:

第二个答案是您的-tt选项,但最好的答案非常适合您的示例,并且更优越(使用-tt可以解决终止的ssh传播,但不能解决Python及其子进程之间的相同问题)。例如:

import subprocess
import time

if __name__ == "__main__":
    for i in range(0, 10):
        proc = subprocess.Popen(
            "ssh localhost 'sleep 90 & read ; kill $!'",
            shell=True,
            stdin=subprocess.PIPE
        )
    time.sleep(40)
使用此解决方案,stdin由所有参与者(python、python子流程、ssh流程、sleep流程)共享,链中任何一点的关闭都会被最终的业务流程检测到,从而触发正常的关闭

用蝗虫编辑: 我快速尝试了一下,问题是奴隶忽略了一个简单的“杀死”(看起来像是lucust方面的问题)。它似乎与“杀戮-9”一起工作:

import subprocess
import time

if __name__ == "__main__":
    for i in range(0, 2):
        proc = subprocess.Popen(
            "ssh localhost 'python -m locust --slave --no-web -f ~devsup/users/flemaitre/tmp/locust_config.py & read ; kill -9 $!'",
            shell=True,
            stdin=subprocess.PIPE
        )
    time.sleep(40)

你好谢谢你的建议-我想我已经接近解决这个问题了,但我仍然有问题。更新了我的问题,以反映我用一个使用蝗虫的示例编辑了我的答案(从他们的文档中提取了一个虚拟配置)。谢谢!我将尝试更新一点问题,以更好地符合答案!
import subprocess
import time

if __name__ == "__main__":
    for i in range(0, 10):
        proc = subprocess.Popen(
            "ssh localhost 'sleep 90 & read ; kill $!'",
            shell=True,
            stdin=subprocess.PIPE
        )
    time.sleep(40)
import subprocess
import time

if __name__ == "__main__":
    for i in range(0, 2):
        proc = subprocess.Popen(
            "ssh localhost 'python -m locust --slave --no-web -f ~devsup/users/flemaitre/tmp/locust_config.py & read ; kill -9 $!'",
            shell=True,
            stdin=subprocess.PIPE
        )
    time.sleep(40)