如何制作 python 脚本来给 sudo 提示我的密码

How to make python script to give sudo prompt my password

我正在 python 3.6 中编写脚本,该脚本使用许多 sudo 命令。作为我的用户,linux 机器上的脚本 运行s。该脚本正在创建一种报告,对许多服务器执行 ssh 和 运行ning 命令,如 lsof。
我需要一种方法让 python 在我使用 sudo 时随时提供我的密码。显然在第一次我会输入我的密码,它可以保存在脚本的内存中。 我一直在使用 python 子进程来 运行 我的 sudo 命令,例如:

cmd = SSH + '-t ' + source + " ' " + SUDO + "-k " + LSOF + "-p " + pid + " ' "
输出 = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True, universal_newlines=True)
(out,error) = output.communicate ()

可能吗?

限制条件:
不允许根工具包
运行 带有 sudo 的脚本不是一个选项,因为该脚本对许多服务器进行 ssh,出于安全原因,我不允许这样做。
无法更改 sudoers 文件中的任何内容。

因为你想给你的 python 脚本 sudo 密码,所以我认为最好创建一个新的用户组并将这个组设置到你的脚本文件中。您的脚本不再需要 sudo 密码(仍然具有 sudo 权限)。

注意:(我的答案是在Ubuntu 14.04上测试的。另一个Linux版本应该是一样的。

如果您以根用户身份登录,您可以随时通过键入以下内容来创建新用户:

adduser <newuser>

sudo adduser <newuser>

如果您的新用户应该能够以 root(管理)权限执行命令,您需要授予新用户 sudo.

的访问权限

我们可以使用 visudo 命令来完成此操作,该命令会在您的编辑器中打开相应的配置文件。这是进行这些更改的最安全方法。

visudo

sudo visudo

搜索如下所示的行:

root    ALL=(ALL:ALL) ALL

在此行下方,复制您在此处看到的格式,仅更改单词 "root" 以引用您想要授予 sudo 权限的新用户:

root      ALL=(ALL:ALL) ALL
<newuser> ALL=(ALL) NOPASSWD:ALL

使用 chown 更改您的 python 脚本的所有权。

sudo chown <newuser>: <python script>

之后你可以 运行 你的脚本在 sudo 权限下无需密码。

注意:(我建议你这样做是因为你想把你的sudo密码放到源代码中。但是,请小心你的脚本。它有更强大的...)

我建议您使用 Python 的 "pexpect" 模块,它就是这样做的。 它基于 "expect" 并用于自动与其他程序交互。 请注意,它不是 python 标准库的一部分,但如果您创建自己的 python 环境,则不一定需要 root 来安装它。

示例:

#import the pexpect module
import pexpect
# here you issue the command with "sudo"
child = pexpect.spawn('sudo /usr/sbin/lsof')
# it will prompt something like: "[sudo] password for < generic_user >:"
# you "expect" to receive a string containing keyword "password"
child.expect('password')
# if it's found, send the password
child.sendline('S3crEt.P4Ss')
# read the output
print(child.read())
# the end

可以在此处找到更多详细信息:

https://pexpect.readthedocs.io/en/stable/api/index.html

希望对您有所帮助!

我认为你应该使用 Paramiko 库来完成。确保在导入之前安装 paramiko。 Check this

下面是示例代码。使用前先测试一下。

$pip install paramiko

import paramiko
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
pid = 12345 # Modify this per your requirement
try:
    ssh_client.connect('source',username='user',password='pwd')
    stdin,stdout,stderr = ssh_client.exec_command('sudo -k lsof -p '+pid)
    stdin.write('pwd\n')
    stdin.flush()
    result = stdout.read.splitlines()
except paramiko.SSHException:
    print('Connection Failed')
    quit()

花了几个小时弄清楚如何使用子流程来完成它。

尽情享受吧:

import getpass
import subprocess

sudo_password = getpass.getpass(prompt='sudo password: ')
p = subprocess.Popen(['sudo', '-S', 'ls'], stderr=subprocess.PIPE, stdout=subprocess.PIPE,  stdin=subprocess.PIPE)

try:
    out, err = p.communicate(input=(sudo_password+'\n').encode(),timeout=5)

except subprocess.TimeoutExpired:
    p.kill()

以下答案执行三次尝试来验证访问:

  • 检查当前用户是否为root
  • 在不提供密码的情况下调用sudo
  • 询问用户密码并调用sudo

sudo 的调用调用 echo 命令并检查应该由 echo 打印的相同测试:单词 OK.

import os, subprocess
from getpass import getpass

def is_root():
    return os.geteuid() == 0

def test_sudo(pwd=""):
    args = "sudo -S echo OK".split()
    kwargs = dict(stdout=subprocess.PIPE,
                  encoding="ascii")
    if pwd:
        kwargs.update(input=pwd)
    cmd = subprocess.run(args, **kwargs)
    return ("OK" in cmd.stdout)

def prompt_sudo():
    ok = is_root() or test_sudo()
    if not ok:
        pwd = getpass("password: ")
        ok  = test_sudo(pwd)
    return ok

if prompt_sudo():
    print("Access granted !")
else:
    print("Access denied !")