所以我写了一个命令行实用程序,遇到了一个我很好奇的问题。
该实用程序可以用文件参数调用,也可以从sys.stdin
读取。 最初我使用sys.stdin.isatty()
来判断数据是否在pipe道中,但是,如果我通过ssh server utility
程序远程调用实用ssh server utility
,则sys.stdin.isatty()
将返回false,尽pipe事实上,没有实际的数据被input。
作为一个解决方法,我正在使用-
作为强制从标准input读取的文件参数(例如: echo "data_here" | utility -f -
),但我很想知道是否有一个可靠的方法来区分pipe道从进程和pipe道获取数据,因为调用是通过ssh才打开的。
系统编程并不是我的专长,所以我很感激我能从你们那里得到任何帮助。
你可以通过检查你的环境来判断你是否通过SSH被调用。 如果通过SSH连接调用,则会设置环境变量SSH_CONNECTION
和SSH_CLIENT
。 你可以测试他们是否设置,说:
if "SSH_CONNECTION" in os.environ: # do something
另一个选择,如果你想坚持你的原始方法sys.stdin.isatty()
,将是为SSH连接分配一个伪tty。 通常情况下,SSH默认是这样做的,如果你只是SSH交互式会话,而不是如果你提供一个命令。 但是,通过传递-t
标志来提供命令时,可以强制执行此操作:
ssh -t server utility
不过,我会提醒你不要做这些。 正如你所看到的,试图检测你是否应该接受来自标准输入的输入,基于它是否是一个TTY可能会导致一些令人惊讶的行为。 如果他们想要一种方式来在调试时交互地提供输入到程序中,那么也可能会导致用户感到沮丧。
添加一个明确的参数的方法使得它更明确,并且不太让人惊讶你得到的行为。 一些实用程序也只是使用缺少任何文件参数意味着从标准输入读取,所以这也是一个不太令人吃惊的选择。
根据这个回答 ,应该声明SSH_CLIENT
或SSH_TTY
环境变量。 从这一点,下面的代码应该工作:
import os def running_ssh(): return 'SSH_CLIENT' in os.environ or 'SSH_TTY' in os.environ
一个更完整的例子将检查父进程,检查是否有任何sshd
这可能需要psutil模块。