簡體   English   中英

使用偽 tty 啟動多個 ssh 會話時輸出亂碼(當 ssh 斷開連接/被殺死時,需要遠程進程退出)

[英]Output garbled when launching multiple ssh-sessions with pseudo-tty (need remote process to exit when ssh disconnects/is killed)

我有一個 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 進程(locust load gen slave),但我已將其簡化為僅使用 echo。

我嘗試過的事情:

  • Universal_newlines=True,bufsize=1(沒有幫助)
  • remove -tt(修復輸出,但如果 python/ssh 終止,遠程進程不會立即死亡,這會產生不希望的副作用)
  • 管道到 cat -e 以獲取隱藏字符(用於調試):
11^M$
     22^M$
          33^M$
               44^M$
                    11$
22$
33$
44$
11$
   22$
      33$
         44$

我不確定是 python 問題還是 SSH 問題。 我的猜測是我需要使用某種行緩沖,但我不知道如何:-/

我在 MacOS Mojave 上,如果重要的話,我已經在 iTerm2 和 Term 中嘗試過。

編輯:我不確定它是否相關,但是如果我確保 python 繼續運行直到 ssh 會話終止(通過在腳本末尾添加 time.sleep(10) ),問題似乎會更頻繁地發生

編輯 2:我嘗試了 @FLemaitre 的解決方案(不使用 -tt 並明確殺死),它在簡單的情況下有效,但在產卵蝗蟲時無效:

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 -c locust --slave ...進程啟動。 它在 ssh 被殺死時死亡,但 locust 本身(上述過程的子進程)不會:-/

我使用以下腳本系統地重現了該問題:

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 似乎相互沖突。 最終,用於運行此腳本的終端也被破壞了(而它不是來源):

>cat test2.py
import subprocess
                 import time
                            import atexit
... etc ...

我檢查了文檔,這個 -t 選項似乎比你實際想要實現的要多得多。 當我刪除第二個 t 和 -q 選項時,我有時(不經常)收到一條神秘的錯誤消息,指出出現問題(但我不再設法重現它)。 我用谷歌檢查過,但沒有太大成功。 不過,我相信這個選項是矯枉過正的,我寧願專注於不朽的過程。 這個問題是眾所周知的:

使用 bash 通過 ssh 啟動進程,然后在 sigint 上終止它

第二個答案是您的 -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 方面的問題)。 它似乎適用於“kill -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)

暫無
暫無

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

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