Using Python subprocess and string formating - python

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.

Related

subprocess.check_output returns non-zero exit status 1 [duplicate]

I'm trying to call ffmpeg command using subprocess.call() on linux, but I'm unable to get the arguments right. Before hand, I used os.system and it worked, but this method is not recommended.
Using arguments with a dash such as "-i" gets me this error
Unrecognized option 'i "rtsp://192.168.0.253:554/user=XXX&password=XXX&channel=0&stream=0.sdp?real_stream"'.
Error splitting the argument list: Option not found
Using arguments without dash like "i" gets me this error
[NULL # 0x7680a8b0] Unable to find a suitable output format for 'i rtsp://192.168.0.253:554/user=admin&password=&channel=0&stream=0.sdp?real_stream'
i rtsp://192.168.0.253:554/user=XXX&password=XXX&channel=0&stream=0.sdp?real_stream: Invalid argument
Here's the code
class IPCamera(Camera):
"""
IP Camera implementation
"""
def __init__(self,
path='\"rtsp://192.168.0.253:554/'
'user=XXX&password=XXX&channel=0&stream=0.sdp?real_stream\"'):
"""
Constructor
"""
self.path = path
def __ffmpeg(self, nb_frames=1, filename='capture%003.jpg'):
"""
"""
ffm_input = "-i " + self.path
ffm_rate = "-r 5"
ffm_nb_frames = "-vframes " + str(nb_frames)
ffm_filename = filename
if platform.system() == 'Linux':
ffm_path = 'ffmpeg'
ffm_format = '-f v4l2'
else:
ffm_path = 'C:/Program Files/iSpy/ffmpeg.exe'
ffm_format = '-f image2'
command = [ffm_path, ffm_input, ffm_rate, ffm_format, ffm_nb_frames, ffm_filename]
subprocess.call(command)
print(command)
BTW, I'm running this command on a MT7688.
Thanks
You have to split the options:
command = [ffm_path, '-i', ffm_input, '-r', ffm_rate, '-f', ffm_format, '-vframes', ffm_nb_frames, ffm_filename]
The ffm_input, ffm_rate, ffm_format should only contain the value:
ffm_input = self.path
ffm_rate = '5'
ffm_nd_frames = str(nb_frames)
ffm_format = 'v412' if platform.system() == 'Linux' else 'image2'
When you pass a list no parsing is done so -r 5 is taken as a single argument but the program expects you to provide two separate arguments -r followed by 5.
Basically if you put them as a single element in the list it's as if you quoted them on the command line:
$ echo "-n hello"
-n hello
$ echo -n hello
hello$
In the first example echo sees a single argument -n hello. Since it does not match any option it just prints it. In the second case echo sees two arguments -n and hello, the first is the valid option to suppress end of line and as you can see the prompt is printed right after hello and not on its own line.

Python Subprocess mount returning - non zero exit status 1

I've successfully mounted the drive using fixed //IP/Folder /Mount/Point while providing interchangable username and password as the NAS has permissions set up which are unique to each user.
My First and Working Attempt:
subprocess.check_call("sudo mount -t cifs -o username="+txtUsername.get()+",password="txtPassword.get()+" //IP/Folder /Mount/Point", shell=true)
However after wanting to create a more felxible program i wanted to be able to change the IP and Folder as well as the Mount Point through a config menu.
However when I try to build the command and use it with shell=true it doesn't work and returns a "non zero exit status 1" as a response from the try/except.The structure of the command returned is no different from my working attempt, however the way which i insert it is through variables.
try
password = txtPassword.get()
username = txtUsername.get()
localpath = mountPath
serverAddress = ' //'+serverIP + serverPath +' '+localpath
command = serverAddress
print(command)
subprocess.check_output('sudo mount -t cifs -o username='+username+',password='+password+str(command), shell=True)
#If try fails, caputure error type and store in variable
except subprocess.CalledProcessError as e:
print ("error Message:"+str(e))
**** UPDATE ****
I've done as request in turning the command into an argument after doing some research however the result is no different and still returns a "non zero exit status 1"
command = "sudo mount -t cifs -o username="+username+" password="+password + " " + serverAddress+ " " + localpath
print(command)
subprocess.check_output(command.split(), shell=False)

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.

Need help with python script with bash commands

I copied this script from internet but idon't know how to use it. i am newbiw to python so please help. When i execute it using
./test.py then i can only see
usage: py4sa [option]
A unix toolbox
options:
--version show program's version number and exit
-h, --help show this help message and exit
-i, --ip gets current IP Address
-u, --usage gets disk usage of homedir
-v, --verbose prints verbosely
when i type py4sa then it says bash command not found
The full script is
#!/usr/bin/env python
import subprocess
import optparse
import re
#Create variables out of shell commands
#Note triple quotes can embed Bash
#You could add another bash command here
#HOLDING_SPOT="""fake_command"""
#Determines Home Directory Usage in Gigs
HOMEDIR_USAGE = """
du -sh $HOME | cut -f1
"""
#Determines IP Address
IPADDR = """
/sbin/ifconfig -a | awk '/(cast)/ { print $2 }' | cut -d':' -f2 | head -1
"""
#This function takes Bash commands and returns them
def runBash(cmd):
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
out = p.stdout.read().strip()
return out #This is the stdout from the shell command
VERBOSE=False
def report(output,cmdtype="UNIX COMMAND:"):
#Notice the global statement allows input from outside of function
if VERBOSE:
print "%s: %s" % (cmdtype, output)
else:
print output
#Function to control option parsing in Python
def controller():
global VERBOSE
#Create instance of OptionParser Module, included in Standard Library
p = optparse.OptionParser(description='A unix toolbox',
prog='py4sa',
version='py4sa 0.1',
usage= '%prog [option]')
p.add_option('--ip','-i', action="store_true", help='gets current IP Address')
p.add_option('--usage', '-u', action="store_true", help='gets disk usage of homedir')
p.add_option('--verbose', '-v',
action = 'store_true',
help='prints verbosely',
default=False)
#Option Handling passes correct parameter to runBash
options, arguments = p.parse_args()
if options.verbose:
VERBOSE=True
if options.ip:
value = runBash(IPADDR)
report(value,"IPADDR")
elif options.usage:
value = runBash(HOMEDIR_USAGE)
report(value, "HOMEDIR_USAGE")
else:
p.print_help()
#Runs all the functions
def main():
controller()
#This idiom means the below code only runs when executed from command line
if __name__ == '__main__':
main()
It seems to me you have stored the script under another name: test.py rather than py4sa. So typing ./test.py, like you did, is correct for you. The program requires arguments, however, so you have to enter one of the options listed under 'usage'.
Normally 'py4sa [OPTIONS]' would mean that OPTIONS is optional, but looking at the code we can see that it isn't:
if options.verbose:
# ...
if options.ip:
# ...
elif options.usage:
# ...
else:
# Here's a "catch all" in case no options are supplied.
# It will show the help text you get:
p.print_help()
Note that the program probably would not be recognized by bash even if you renamed it to py4sa, as the current directory is often not in bash's PATH. It says 'usage: py4sa (..)' because that's hard-coded into the program.
The script is called "test.py". Either invoke it as such, or rename it to "py4sa".
you run a Python script using the interpreter, so
$ python py4sa

Run shell command with input redirections from python 2.4?

What I'd like to achieve is the launch of the following shell command:
mysql -h hostAddress -u userName -p userPassword
databaseName < fileName
From within a python 2.4 script with something not unlike:
cmd = ["mysql", "-h", ip, "-u", mysqlUser, dbName, "<", file]
subprocess.call(cmd)
This pukes due to the use of the redirect symbol (I believe) - mysql doesn't receive the input file.
I've also tried:
subprocess.call(cmd, stdin=subprocess.PIPE)
no go there ether
Can someone specify the syntax to make a shell call such that I can feed in a file redirection ?
Thanks in advance.
You have to feed the file into mysql stdin by yourself. This should do it.
import subprocess
...
filename = ...
cmd = ["mysql", "-h", ip, "-u", mysqlUser, dbName]
f = open(filename)
subprocess.call(cmd, stdin=f)
The symbol < has this meaning (i. e. reading a file to stdin) only in shell. In Python you should use either of the following:
1) Read file contents in your process and push it to stdin of the child process:
fd = open(filename, 'rb')
try:
subprocess.call(cmd, stdin=fd)
finally:
fd.close()
2) Read file contents via shell (as you mentioned), but redirect stdin of your process accordingly:
# In file myprocess.py
subprocess.call(cmd, stdin=subprocess.PIPE)
# In shell command line
$ python myprocess.py < filename
As Andrey correctly noticed, the < redirection operator is interpreted by shell. Hence another possible solution:
import os
os.system("mysql -h " + ip + " -u " + mysqlUser + " " + dbName)
It works because os.system passes its argument to the shell.
Note that I assumed that all used variables come from a trusted source, otherwise you need to validate them in order to prevent arbitrary code execution. Also those variables should not contain whitespace (default IFS value) or shell special characters.

Categories