[英]How to change a Linux user password from python
我在从 python 更改 Linux 用户的密码时遇到问题。 我已经尝试了很多事情,但我无法解决问题,这是我已经尝试过的事情的示例:
sudo_password 是 sudo 的密码,sudo_command 是我希望系统运行的命令,user 是从 List 中获取的,是我想为其更改密码的用户,newpass 是我想分配给“用户”的通行证
user = list.get(ANCHOR)
sudo_command = 'passwd'
f = open("passwordusu.tmp", "w")
f.write("%s\n%s" % (newpass, newpass))
f.close()
A=os.system('echo -e %s|sudo -S %s < %s %s' % (sudo_password, sudo_command,'passwordusu.tmp', user))
print A
windowpass.destroy()
'A' 是执行 os.system 的返回值,在本例中为 256。我也试过
A=os.system('echo %s|sudo -S %s < %s %s' % (sudo_password, sudo_command,'passwordusu.tmp', user))
但它返回相同的错误代码。 我用“passwd”命令尝试了其他几种方法,但没有成功。 使用 'chpasswd' 命令我试过这个:
user = list.get(ANCHOR)
sudo_command = 'chpasswd'
f = open("passwordusu.tmp", "w")
f.write("%s:%s" % (user, newpass))
f.close()
A=os.system('echo %s|sudo -S %s < %s %s' % (sudo_password, sudo_command,'passwordusu.tmp', user))
print A
windowpass.destroy()
还有:
A=os.system('echo %s|sudo -S %s:%s|%s' % (sudo_password, user, newpass, sudo_command))
@;which returns 32512
A=os.system("echo %s | sudo -S %s < \"%s\"" % (sudo_password, sudo_command, "passwordusu.tmp"))
@;which returns 256
我也像这样试过 'mkpasswd' 和 'usermod':
user = list.get(ANCHOR)
sudo_command = 'mkpasswd -m sha-512'
os.system("echo %s | sudo -S %s %s > passwd.tmp" % (sudo_password,sudo_command, newpass))
sudo_command="usermod -p"
f = open('passwd.tmp', 'r')
for line in f.readlines():
newpassencryp=line
f.close()
A=os.system("echo %s | sudo -S %s %s %s" % (sudo_password, sudo_command, newpassencryp, user))
@;which returns 32512
但是,如果您访问https://www.mkpasswd.net ,对“newpass”进行哈希处理并替换为“newpassencryp”,它会返回 0,这在理论上意味着它已经正确,但到目前为止它并没有更改密码。
我已经在互联网和 stackoverflow 上搜索过这个问题或类似的问题,并尝试了公开的解决方案,但同样没有成功。
我真的很感激任何帮助,当然,如果您需要更多信息,我很乐意提供!
提前致谢。
尝试在管道中对 passwd 命令使用“--stdin”选项。 引用手册页:
--stdin This option is used to indicate that passwd should read the new password from standard input, which can be a pipe.
另一种选择,如果您的 Linux 有 usermod 命令,作为 root(或通过 sudo),您可以使用“-p”选项显式设置(加密)密码。
您正在运行的用户必须具有 sudo 权限才能在没有密码的情况下运行passwd
命令。
>>> from subprocess import Popen
>>> proc = Popen(['/usr/bin/sudo', '/usr/bin/passwd', 'test', '--stdin'])
>>> proc.communicate('newpassword')
我今天遇到了同样的问题,我围绕subprocess
编写了一个简单的包装器来调用passwd
命令并使用新密码提供stdin
。 此代码不是万无一失的,仅在以 root 身份运行时才有效,不会提示输入旧密码。
import subprocess
from time import sleep
PASSWD_CMD='/usr/bin/passwd'
def set_password(user, password):
cmd = [PASSWD_CMD, user]
p = subprocess.Popen(cmd, stdin=subprocess.PIPE)
p.stdin.write(u'%(p)s\n%(p)s\n' % { 'p': password })
p.stdin.flush()
# Give `passwd` cmd 1 second to finish and kill it otherwise.
for x in range(0, 10):
if p.poll() is not None:
break
sleep(0.1)
else:
p.terminate()
sleep(1)
p.kill()
raise RuntimeError('Setting password failed. '
'`passwd` process did not terminate.')
if p.returncode != 0:
raise RuntimeError('`passwd` failed: %d' % p.returncode)
如果您需要 passwd 的输出,您还可以将stdout=subprocess.PIPE
传递给Popen
调用并从中读取。 就我而言,我只对操作成功与否感兴趣,所以我只是跳过了那部分。
安全考虑:不要使用类似echo -n 'password\\npassword\\n | passwd username'
echo -n 'password\\npassword\\n | passwd username'
因为这将使密码在进程列表中可见。
由于您希望使用sudo passwd <username>
我建议在您的/etc/sudoers
添加一个新行(为此使用visudo
!)
some_user ALL = NOPASSWD: /usr/bin/passwd
Sudo 不会询问some_user
的密码,脚本将按预期运行。
或者,只需添加一个额外的p.stdin.write(u'%s\\n' % SUDO_PASSWORD)
行。 这样sudo
将首先接收用户密码,然后passwd
接收新的用户密码。
基于usermod
的版本:
#!/usr/bin/env python
from crypt import crypt
from getpass import getpass
from subprocess import Popen, PIPE
sudo_password_callback = lambda: sudo_password # getpass("[sudo] password: ")
username, username_newpassword = 'testaccount', '$2&J|5ty)*X?9+KqODA)7'
# passwd has no `--stdin` on my system, so `usermod` is used instead
# hash password for `usermod`
try:
hashed = crypt(username_newpassword) # use the strongest available method
except TypeError: # Python < 3.3
p = Popen(["mkpasswd", "-m", "sha-512", "-s"], stdin=PIPE, stdout=PIPE,
universal_newlines=True)
hashed = p.communicate(username_newpassword)[0][:-1] # chop '\n'
assert p.wait() == 0
assert hashed == crypt(username_newpassword, hashed)
# change password
p = Popen(['sudo', '-S', # read sudo password from the pipe
# XXX: hashed is visible to other users
'usermod', '-p', hashed, username],
stdin=PIPE, universal_newlines=True)
p.communicate(sudo_password_callback() + '\n')
assert p.wait() == 0
对于那些 --stdin 不是一个选项的人:
import subprocess
cmd = "bash -c \"echo -e 'NewPassword\\nNewPassword' | passwd root\""
subprocess.check_call(cmd, shell=True)
如前所述,不幸的是,在命令行上传递密码并不是很安全。 此外,并非每个passwd
实现都提供诸如“ --stdin
”之类的用于passwd
内容。 因此,这里有一个使用chpasswd
的更安全版本:
def setPassword(userName:str, password:str):
p = subprocess.Popen([ "/usr/sbin/chpasswd" ], universal_newlines=True, shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(stdout, stderr) = p.communicate(userName + ":" + password + "\n")
assert p.wait() == 0
if stdout or stderr:
raise Exception("Error encountered changing the password!")
解释:
使用subprocess.Popen
我们启动一个chpasswd
实例。 我们将用户名和密码通过管道传送到chpasswd
一个实例。 然后chpasswd
将使用为当前操作系统定义的设置更改密码。 如果没有发生错误, chpasswd
将保持完全沉默。 因此,如果发生任何类型的错误,上面的代码将引发异常(无需仔细查看实际错误)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.