如何检查Python脚本是否通过SSH远程调用

4

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

该实用程序可以使用文件参数调用,也可以从sys.stdin读取。最初,我使用sys.stdin.isatty()来确定数据是否通过管道传入,但是,我发现如果通过ssh server utility远程调用实用程序,sys.stdin.isatty()将返回false,尽管实际上没有数据被输送进来。

为了解决这个问题,我使用“-”作为文件参数来强制从stdin中读取(例如:echo "data_here" | utility -f -),但我很想知道是否有一种可靠的方法来区分获取来自进程的数据和仅因为通过ssh进行调用而打开的管道。

系统编程不是我的强项,所以非常感谢你们的帮助。


所有的管道都是一样的,所以不要认为你可以。你可能需要研究进程组和父进程——但这变得非常恶心了。 - Soren
2个回答

8

您可以通过检查环境变量来确定是否正在使用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检测是否应该从stdin接受输入会导致一些令人惊讶的行为。如果用户希望在调试程序时以交互方式提供输入,则还可能引起他们的不满。
添加明确的“-”参数方法更加明确和不令人惊讶,您将获得所需的行为。有些实用程序仅使用缺少任何文件参数来表示要从stdin读取,因此这也是一个不会令人惊讶的替代方案。

谢谢,这就是我想要的。看起来我将坚持我的解决方案。 - Laharah

2

根据这个答案中的说明,应该声明SSH_CLIENTSSH_TTY环境变量。在此基础上,以下代码可以工作:

import os

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

一个更完整的例子将检查父进程,以查看它们中是否有任何一个是sshd,这可能需要使用psutil模块。


如果这些变量未被设置,它将抛出一个异常,而非返回布尔值。 - Brian Campbell
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Laharah
谢谢@BrianCampbell。我已经更新了这个例子。在JavaScript领域花费太多时间了。 - Alex Taylor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接