所以我正在编写一个命令行工具,而且我遇到了一个我很好奇的问题。
可以使用文件参数调用该实用程序,也可以从sys.stdin
读取该实用程序。最初我使用sys.stdin.isatty()
来确定数据是否被传输,但是,我发现如果我通过ssh server utility
远程调用该实用程序,sys.stdin.isatty()
将返回false,尽管事实是没有实际的数据输入。
作为一种解决方法,我使用-
作为文件参数来强制从标准输入读取(例如:echo "data_here" | utility -f -
),但我很想知道是否存在'一种可靠的方法来区分管道从进程获取数据与管道之间的区别,因为该调用是通过ssh进行的。
系统编程不是我的强项,所以我很感激能从你们那里得到任何帮助。
答案 0 :(得分:3)
您可以通过检查环境来判断是否通过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
但是,我会提醒您不要做其中任何一项。正如您所看到的,尝试检测是否应该接受来自stdin的输入,基于它是否是TTY可能会导致一些令人惊讶的行为。如果用户想要在调试时以交互方式为程序提供输入,也可能会引起用户的沮丧。
添加显式-
参数的方法使得它更加明确,并且不那么令人惊讶。一些实用程序也只是使用缺少任何文件参数来表示从stdin读取,因此这也是一个不太令人惊讶的替代方案。
答案 1 :(得分:2)
根据this answer,应声明SSH_CLIENT
或SSH_TTY
环境变量。从那以后,下面的代码应该可以工作:
import os
def running_ssh():
return 'SSH_CLIENT' in os.environ or 'SSH_TTY' in os.environ
更完整的示例将检查父进程,以检查它们中是否有sshd
可能需要psutil模块。