subprocess时报sudo: sorry, you must have a tty to run sudo

1.一般我们在python代码中要执行Linux命令行时,一般都会使用subprocess这个模块来做。
2.但是我们用subprocess执行大多数命令都是可以直接挂在后台执行的,也就是它的stdin参数可以直接指定一个管道subprocess.PIPE,也就是如下这样:

import subprocess
p = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

3.但是我们执行某些命令的时候,上面那句代码会提示:sudo: sorry, you must have a tty to run sudo,即我们的命令是sudo来运行的时候,有些操作系统上是运行直接后台直接运行的(如suse Linux,suse默认运行后台运行sudo),而有些Linux上则必须要我们开一个tty终端来运行(例如centos6、7,默认运行后台不允许运行sudo)。
4.当我们遇到了在后台不运行sudo时,也就是subprocess时提示sudo: sorry, you must have a tty to run sudo,这个时候我们有两种解决方案:

  • 我们可以去修改/etc/sudoers这个文件,将“Defaults requiretty”注释掉,此操作不需要重启服务,之后使用subprocess执行sudo时即可正常执行了
  • 上面那种做法或许只适合平时我们自己实验时使用,真正的生产环境中,一般不建议这么操作,这个时候我们可以使用python给我提供的一个名叫pty的模块来模拟开一个tty终端:
master, slave = pty.openpty()
proc = subprocess.Popen(cmd,
                        stdin=slave,
                        stdout=subprocess.PIPE,
                        stderr=subprocess.PIPE,
                        preexec_fn=os.setsid,
                        close_fds=True,
                        shell=True)
os.close(slave)

5.可以通过查看pty模块的源码可以知道其实pty中的openpty这个方法,底层是对os的openpty的一个扩展

def openpty():
    """openpty() -> (master_fd, slave_fd)
    Open a pty master/slave pair, using os.openpty() if possible."""

    try:
        return os.openpty()
    except (AttributeError, OSError):
        pass
    master_fd, slave_name = _open_terminal()
    slave_fd = slave_open(slave_name)
    return master_fd, slave_fd

参考1
参考2
参考3

猜你喜欢

转载自blog.csdn.net/mingtiannihaoabc/article/details/103796155