Take the 2-minute tour ×

I'm trying to write some scripts in Python and stumbled upon the need of making something to update the password of a given user in a Linux system...

UPDATE: the objective is to achieve the script to update the password automatically from a given data/algorithm. The important thing is to have no human intervention...

is there a way to achieve that? or should I search through other means?


share|improve this question

4 Answers 4

up vote 7 down vote accepted

You can use openssl and usermod:

#!/usr/bin/env python
import subprocess

login = 'username'
password = 'somepassword'

# OpenSSL doesn't support stronger hash functions, mkpasswd is preferred
#p = subprocess.Popen(('openssl', 'passwd', '-1', password), stdout=subprocess.PIPE)
p = subprocess.Popen(('mkpasswd', '-m', 'sha-512', password), stdout=subprocess.PIPE)
shadow_password = p.communicate()[0].strip()

if p.returncode != 0:
    print 'Error creating hash for ' + login

r = subprocess.call(('usermod', '-p', shadow_password, login))

if r != 0:
    print 'Error changing password for ' + login
share|improve this answer
alright! this almost got it! the thing is that I still need interaction with the script, but indirectly: I need to run it with sudo, asking me for the user password executing the script, even if login variable is the same name as the user running the script. I guess it has to do with usermod, right? –  Javier Novoa C. Jan 20 '11 at 16:14
Yes, it seems so. I don't know if there is a way to get around this. The user that runs usermod needs permissions to modify /etc/passwd and /etc/shadow. You would have to check how passwd changes the password without requiring the permissions. –  Juliusz Gonera Jan 20 '11 at 17:51
Thank you very much. Since I pretend to modify automatically the password for a certain user at certain moment, I manage to go around it by using root's crontab (which I can access through sudo crontab -e), and then the script runs as I desire... –  Javier Novoa C. Jan 20 '11 at 18:47
Unfortunately openssl-passwd only supports crypt, md5, and apr1 hashes, and not blowfish or sha1 which are more commonly used nowadays. Also it doesn't check password strength, etc. –  zbyszek Apr 25 '12 at 9:16
@zbyszek, I guess you're right. It seems that mkpasswd is able to generate stronger hashes. I updated the answer. –  Juliusz Gonera Apr 27 '12 at 16:33

You can use crypt to do the password hashing instead of using openssl passwd (where you are passing the password in plaintext in the command line)

Adapting Juliusz script:

#!/usr/bin/env python
import subprocess,crypt,random

login = 'username'
password = 'somepassword'

ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
salt = ''.join(random.choice(ALPHABET) for i in range(8))

shadow_password = crypt.crypt(password,'$1$'+salt+'$')


if r != 0:
    print 'Error changing password for ' + login

This way, the password is only passed in the command line already hashed (to usermod).
I've tested this with ubuntu+python2.6.6+pycrypto2.5.

share|improve this answer

I just needed to do this again today, and below is my solution. It is fully automatic, and also uses standard system passwd binary, so system policies are respected.


username = 'joe'

# generate passphrase
pw_length = 6
phrase = subprocess.check_output(['pwgen', str(pw_length), '1'])
phrase = phrase.decode('utf-8').strip()

dev_null = open('/dev/null', 'w')
passwd = subprocess.Popen(['sudo', 'passwd', user], stdin=subprocess.PIPE,
passwd.communicate( ((phrase + '\n')*2).encode('utf-8') )
if passwd.returncode != 0:
    raise OSError('password setting failed')

(This generated the password too. Skip the first part if not useful.)

share|improve this answer

Use subprocess to invoke passwd.

share|improve this answer
thanks for answering, but what I really need is to get it done without human intervention, and as far as I know, passwd requires it... –  Javier Novoa C. Jan 20 '11 at 15:37
Have you tried the options given in the man page? Specifically --stdin. –  Ignacio Vazquez-Abrams Jan 20 '11 at 15:39
Consider invoking usermod too. –  ulidtko Jan 20 '11 at 15:40
passwd --stdin is not an option since that parameter is not always present in all distros, or so I've noticed. In my test system, a Debian (and also found the same on Ubuntu, almost obviously), there isn't a --stdin option. I've notived that in CentOS it is present, but the problem remains: not all distros support it... –  Javier Novoa C. Jan 20 '11 at 16:01
I'll take a look at usermod , didn't knew about it, but I tested manually and found that since usermod stores the password "as returned by crypto" (according to man page), the system didn't allow me to login with the usermod-modified password, so I had to su and passwd manually back again... Have to research a little more... –  Javier Novoa C. Jan 20 '11 at 16:03

Your Answer


