You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python调用subprocess使用sshpass时密码含特殊字符认证失败怎么办

问题场景

编写Python脚本实现从密码管理器API获取密码、自动创建SSH会话的功能,核心调用代码如下:

subprocess.call(['sshpass', '-p', password, 'ssh', '-l', username, url])

当密码包含特殊字符时(例如测试密码*jadKWI_3ekd}ad2+),脚本执行后SSH返回认证失败报错:

Permission denied, please try again.

直接在Shell中执行如下等价命令可以正常连接,无异常:

sshpass -p "*jadKWI_3ekd}ad2+" ssh url -l username

此前尝试使用Python原始字符串处理密码变量,没有解决问题。

问题根因
  • 原始字符串方案无效是因为这里不存在Python字符串转义问题:subprocess.call使用列表传参时默认shell=False,参数会直接传递给目标进程,不会经过Shell解析,*、}、+这类特殊字符不会被转义篡改。
  • 最高概率的诱因是从密码管理器API获取的password变量携带了不可见的首尾冗余字符:比如接口返回自带的尾部换行\n、回车符\r,这类字符会被sshpass计入密码内容,导致认证失败;手动在Shell执行命令时,引号包裹的密码不含这类冗余字符,因此可以正常连接。
  • 次要诱因是sshpass通过-p参数传递密码时,部分环境下存在参数解析边界问题,极端特殊字符组合可能出现截断。
解决方法
  • 首先清理密码变量的冗余字符:从API拿到密码后,先移除尾部的换行、回车符,如果密码首尾没有合法空格,可直接全量strip:
# 密码首尾无合法空格时使用
password = password.strip()

# 密码首尾可能存在合法空格时,仅移除换行回车
password = password.rstrip('\r\n')
  • 替换sshpass的密码传递方式,放弃命令行-p传参,改用环境变量传递密码,彻底规避参数解析问题,参考代码:
import os
import subprocess

# 复制当前环境变量,注入SSHPASS密码
run_env = os.environ.copy()
run_env['SSHPASS'] = password

subprocess.call(
    [
        'sshpass', '-e',
        'ssh',
        '-o', 'StrictHostKeyChecking=no',  # 可选,跳过首次连接主机密钥确认
        '-l', username,
        url
    ],
    env=run_env
)

sshpass -e参数会直接读取SSHPASS环境变量的值作为密码,全程不经过命令行参数解析,支持任意特殊字符的密码。

  • 如果上述调整后仍认证失败,可给ssh添加-tt参数强制分配伪终端,规避部分服务端因未检测到tty拒绝密码认证的问题:
subprocess.call(
    [
        'sshpass', '-e',
        'ssh', '-tt',
        '-o', 'StrictHostKeyChecking=no',
        '-l', username,
        url
    ],
    env=run_env
)

内容的提问来源于stack exchange,提问作者jozinko9

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 03:57:21