3 arguments for 3 tokens but not enough arguments error - python

If I create a user named Talbot on an ubuntu server, I'm able to manually change ownership of this user's directory by running this command as sudo
chown talbot:talbot -R /home/talbot
I try to do the same thing in the last line of this Fabric python script by doing
sudo("chown %s:%s -R /home/%s" % new_user,new_user, new_user)
However, it keeps giving me this error
sudo("chown %s:%s -R /home/%s" % new_user, new_user,new_user)
TypeError: not enough arguments for format string
Can you explain why this error is happening?
def user_add(new_user, passwd=False):
"""Add new user"""
with settings(hide('running', 'stdout', 'stderr'), warn_only=True):
# if is_host_up(env.host):
if not passwd:
passwd = generate_passwd()
if not sudo("useradd -p $(echo '%s' | openssl passwd -1 -stdin) %s" % (passwd, new_user)).failed:
run('echo "{user} ALL=(ALL:ALL) ALL" >> /etc/sudoers'.format(user=new_user))
if env.host== '107.XX.XX.XXX':
sudo("mkdir /home/%s" % new_user, warn_only=True)
sudo("chown %s:%s -R /home/%s" % new_user,new_user, new_user)

All of your arguments for your format string need to be encased in a single tuple. So instead of
sudo("chown %s:%s -R /home/%s" % new_user,new_user, new_user)
You should use
sudo("chown %s:%s -R /home/%s" % (new_user,new_user, new_user))

Related

SQLAlchemy "def print_usage()" in Python 3 error

I'm following this link https://gist.github.com/thoas/1589496 that copies table from a database to a destination database.
I'm having error with this one
def print_usage():
print """
Usage: %s -f source_server -t destination_server
-f, -t = driver://user[:password]#host[:port]/database
Example: %s -f oracle://someuser:PaSsWd#db1/TSH1 \\
-t mysql://root#db2:3307/reporting
""" % (sys.argv[0], sys.argv[0])
in which I modify following the format for Python 3:
def print_usage():
print("%s -f mysql://root#localhost:3306/db_test -t mysql://root#localhost:3306/db_test1" % (sys.argv[0], sys.argv[0]))
I wanted to test first in MySQL but there is an error
TypeError: not all arguments converted during string formatting
What is the problem on my string? Thanks!
you have only one %s in your format string while you have two variables to put in string.
more details:
when you do
print("%s -f mysql://root#localhost:3306/db_test -t mysql://root#localhost:3306/db_test1" % (sys.argv[0], sys.argv[0]))
you replace each '%s' with a value from (sys.argv[0], sys.argv[0]) so you must have the same number of '%s' and values in the tuple.
try change your code to this:
print("%s -f mysql://root#localhost:3306/db_test -t mysql://root#localhost:3306/db_test1" % (sys.argv[0], ))

Docopt function argument issues

Im not entirely sure how to call my tasklist function with all the required arguments. Im guessing im getting the syntax wrong. Can anyone point out my stupidity please?
CODE
#!/usr/bin/python
"""
Description:
Used for checking users logged into a list of servers.
Usage:
hunter.py (-u <username>) (-p <password>) (-d <domain>) (-s <FILE>)
hunter.py -h | --help
hunter.py --version
Options:
-u --username
-h --help Show this screen.
--version Show version.
-p --password
-d --domain
-s --serverfile=FILE
"""
from docopt import docopt
import subprocess
from subprocess import CalledProcessError
def tasklist(serverlist, domain, username):
for serverl in serverlist():
try:
print "%s Services Listed Below" % serverl
cmd = 'tasklist /V /S %s -u%s\%s /FI "USERNAME eq $s"' % serverl, domain, username, domain
print cmd
subprocess.check_output(cmd)
except CalledProcessError as e:
print(e.returncode)
def getservers(servers):
slist = open(servers).readlines()
return [s.replace('\n', '') for s in slist]
if __name__ == "__main__":
arguments = docopt(__doc__, version='0.1a')
print arguments
serverlist = getservers(arguments['--serverfile'])
print serverlist
tasklist(serverlist,(arguments['<domain>'], ['<username>']))
COMMANDLINE EXAMPLE
c:\Python27>hunter.py -u xpuser -p xpuser -d WORKGROUP -s servers.txt
TRACEBACK
{'--domain': True,
'--help': False,
'--password': True,
'--serverfile': 'servers.txt',
'--username': True,
'--version': False,
'<domain>': 'WORKGROUP',
'<password>': 'xpuser',
'<username>': 'xpuser'}
['192.168.1.122', '192.168.1.121']
Traceback (most recent call last):
File "C:\Python27\hunter.py", line 44, in <module>
tasklist(serverlist,(arguments['<domain>'], ['<username>']))
TypeError: tasklist() takes exactly 3 arguments (2 given)
tasklist() function requires 3 arguments, you are passing just two. Replace:
tasklist(serverlist,(arguments['<domain>'], ['<username>']))
with:
tasklist(serverlist, arguments['<domain>'], arguments['<username>'])
Also, you don't need to call serverlist, it's a list, omit the parenthesis:
for serverl in serverlist:
Also, replace:
cmd = 'tasklist /V /S %s -u%s\%s /FI "USERNAME eq $s"' % serverl, domain, username, domain
with:
cmd = 'tasklist /V /S %s -u%s\%s /FI "USERNAME eq %s"' % (serverl, domain, username, domain)
Hope that helps.

Using Python subprocess and string formating

I am attempting to call a windows command with relevant arguments using python's subprocess . The command is executing and the arguments and their values look to be correct, however It only seems to be working correctly when using the "local mode" -l.
I'm getting an invalid argument/option error when using the remote mode. Could any point out where im going wrong?
Could anyone point out how to format the subprocess.check_ouput() arguments correctly to include the variables given at commandline when executing the script? As you can see ive tryd using string formating, both old and new to try get it working as I cant workout how to add the last domain variable inbetween the filter (/FI) argument value without string formatting.
expected commandline to execute
tasklist /V /S 192.168.1.122 /U 'DOMAIN'\'USERNAME' /P 'PASSWORD' /FI "USERNAME eq 'DOMAIN'\*"
with this commandline example of the script:
hunter.py -d DOMAIN -u USERNAME -p PASSWORD -s servers.txt
This is the error:
ERROR: Invalid argument/option - '/S 192.168.1.122'.
Type "TASKLIST /?" for usage.
Clearly the argument is correct "visually" correct anyway, here is the usage for the tasklist:
Description:
This tool displays a list of currently running processes on
either a local or remote machine.
Parameter List:
/S system Specifies the remote system to connect to.
/U [domain\]user Specifies the user context under which
the command should execute.
/P [password] Specifies the password for the given
user context. Prompts for input if omitted.
/M [module] Lists all tasks currently using the given
exe/dll name. If the module name is not
specified all loaded modules are displayed.
/SVC Displays services hosted in each process.
/APPS Displays Store Apps and their accociated processes.
/V Displays verbose task information.
/FI filter Displays a set of tasks that match a
given criteria specified by the filter.
/FO format Specifies the output format.
Valid values: "TABLE", "LIST", "CSV".
/NH Specifies that the "Column Header" should
not be displayed in the output.
Valid only for "TABLE" and "CSV" formats.
/? Displays this help message.
This is the python code i have so far;
#!/usr/bin/python
"""
Description:
Used for checking users logged into a list of servers.
Usage:
hunter.py [-u <username>] [-p <password>] [-s <FILE>] (-d <domain>)
hunter.py (-d <domain>) (-l)
hunter.py -h | --help
hunter.py --version
Options:
-l --local
-u --username
-h --help Show this screen.
--version Show version.
-p --password
-d --domain
-s --serverfile=FILE
"""
from docopt import docopt
import subprocess
from subprocess import CalledProcessError
def tldomain(serverlist, domain, username, password):
nlist = serverlist
for serverl in nlist:
try:
print subprocess.check_output(["tasklist", "/V", "/S " + serverl, "/U" + domain, "\\" + username, "/P" + password, "/FI", "'USERNAME eq %s\\\*'"]) % domain
except CalledProcessError as e:
print(e.returncode)
def tllocal(domain):
try:
cmd = 'tasklist /V /FI "USERNAME eq {0}\\*"' .format(domain)
subprocess.call(cmd)
except OSError as e:
print e
def getservers(servers):
slist = open(servers).readlines()
return [s.replace('\n', '') for s in slist]
if __name__ == "__main__":
arguments = docopt(__doc__, version='0.1a')
print arguments
if (arguments['--local']) == False:
serverlist = getservers(arguments['--serverfile'])
tldomain(serverlist, arguments['<domain>'], arguments['<username>'], arguments['<password>'])
else:
tllocal(arguments['<domain>'])
Pass in your arguments as separate elements in the list and apply the string formatting to the last element, no the output of the subprocess.check_output() call:
print subprocess.check_output(
["tasklist", "/V", "/S", serverl, "/U", domain + "\\" + username,
"/P", password, "/FI", "USERNAME eq %s\\*" % domain])
Note that I also removed the ' quoting from the last argument, leave that to the subprocess module.
This also assumes that domain is always a non-empty string; if that's not the case, use:
if domain:
domain += '\\'
print subprocess.check_output(
["tasklist", "/V", "/S", serverl, "/U", domain + username,
"/P", password, "/FI", "USERNAME eq %s*" % domain])
e.g. only use the \ backslash when domain is actually specified.

Pass a variable to a path/command in python

I am new to Python. I want to execute a script which has parameters in python. Please have a look at below example on what I finally want to achieve.
I have a script with parameters:
PATH="ABCXYZ"
username = "admin"
password = "pass"
query = "select * from user;"
OUTPUT = /usr/local/<PATH>/dbscript -u username -p password -q query
How can I pass a PATH variable in "/usr/local/<PATH>/dbscript" here ?
I tried with os.system & subprocess, But We cannot use variable in between.
I want that OUTPUT variable data which will print yes or no or some number
Below must work.
import subprocess as sp
PATH="ABCXYZ"
username = "admin"
password = "pass"
query = "select * from user;"
command = "/usr/local/%s/dbscript -u %s -p %s -q %s" % (PATH, username, password, query)
#Next line print '/usr/local/ABCXYZ/dbscript -u admin -p pass -q select * from user;' for me.
print command #
sp.Popen(command.split(), shell=True)
Furthermore you should play with shell parameter and useful read it.

how to find out with python on ubuntu if MySQL is running?

On Ubuntu this command line:
sudo netstat -tap | grep mysql
if MySQL is running returns something like that:
tcp 0 0 localhost:mysql *:* LISTEN 6732/mysqld
and nothing if it's not.
I'm using subprocess to find out from inside the python code if MySQL is up by looking for a "LISTEN" in what that netstat returns, doing that:
import subprocess
msqlr = subprocess.Popen(["sudo netstat -tap | grep mysql"], stdout=subprocess.PIPE).communicate()[0]
msqlrLines = msqlr.split("\n")
vals = msqlrLines[0].split()
print "vals[0] : %s" % vals[0]
if vals[0][-2] == "LISTEN":
print "OK - MySQL is running."
else:
print "Not OK - MySQL is not running."
When I run this it returns:
OSError: [Errno 2] No such file or directory
When in the same subprocess.Popen... I use a one word argument (let's say "df") – it works OK. If the argument is more that one word (i.e. "df -h /" or, like here "sudo netstat -tap | grep mysql") – I'm getting this "No such file or directory" error.
And related question (#2), when I'm running this command in a command line — sometimes it asks for a root password. How do I pass a password from a python script?
Try something line this.
import subprocess
import string
msqlr = subprocess.Popen("sudo /usr/sbin/netstat -al".split(), stdout=subprocess.PIPE).stdout
grep = subprocess.Popen(["/usr/bin/grep", "mysql"], stdin=msqlr, stdout=subprocess.PIPE).stdout
msqlrLines = grep.read().split("\n")
vals = map(string.strip, msqlrLines[0].split())
print vals
if vals[-1] in ("LISTENING", "LISTEN"):
print "OK - MySQL is running."
else:
print "Not OK - MySQL is not running."
OUTPUT on my machine:
['tcp4', '0', '0', '*.mysql', '*.*', 'LISTEN']
OK - MySQL is running.
The idea here is you do the normal netstat, and collect all of the data. Then use the stdout from that subproc as the stdin for the next subproc and do your grep there.
Here is an example running on ubuntu 12.04
import subprocess
import string
msqlr = subprocess.Popen("sudo /bin/netstat -al".split(), stdout=subprocess.PIPE).stdout
grep = subprocess.Popen(["/bin/grep", "mysql"], stdin=msqlr, stdout=subprocess.PIPE).stdout
msqlrLines = grep.read().split("\n")
vals = map(string.strip, msqlrLines[0].split())
print vals
if len(vals) and vals[-1] in ("LISTENING", "LISTEN"):
print "OK - MySQL is running."
else:
print "Not OK - MySQL is not running."
Why not just see if you can connect in python:
try:
con = _mysql.connect('localhost', 'user',
'password', 'testdb')
except _mysql.Error, e:
print "Error %d: %s" % (e.args[0], e.args[1])
sys.exit(1)

Categories