在终端中通过 ssh 启动 python 程序并读取 stdin

在终端中通过 ssh 启动 python 程序并读取 stdin

我有这个小 python3 脚本test.py

import sys

print('test1')
test1 = sys.stdin.read()
print('test2')
test2 = sys.stdin.read()

print(test1)
print(test2)

我希望通过 ssh 远程运行这个脚本,如下所示:

ssh srvid 'cd; python3 test.py'

我希望程序打印test1,然后等待输入,然后打印test2并再次等待输入。

但行为略有不同:

ssh srvid 'cd; python3 test.py'
hell
test1
test2
hell

程序首先等待输入。我输入hell后按下回车键,然后按下 ctr+d 来结束输入。脚本没有等待第二次输入,而是打印出test1test2

看起来,stdin / stdout 不知何故被阻塞了。

我在 bash 中尝试了同样的例子:

#!/bin/bash

echo "Hello world";
read test;
echo "helloworld 2";
read test2;
echo $test;
echo $test2;

当我通过 ssh 调用该脚本时,一切都按我预期的方式进行。

有人能帮助我吗?

答案1

这是由于libc 约定用于 stdio 缓冲。如果 stdout 是 tty,则通常采用行缓冲;否则采用完全缓冲。

正如其他人所建议的那样,将 -t 标志传递给 ssh 会强制进行伪tty分配,结果您会得到行缓冲。

但是,您也可以明确刷新 stdout 以获得类似的结果,如下所示:

import sys

print('test1')
sys.stdout.flush()
test1 = sys.stdin.readline() # ctrl+d and .read() effectively closes 
print('test2')               # stdin for the duration
sys.stdout.flush()
test2 = sys.stdin.readline()

print(test1)
print(test2)
# flushing happens implicitly when the stream is closed

另一个选择是使用标志以完全非缓冲模式运行 Python -u,如下所示

ssh srvid 'cd; python3 -u test.py'

其他解决方法可以参见这个 stackoverflow 问题


程序首先等待输入。我输入hell后按下回车键,然后按下 ctr+d 来结束输入。脚本没有等待第二次输入,而是打印出test1test2

我很确定脚本没有在第二次输入时停止,因为你在第一次输入时向它发送了 EOF。


无论如何,我可能会以这种方式编写 python,除非您需要多行输入。在我看来,它与您的 bash 示例更接近。

#!/usr/bin/env python3

print('test1')
test1 = input() # raw_input() in python 2.x
print('test2')         
test2 = input()

print(test1)
print(test2)

相关内容