python - 如何通过子进程模块调用 ssh 以便它使用 SSH_ASKPASS 变量

标签 python ssh subprocess

我正在编写一个使用 SSH 命令的 GUI。我尝试使用 subprocess 模块调用 ssh 并设置 SSH_ASKPASS 环境变量,以便我的应用程序可以弹出一个窗口询问 SSH 密码。但是,我无法使用给定的 SSH_ASKPASS 命令让 ssh 读取密码:它总是在终端窗口中提示它,无论我如何设置 DISPLAY、SSH_ASKPASS、TERM 环境变量或我如何通过管道传输标准输入/输出。如何确保 ssh 与当前 TTY 分离并使用给定程序读取密码?

我的测试代码是:

#!/usr/bin/env python

import os
import subprocess

env = dict(os.environ)
env['DISPLAY'] = ':9999' # Fake value (trying in OS X and Windows)
del env['TERM']
env['SSH_ASKPASS'] = '/opt/local/libexec/git-core/git-gui--askpass'

p = subprocess.Popen(['ssh', '-T', '-v', 'user@myhost.com'],
    stdin=subprocess.PIPE,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE,
    env=env
)
p.communicate()

最佳答案

SSH 仅在进程真正脱离 TTY 时才使用 SSH_ASKPASS 变量(stdin 重定向和设置环境变量是不够的)。要从控制台分离进程,它应该 fork 并调用 os.setsid()。所以我找到的第一个解决方案是:

# Detach process
pid = os.fork()
if pid == 0:
    # Ensure that process is detached from TTY
    os.setsid()

    # call ssh from here
else:
    print "Waiting for ssh (pid %d)" % pid
    os.waitpid(pid, 0)    
    print "Done"

还有一种使用子进程模块的优雅方法:在 preexec_fn 参数中,我们可以传递一个 Python 函数,该函数在执行外部命令之前在子进程中调用。所以问题的解决方案是多一行:

env = {'SSH_ASKPASS':'/path/to/myprog', 'DISPLAY':':9999'}
p = subprocess.Popen(['ssh', '-T', '-v', 'user@myhost.com'],
    stdin=subprocess.PIPE,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE,
    env=env,
    preexec_fn=os.setsid
)

关于python - 如何通过子进程模块调用 ssh 以便它使用 SSH_ASKPASS 变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1787288/

相关文章:

python - 如何让 Popen 等待命令完成?

python - SPI_SETSCREENSAVETIMEOUT 不适用于使用 Python 和 ctypes 的 Windows 7

git - 标准错误 : Host key verification failed | GitHub | Jenkins | Windows

macos - OS X 上的 Bitbucket 权限被拒绝(公钥)Git

Python - 使用 Popen 中的列表作为命令

python - subprocess.check_call 出现奇怪的 python 错误

python - 使用python将xml节点添加到xml文件

python - 有效地从文件中读取主版本号

python - Flask 重定向具有相同的 url 和不同的主机?

linux - 我如何覆盖此文件的更改?