如何检查 python 脚本是否正在通过 ssh 远程调用

how to check if python script is being called remotely via ssh

所以我正在编写一个命令行实用程序,我 运行 遇到了一个我很好奇的问题。

该实用程序可以使用文件参数调用,也可以从 sys.stdin 中读取。最初我使用 sys.stdin.isatty() 来确定是否正在通过管道输入数据,但是,我发现如果我通过 ssh server utility 远程调用该实用程序,sys.stdin.isatty() 将 return 为假,尽管没有实际数据通过管道输入。

作为一种变通方法,我使用 - 作为强制从标准输入读取的文件参数(例如:echo "data_here" | utility -f -),但我很想知道是否有可靠的方法来判断从进程获取数据的管道与仅打开的管道之间的区别,因为调用是通过 ssh 进行的。

系统编程不是我的强项,所以我很感激能从你们那里得到的任何帮助。

根据 this answer,应该声明 SSH_CLIENTSSH_TTY 环境变量。由此,以下代码应该可以工作:

import os

def running_ssh():
    return 'SSH_CLIENT' in os.environ or 'SSH_TTY' in os.environ

一个更完整的示例将检查父进程以检查它们是否是 sshd,这可能需要 psutil 模块。

您可以通过检查您的环境来判断是否通过 SSH 调用您。如果您通过 SSH 连接被调用,环境变量 SSH_CONNECTIONSSH_CLIENT 将被设置。您可以测试它们是否设置为:

if "SSH_CONNECTION" in os.environ:
    # do something

另一个选择,如果您只想坚持原来的 sys.stdin.isatty() 方法,就是为 SSH 连接分配一个伪终端。通常,如果您只是通过 SSH 进入交互式会话,SSH 默认会执行此操作,但如果您提供命令则不会。但是,您可以通过传递 -t 标志在提供命令时强制它这样做:

ssh -t server utility

但是,我要提醒您不要做任何这些事情。如您所见,尝试根据标准输入是否是 TTY 来检测您是否应该接受输入可能会导致一些令人惊讶的行为。如果用户想要一种在调试某些内容时以交互方式向您的程序提供输入的方法,这也可能会导致用户感到沮丧。

添加显式 - 参数的方法使您获得的行为更加明确且不那么令人惊讶。一些实用程序也只是使用缺少任何文件参数来表示从标准输入读取,因此这也是一个不那么令人惊讶的选择。