使用subprocess执行SSH sudo切换用户报错:需TTY才能运行sudo
问题分析与解决方案
我明白你遇到的麻烦了——在终端里能正常跑的SSH+sudo切换用户命令,放到subprocess里就各种出问题,一会儿切换失败,一会儿报需要tty的错。这其实是subprocess和终端环境的差异导致的,咱们一步步来解决:
为什么会报错?
终端里执行命令时,系统会自动分配一个tty(终端设备),而sudo默认配置要求必须有tty才能执行(这是一种安全限制)。但subprocess默认运行命令时不会分配伪终端,所以远程执行sudo时就触发了这个限制,抛出sudo: sorry, you must have a tty to run sudo的错误。
至于之前sudo -u userB -i没成功切换用户,大概率也是因为没有tty环境,-i参数模拟登录shell的过程没有完整执行,导致切换后的上下文没生效。
解决方案
方案1:给SSH命令强制分配tty(推荐)
在SSH命令里加上-t参数,这个参数会强制远程服务器为当前连接分配一个tty,刚好满足sudo的要求。把你的命令改成下面这样,再放到subprocess里执行:
import subprocess # 替换成你的远程主机地址、用户名 ssh_cmd = 'ssh userA@your_remote_host -t "sudo -u userB -i && whoami"' # 执行命令并捕获输出 result = subprocess.run( ssh_cmd, shell=True, capture_output=True, text=True ) print("输出结果:", result.stdout.strip()) if result.stderr: print("错误信息:", result.stderr.strip())
方案2:修改远程服务器的sudoers配置(不推荐,谨慎使用)
如果不想用-t参数,也可以修改远程服务器的sudoers配置,取消对userA的tty要求:
- 登录远程服务器,执行
sudo visudo编辑sudoers文件(一定要用visudo,避免语法错误锁死sudo) - 添加一行:
Defaults:userA !requiretty,意思是允许userA执行sudo时不需要tty - 保存退出后,再用subprocess执行原来的命令就不会报错了
不过这个方法会降低一点安全性,所以优先推荐方案1。
内容的提问来源于stack exchange,提问作者ArchieTiger
相关产品推荐
相关产品推荐

