I'm trying to automate the setup of SFTP access. This script is running as a user with sudo permissions and no password.
I can create a user like so:
>>> import subprocess
>>> process = subprocess.Popen(['sudo', 'useradd', 'test'], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> process.communicate()
('', '')
Next I need to set the user's password, but I can't figure out how. Here's what I've tried.
>>> process = subprocess.Popen(['sudo', 'chpasswd'], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> process.communicate('test:password')
In my python program it has no effect, in the interactive interpreter it locks up after the first line.
What's the best way to do this?
I'm running python 2.6 on Ubuntu lucid.
The documentation for communicate
says that you'll need to add stdin=PIPE
if you're sending data to standard input via the communicate
parameter:
http://docs.python.org/release/2.6/library/subprocess.html#subprocess.Popen.communicate
I appreciate this is just skeleton code, but here are another couple of other small comments, in case they are of use:
- If you're not interested in the output of the
useradd
command other than whether it failed or not, you might be better off using subprocess.check_call
which will raise an exception if the command returns non-zero.
- In the second case, you should check whether
process.returncode
is 0 after your call to communicate('test:password')
Try below code which will do as you required automation
from subprocess import Popen, PIPE, check_call
check_call(['useradd', 'test'])
proc=Popen(['passwd', 'test'],stdin=PIPE,stdout=PIPE,stderr=PIPE)
proc.stdin.write('password\n')
proc.stdin.write('password')
proc.stdin.flush()
stdout,stderr = proc.communicate()
print stdout
print stderr
print
statements are optional.
You forgot this:
stdin=subprocess.PIPE
To send data to the process, you need a stdin
.
So the full statement is:
process = subprocess.Popen(['sudo', 'chpasswd'], stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE)
and then call communicate('password')
.
On Ubuntu, use usermod
class SomeClass
def userPasswd(self, login, password):
encPass = crypt.crypt(password)
command = "usermod -p '{0:s}' {1:s}".format(encPass, login)
result = os.system(command)
if result != 0:
logging.error(command)
return result
I guess the issue is that you forgot the -S option for sudo.