Trying to run some windows application in a specific user mode. After passing the command, it will ask for password. So passing the password using proc.communicate() but its not working, Please help
from subprocess import Popen, PIPE
import time
cmd = "runas /user:administrator notepad.exe"
proc = Popen(cmd, stdout=PIPE, stdin=PIPE, stderr=PIPE)
print proc.stdout.read()
proc.communicate('password')
Are you open to using Pexpect instead? If yes, you can use the following:
import pexpect
cmd = "runas /user:administrator notepad.exe"
child_process = pexpect.spawn(cmd)
child_process.expect('assword')
child_process.sendline(password)
I'm trying to spawn an ssh child process using subprocess.
I'm working on Python 2.7.6 on Windows 7
here is my code:
from subprocess import *
r=Popen("ssh sshserver#localhost", stdout=PIPE)
stdout, stderr=r.communicate()
print(stdout)
print(stderr)
The outputs:
None
stdout should contain:
sshserver#localhost's password:
Here's an example of working SSH code that handles the promt for yes/no on the certificate part and also when asked for a password.
#!/usr/bin/python
import pty, sys
from subprocess import Popen, PIPE, STDOUT
from time import sleep
from os import fork, waitpid, execv, read, write
class ssh():
def __init__(self, host, execute='echo "done" > /root/testing.txt', askpass=False, user='root', password=b'SuperSecurePassword'):
self.exec = execute
self.host = host
self.user = user
self.password = password
self.askpass = askpass
self.run()
def run(self):
command = [
'/usr/bin/ssh',
self.user+'#'+self.host,
'-o', 'NumberOfPasswordPrompts=1',
self.exec,
]
# PID = 0 for child, and the PID of the child for the parent
pid, child_fd = pty.fork()
if not pid: # Child process
# Replace child process with our SSH process
execv(command[0], command)
## if we havn't setup pub-key authentication
## we can loop for a password promt and "insert" the password.
while self.askpass:
try:
output = read(child_fd, 1024).strip()
except:
break
lower = output.lower()
# Write the password
if b'password:' in lower:
write(child_fd, self.password + b'\n')
break
elif b'are you sure you want to continue connecting' in lower:
# Adding key to known_hosts
write(child_fd, b'yes\n')
elif b'company privacy warning' in lower:
pass # This is an understood message
else:
print('Error:',output)
waitpid(pid, 0)
The reason (and correct me if i'm wrong here) for you not being able to read the stdin straight away is because SSH runs as a subprocess under a different process ID which you need to read/attach to.
Since you're using windows, pty will not work. there's two solutions that would work better and that's pexpect and as someone pointed out key-based authentication.
In order to achieve a key-based authentication you only need to do the following:
On your client, run: ssh-keygen
Copy your id_rsa.pub content (one line) into /home/user/.ssh/authorized_keys on the server.
And you're done.
If not, go with pexpect.
import pexpect
child = pexpect.spawn('ssh user#host.com')
child.expect('Password:')
child.sendline('SuperSecretPassword')
I am new to python and have done several searches on SO and google regarding this question.
How can I pass a variable pw, which is the user's password, to the input for popen.communicate?
Here is the code involved:
pw = getpass.getpass()
from subprocess import Popen, PIPE, STDOUT
ssh_conn = Popen(["ssh", "-t", server, "sudo -S cp /etc/"+map, "/etc/"+map + "." +fulltime], stdout=PIPE, stdin=PIPE, stderr=STDOUT)
ssh_conn.communicate(input='pw\n')[0]
The code above appears to send the string 'pw' to standard input, instead I would like the value of the variable pw to be sent.
I realize that this approach is less than ideal and that there are other python modules that could do the job more simply, but I am not in a position to install any additional modules.
Use str.format to insert the password into the string:
pw = getpass.getpass()
from subprocess import Popen, PIPE, STDOUT
ssh_conn = Popen(["ssh", "-t", server, "sudo -S cp /etc/"+map, "/etc/"+map + "." +fulltime], stdout=PIPE, stdin=PIPE, stderr=STDOUT)
ssh_conn.communicate(input='{0}\n'.format(pw))[0]
I shall write a script using Python to change an user password on a SAMBA server.
I never learned Python and now I tried different things on my VirtualBox with Ubuntu.
With this code I can change (or better delete and set a new) password of an user in my VirtualBox.
But will it also work on the Server?
I have no clue. Please help me. Thank you!
from subprocess import Popen
uname = raw_input("Username: ")
proc = Popen(['/usr/bin/sudo', '/usr/bin/passwd', uname, '--d'])
proc.communicate()
proc = Popen(['/usr/bin/sudo', '/usr/bin/passwd', uname])
proc.communicate()
user2960552's solution doesn't work without user interaction. The following fixes that:
def create_or_update_samba_user(username, password):
proc = subprocess.Popen(['sudo', 'smbpasswd', '-a', username], stdin=subprocess.PIPE)
proc.communicate(input=password + '\n' + password + '\n')
Cannot comment that's why here is a slightly different version from Nyman:
def create_or_update_samba_user(username, password):
proc = subprocess.Popen(['sudo', 'smbpasswd', '-a', '-s', username], stdin=subprocess.PIPE)
proc.communicate(input=password + '\n' + password + '\n')
This is the version that does not require any user intervention. The '-s' tells smbpasswd to take the password from stdin.
So if I read right this should work?
from subprocess import Popen
uname = raw_input("Username: ")
proc = Popen(['/usr/bin/sudo', '/usr/bin/smbpasswd', '-a', uname])
proc.communicate()
Thank you for your help!
Sadly I don't have access to the Server yet so I can't test it. And I don't want to give a not-working script to the server-administrator.
I'm attempting to use the python subprocess module to log in to a secure ftp site and then grab a file. However I keep getting hung up on just trying to send the password when it is requested. I so far have the following code:
from subprocess import Popen, PIPE
proc = Popen(['sftp','user#server', 'stop'], stdin=PIPE)
proc.communicate('password')
This still stops at the password prompt. If I enter the password manually it then goes to the ftp site and then enters the password on the command line. I've seen people suggest using pexpect but long story short I need a standard library solution. Is there anyway with subprocess and/or any other stdlib? What am I forgetting above?
Try
proc.stdin.write('yourPassword\n')
proc.stdin.flush()
That should work.
What you describe sounds like stdin=None where the child process inherits the stdin of the parent (your Python program).
Perhaps you should use an expect-like library instead?
For instance Pexpect (example). There are other, similar python libraries as well.
from subprocess import Popen, PIPE
proc = Popen(['sftp','user#server', 'stop'], stdin=PIPE)
proc.communicate(input='password')
Try with input=‘password’ in communicate, that worked for me.
Use Paramiko for SFTP. For anything else, this works:
import subprocess
args = ['command-that-requires-password', '-user', 'me']
proc = subprocess.Popen(args,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
proc.stdin.write('mypassword\n')
proc.stdin.flush()
stdout, stderr = proc.communicate()
print stdout
print stderr
For some reason, I couldn't get any of the standard library answers here to work for me - getting very strange problems with all of them. Someone else here: unable to provide password to a process with subprocess [python] had the same problem, and concluded that ultimately you just have to go with pexpect to be able to send a password.
I wanted to add my final code here to just save the time of anyone having a similar problem, since I wasted so much time on this (Python 3, 2020):
ssh_password = getpass("user's password: ")
ssh_password = (ssh_password + "\n").encode()
scp_command = 'scp xx.xx.xx.xx:/path/to/file.log /local/save/path/'
child = pexpect.spawn(scp_command)
# make output visible for debugging / progress watching
child.logfile = sys.stdout.buffer
i = child.expect([pexpect.TIMEOUT, "password:"])
if i == 0:
print("Got unexpected output: {} {}".format(child.before, child.after))
return
else:
child.sendline(ssh_password)
child.read()
The above code runs an SCP command to pull a file from the remote server onto your local computer - alter the server IP and paths as necessary.
Key things to remember:
Have to have a pexpect.TIMEOUT in the child.expect call
Have to encode to bytes whatever strings you pass in, and have to use the default encode
Write pexpect output to sys.stdout.buffer so that you can actually see what is going on
Have to have a child.read() at the end
I would recommend scrapping the subprocess approach and using the paramiko package for sftp access.
This same problem plagued me for a week. I had to submit a password from user input through subprocess securely because I was trying to avoid introducing a command injection vulnerability. Here is how I solved the problem with a little help from a colleague.
import subprocess
command = ['command', 'option1', '--password']
subprocess.Popen(command, stdin=subprocess.PIPE).wait(timeout=60)
The .wait(timeout=int) was the most important component because it allows the user to feed input to stdin. Otherwise, the timeout is defaulted to 0 and leaves the user no time to enter input, which consequently results in a None or null string. Took me FOREVER to figure this out.
For repeat use-cases where you know you'll have to do this multiple times, you can override the popen function and use it as a private method which I was told by the same programmer is best practice if you anticipate someone else will be interested in maintaining the code later on and you don't want them to mess with it.
def _popen(cmd):
proc_h = subprocess.Popen(cmd, stdin=subprocess.PIPE)
proc_h.wait(timeout=60)
return proc_h.poll() == os.EX_OK
It is important to remove stdout=subprocess.PIPE if the user is going to be prompted for input. Otherwise, the process appears to hang for 60 seconds, and the user doesn't get a prompt, nor do they realize they are expected to give a password. The stdout will naturally go to the shell window and allow the user to pass input to popen().
Also, just to explain why you return proc_h.poll() == os.EX_OK, is that it returns 0 if the command succeeded. This is just c-style best-practice for when you want to return system error codes in the event the function fails, while accounting for the fact that return 0 will be treated as "false" by the interpreter.
This is a pure Python solution using expect - not pexpect.
If on Ubuntu you first need to install expect with:
sudo apt install expect
Python 3.6 or later:
def sftp_rename(from_name, to_name):
sftp_password = 'abigsecret'
sftp_username = 'foo'
destination_hostname = 'some_hostname'
from_name = 'oldfilename.txt'
to_name = 'newfilename.txt'
commands = f"""
spawn sftp -o "StrictHostKeyChecking no"
{sftp_username}#{destination_hostname}
expect "password:"
send "{sftp_password}\r"
expect "sftp>"
send "rename {from_name} {to_name}\r"
expect "sftp>"
send "bye\r"
expect "#"
"""
sp = subprocess.Popen(['expect', '-c', commands], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
since what you want is just grab a file, I am trying to use "sub process" but it is not works for me. So now I am using paramiko, here is my code:
here is one tutorial I found online
Transfer a file from local server to remote server and vice versa using paramiko of python
"https://www.youtube.com/watch?v=dtvV2xKaVjw"
underneath is my code for transfering all the files in one folder from Linux to windows
import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname='11.11.11.1111', username='root', password='********', port=22)
sftp_client = ssh.open_sftp()
source_folder = '/var/ftp/file_pass'
local_folder = 'C:/temp/file_pass'
inbound_files = sftp_client.listdir(source_folder)
print(inbound_files)
for ele in inbound_files:
try:
path_from = source_folder + '/' + ele
path_to = local_folder + '/'+ ele
sftp_client.get(path_from, path_to)
except:
print(ele)
sftp_client.close()
ssh.close()
Python have a built in library called ftplib, that can be used for ftp processes without any hassle. (Assuming the remote server have a ftp service running)
from ftplib import FTP
ftp = FTP('ftp.us.debian.org') # connect to host, default port
ftp.login() # user anonymous, passwd anonymous#
##'230 Login successful.'
ftp.cwd('debian') # change into "debian" directory
##'250 Directory successfully changed.'
ftp.retrlines('LIST')
Otherwise, You can use scp command, which is a command line tool. The problem with the password can be avoided creating password less user for remote host.
import os
os.system('scp remoteuser#remotehost:/remote/location/remotefile.txt /client/location/')
To create a passwordless user in linux systems,
Fallow below Steps. Fallow this SO answer.
> ssh-keyscan remotehost
> known_hosts ssh-keygen -t rsa # ENTER toevery field (One time)
> ssh-copy-id remoteuser#remotehost
The safest way to do this is to prompt for the password beforehand and then pipe it into the command. Prompting for the password will avoid having the password saved anywhere in your code. Here's an example:
from getpass import getpass
from subprocess import Popen, PIPE
password = getpass("Please enter your password: ")
proc = Popen("sftp user#server stop".split(), stdin=PIPE)
# Popen only accepts byte-arrays so you must encode the string
proc.communicate(password.encode())
import subprocess
args = ['command', 'arg1', 'arg2']
proc = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
proc.stdin.write(b'password') ##The b prefix is necessary because it needs a byte type
proc.stdin.flush()
stdout, stderr = proc.communicate()
print(stdout)
print(stderr)
You just forgot the line return (aka user pressing Enter) in your password.
from subprocess import Popen, PIPE
proc = Popen(['sftp','user#server', 'stop'], stdin=PIPE)
proc.communicate('password\n'.encode())
Also .encode() because by default proc.communicate() accept bytes-like object.