I am trying to write a python script with which to restore our database. We store all our tables (individually) in the repository. Since typing "source table1.sql, source table2.sql,.." Will be cumbersome I've written a script to do this automatically.
I've found a solution using Popen.
process = Popen('mysql %s -u%s -p%s' % (db, "root", ""), stdout=PIPE, stdin=PIPE, shell=True)
output = process.communicate('source' + file)[0]
The method appears to work very well, however, for each table, it prompts me for a password. How do I bypass this to either get it prompt for a password only once or have the subprocess read the password from a config file?
Is there a better way to do this? I've tried to do this using a windows batch script, but as you'll expect, this is a lot less flexible than using python (for e.g)
Since apparently you have an empty password, remove the -p option, -p without a password makes mysql prompt
from subprocess import Popen, PIPE
process = Popen('mysql %s -u%s' % (db, "root"), stdout=PIPE, stdin=PIPE, shell=True)
output = process.communicate('source' + file)[0]
In order to prevent exposing the password to anyone with permission to see running processes, it's best to put the password in a config file, and call that from the command-line:
The config file:
[client]
host=host_name
user=user_name
password=your_pass
Then the command-line:
mysql --defaults-extra-file=your_configfilename
Well, you could pass it on in the command line after reading it from a file
with open('secret_password.txt', 'r') as f:
password = f.read()
process = Popen('mysql %s -u%s -p%s' % (db, "root", password), stdout=PIPE, stdin=PIPE,
Otherwise you could investigate pexpect, which lets you interact with processes. Other alternatives for reading from a config file (like ConfigParser) or simply making it a python module and importing the password as a variable.
Related
I am appending text to a file that requires sudo permissions. When I run this python script below:
import subprocess
ssid= "testing"
psk= "testing1234"
p1 = subprocess.Popen(["wpa_passphrase", ssid, psk], stdout=subprocess.PIPE)
p2 = subprocess.Popen(["sudo","tee","-a","/etc/wpa_supplicant/wpa_supplicant.conf",">","/dev/null"], stdin=p1.stdout, stdout=subprocess.PIPE)
p1.stdout.close()
output,err = p2.communicate
It will append to the file as expected, but will append this:
network={
ssid="testing"
#psk="testing1234"
psk=9891dab18debe8308a5d3bf596f5277e4a5c158bff016145830b12673ef63360
}
When I want this:
network={
ssid="testing"
psk="testing1234"
key_mgmt=WPA-PSK
}
This subprocess syntax is complicated to me, so I am open to an alternative method! I tried to use f=open("appendedtext >> /etc/wpa_supplicant/wpa_supplicant.conf") but I need to run as sudo and I can't seem to find a way to do this via open(). I get a permission error.
Any help is appreciated!!
It's not python or subrpocess issue, you're getting expected output from wpa_passphrase, see the man page:
NAME
wpa_passphrase - Generate a WPA PSK from an ASCII passphrase for a SSID
SYNOPSIS
wpa_passphrase [ ssid ] [ passphrase ]
OVERVIEW
wpa_passphrase pre-computes PSK entries for network configuration blocks of a wpa_supplicant.conf file. An ASCII passphrase and SSID are
used to generate a 256-bit PSK.
if you need plain text password just write it to file without calling wpa_passphrase:
with open('/etc/wpa_supplicant/wpa_supplicant.conf', 'a') as conf:
conf.writelines(['network={\n', '\tssid="{0}"\n'.format(ssid), '\tpsk="{0}"\n'.format(psk), '\tkey_mgmt=WPA-PSK\n', '}\n'])
and don't forget to call it with sudo: sudo python script.py.
I'd like to change my current password from Python script using PowerShell. For this I need to run PowerShell command from the code bellow. What would be the best way to do that?
import datetime
#generated password is always changing. There might be different quotations and slashes so it's tricky to put it into PowerShell command bellow
generated_password=r'/#\n\9{S;-l2H~'
#password to set is changing depending on date. Let's say today it has become 'xxx180220'
password_to_set="xxx"+datetime.datetime.now().strftime("%y%m%d")
#I'd like to run this PS command to change my generated password to value stored in password_to_set variable. How do I do it?
PowerShell.exe -ExecutionPolicy ByPass ([adsi]'WinNT://valueaddco/wadmin,user').ChangePassword('/#\n\9{S;-l2H~','xxx180220')
I've created new1.ps file:
echo "changing password from $($args[0]) to $($args[1])"
([adsi]'WinNT://valueaddco/wadmingolyaa1,user').ChangePassword($($args[0]), $($args[1]))
It could be launched with Python code:
from subprocess import Popen, PIPE
cmd = ['powershell.exe', '-ExecutionPolicy', 'ByPass', '-File', 'new.ps1', generated_password, password_to_set]
proc= Popen(cmd, stdout=PIPE, stderr=PIPE)
while True:
line = proc.stdout.readline()
if line != b'':
print(line.strip())
else:
break
Here's my sample python code
def gitClone():
proc = subprocess.Popen(['git', 'clone', 'https://someuser#sailclientqa.scm.azurewebsites.net:443/sailclientqa.git'], stdout=subprocess.PIPE)
stdout,stderr = proc.communicate('mypassword')
print(stddata)
print (stderr)
Every execution results in prompt for password. What's the best way for me to do this git clone from python without password prompt.
I'd appreciate your expertise/advice
The naive approach would be to add stdin=subprocess.PIPE to your command so you can feed it password input. But that's not that simple with password inputs which use special ways of getting keyboard input.
On the other hand, as stated in this answer it is possible to pass the password in command line (although not advised since password is stored in git command history with the command line !).
I would modify your code as follows:
add a password parameter. If not set, use python getpass module to prompt for password (maybe you don't need that)
if the password is properly set, pass it in the modified command line
my proposal:
import getpass
def gitClone(password=None):
if password is None:
password = getpass.getpass()
proc = subprocess.Popen(['git', 'clone', 'https://someuser:{}#sailclientqa.scm.azurewebsites.net:443/sailclientqa.git'.format(password)], stdout=subprocess.PIPE)
stdout,stderr = proc.communicate()
print(stddata)
print (stderr)
An alternative if the above solution doesn't work and if you cannot setup ssh keys, is to use pexpect module which handles special password input streams:
def gitClone(mypassword):
child = pexpect.spawn('git clone https://someuser#sailclientqa.scm.azurewebsites.net:443/sailclientqa.gi')
child.expect ('Password:')
child.sendline (mypassword)
It has the nice advantage of not storing the password in git command history.
source: How to redirect data to a "getpass" like password input?
So I have this python3 script that does a lot of automated testing for me, it takes roughly 20 minutes to run, and some user interaction is required. It also uses paramiko to ssh to a remote host for a separate test.
Eventually, I would like to hand this script over to the rest of my team however, it has one feature missing: evidence collection!
I need to capture everything that appears on the terminal to a file. I have been experimenting with the Linux command 'script'. However, I cannot find an automated method of starting script, and executing the script.
I have a command in /usr/bin/
script log_name;python3.5 /home/centos/scripts/test.py
When I run my command, it just stalls. Any help would be greatly appreciated!
Thanks :)
Is a redirection of the output to a file what you need ?
python3.5 /home/centos/scripts/test.py > output.log 2>&1
Or if you want to keep the output on the terminal AND save it into a file:
python3.5 /home/centos/scripts/test.py 2>&1 | tee output.log
I needed to do this, and ended up with a solution that combined pexpect and ttyrec.
ttyrec produces output files that can be played back with a few different player applications - I use TermTV and IPBT.
If memory serves, I had to use pexpect to launch ttyrec (as well as my test's other commands) because I was using Jenkins to schedule the execution of my test, and pexpect seemed to be the easiest way to get a working interactive shell in a Jenkins job.
In your situation you might be able to get away with using just ttyrec, and skip the pexpect step - try running ttyrec -e command as mentioned in the ttyrec docs.
Finally, on the topic of interactive shells, there's an alternative to pexpect named "empty" that I've had some success with too - see http://empty.sourceforge.net/. If you're running Ubuntu or Debian you can install empty with apt-get install empty-expect
I actually managed to do it in python3, took a lot of work, but here is the python solution:
def record_log(output):
try:
with open(LOG_RUN_OUTPUT, 'a') as file:
file.write(output)
except:
with open(LOG_RUN_OUTPUT, 'w') as file:
file.write(output)
def execute(cmd, store=True):
proc = Popen(cmd.encode("utf8"), shell=True, stdout=PIPE, stderr=PIPE)
output = "\n".join((out.decode()for out in proc.communicate()))
template = '''Command:\n====================\n%s\nResult:\n====================\n%s'''
output = template % (cmd, output)
print(output)
if store:
record_log(output)
return output
# SSH function
def ssh_connect(start_message, host_id, user_name, key, stage_commands):
print(start_message)
try:
ssh.connect(hostname=host_id, username=user_name, key_filename=key, timeout=120)
except:
print("Failed to connect to " + host_id)
for command in stage_commands:
try:
ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command(command)
except:
input("Paused, because " + command + " failed to run.\n Please verify and press enter to continue.")
else:
template = '''Command:\n====================\n%s\nResult:\n====================\n%s'''
output = ssh_stderr.read() + ssh_stdout.read()
output = template % (command, output)
record_log(output)
print(output)
I am writing a python (2.7) script that checks if some files are missing and downloads them via wget. Everything works fine, but after the download has finished and the script should exit, the bash (where I started the python script from) is not showing up correctly.
I have the cursor and can enter things, but the standard prompt is not showing up. I have to resize the terminal window to make the prompt display correctly. What might be the reason for this?
tilenames = ['File1', 'File2', ...]
web_url = http://...
for t in tilenames:
try:
open(t, 'r')
except IOError:
print 'file %s not found.' % (t)
command = ['wget', '-P', './SRTM/', web_url + t ]
output = Popen(command, stdout=subprocess.PIPE)
print "Done"
I think it has something to do with the way the wget process is invoked. The last command print "Done" is actually done before wget writes all of its output into the shell.
Just add a .communicate() after output, like this:
tilenames = ['File1', 'File2', ...]
web_url = http://...
for t in tilenames:
try:
open(t, 'r')
except IOError:
print 'file %s not found.' % (t)
command = ['wget', '-P', './SRTM/', web_url + t ]
p = Popen(command, stdout=subprocess.PIPE)
stdout, stderr = p.communicate()
print "Done"
communicate will return the output written to stdout and None for stderr, because it's not forwarded to a PIPE (you will see it on the terminal instead).
Btw. you should close opened file objects (to check if a file exists you can use the functions in os.path e.g. os.path.exists)
wget writes its statistics to stderr, which is why it scrambles your terminal. stdout and stderr are flushed and queried at different intervals, so it is possible that your Done shows up before the output from wget.
A fix would be to call wget with -q or to also redirect stderr using stderr=open("/dev/null", "w") or something similar.
Additionally, you should probably use .communicate() to avoid pipe issues.
You could use os.system (but see http://docs.python.org/release/2.5.2/lib/node536.html). Basically Popen is intended to ALLOW your python process to read from the command output. You don't seem to need to do that, so the fragment below should get you what you want:
import os
import subprocess
p = subprocess.Popen(['wget','http://www.aol.com'],stdout=subprocess.PIPE)
os.waitpid(p.pid,0)
print "done"
If you add the -q option to wget it works too (quite mode)