Using the subprocess library: error: unrecognized arguments - python

So essentially I have 15 or so scripts that can connect to various networking devices using an SSH library. I want to create one top-level python file that can run other python scripts so the user can decide which scripts they want to run. I have been advised to use the subprocess library and this seems to make the most sense for what I want to do. It is important to note that my python scripts contain command-line argparse arguments for it to run, for example:
python San_cable_test.py -deviceIP 172.1.1.1 -deviceUsername myUsername -devicePassword myPassword
So far I have created a top-level python file that is set up to call two python scripts to start with that the user can enter. However, when I run the program and select one of the options and get the user arguments, I get a
error: unrecognized arguments:
I tried it two different ways and I'll show the tracebacks:
usage: San_cable_test.py [-h] [-deviceIP DEVICEIP]
The name of this script is: San_cable_test.py
[-deviceUsername DEVICEUSERNAME]
[-devicePassword DEVICEPASSWORD]
San_cable_test.py: error: unrecognized arguments: 172.1.1.1 myUsername myPassword
and
usage: San_cable_test.py [-h] [-deviceIP DEVICEIP]
[-deviceUsername DEVICEUSERNAME]
The name of this script is: San_cable_test.py
[-devicePassword DEVICEPASSWORD]
San_cable_test.py: error: unrecognized arguments: -deviceIP 172.1.1.1 -deviceUsername myUsername -devicePassword myPassword
This is my first time using the subprocces library and I don't know if I'm calling these scripts right. The problem is that these scripts are run in the command line using argparse, so that's the issue. Unfortunately I am using 2.7.16 because of this weird company thing and I've been trying to get my managers to know that 2.7 is going to be unsupported soon but that's not relevant as of now. Here is the important part of my code. I really appreciate the help!
def runMain():
scriptName = os.path.basename(__file__)
print("The name of this script: " + scriptName + "\n")
scriptPurpose = 'This script is the top-level module that can invoke any script the user desires !\n'
while True:
optionPrinter()
user_input = input("Please select an option for which your heart desires...\n")
switch_result = mySwitch(user_input)
if switch_result == "our_Switch":
deviceIP = raw_input("Enter the IP address for the device")
deviceUsername = raw_input("Enter the username for the device")
devicePassword = raw_input("Enter the password for the device")
subprocess.call(['python', 'our_Switch.py', deviceIP, deviceUsername, devicePassword])
elif switch_result == "San_cable_test":
deviceIP = raw_input("Enter the IP address for the device")
deviceUsername = raw_input("Enter the username for the device")
devicePassword = raw_input("Enter the password for the device")
subprocess.call(['python', 'San_cable_test.py', deviceIP, deviceUsername, devicePassword])
else:
print("Exiting the program now, have a great day !\n")
sys.exit(-1)
if __name__ == '__main__':
Here is the an example of argparse being used in one of the scripts
def runMain():
scriptName = os.path.basename(__file__)
print("The name of this script is: " + scriptName)
scriptPurpose = 'This script enables and disables the SAN switches'
parser = argparse.ArgumentParser(description=scriptPurpose, formatter_class=RawTextHelpFormatter)
parser.add_argument("-deviceIP", help="Target device IP address", type=str)
parser.add_argument("-deviceUsername", help="Target device username", type=str)
parser.add_argument("-devicePassword", help="Target device password", type=str)
args = parser.parse_args()
if args.deviceIP is None:
print("The device IP parameter is blank\n")
else:
deviceIP = args.deviceIP
if args.deviceUsername is None:
print("The device userName parameter is blank\n")
else:
deviceUsername = args.deviceUsername
if args.devicePassword is None:
print("The device password parameter is blank\n")
else:
devicePassword = args.devicePassword
print("**********************\n")
print (deviceIP + " " + deviceUsername + " " + devicePassword)
print("**********************\n")
print("This script allows the user to enable and disable ports on a SAN switch to see how it behaves\n")
print("Checking to see if the SAN switch is pingable\n")
test_ping = canPing(deviceIP)
if test_ping:
print("The switch is pingable, let's proceed !\n")
else:
print("This device is not pingable unfortunately, sorry... : (\n")
sys.exit(-1)
sshConnection = connectToSSH(deviceIP, deviceUsername, devicePassword)
while True:
optionPrinter()
user_input = input("Select an option from the menu\n")
switch_result = mySwitch_function(user_input)
if switch_result == 'ShowPort':
portShow(sshConnection)
elif switch_result == 'SwitchShow':
switchShow(sshConnection)
elif switch_result == 'EnablePort':
enablePort(sshConnection)
elif switch_result == 'DisablePort':
disablePort(sshConnection)
elif switch_result == 'disableEnable':
disableEnableIteration(sshConnection)
else:
print("Program is exiting now, have a great day/night ! \n")
sys.exit(-1)

You're missing the option names before the parameters.
subprocess.call(['python', 'our_Switch.py', '-deviceIP', deviceIP, '-deviceUsername', deviceUsername, '-devicePassword', devicePassword])
However, it would probably be cleaner if you changed these other scripts into Python modules that you could simply import and call directly as functions, rather than running them as subprocesses.

Related

Issues with input() and raw_input() for Python 2.7. User entered data is not read properly. What is going on?

So at my company they are making me use python 2.7 because of the product for a compatibility reason that I won't get into here.
So I am writing a program that connects to a device using SSH (a switch specifically) and I am able to actually access the device using SSH and this device is ping-able on my machine. The problem ? raw_input seems to not be taking it as a string. When I try input(), it gives me an invalid syntax error.
For the scripts I write, I usually use arparse and the user enters the IP address, username, and password through the terminal, but I want this script to not use argparse and to use input() or raw_input. All my SSH scripts work good except for this one, the only one using raw_input and input() instead of argparse
def runMain():
scriptName = os.path.basename(__file__)
print("The name of this script is: " + scriptName)
print("**************************************\n")
print("This script allows you to enable and disable ports on the SNET or SOOBM switches, have fun ! \n")
print("**************************************\n")
optionPrinter_switches_top()
user_input = raw_input("Make your selection") # This does not work if I change to input(), it exits out of the program
if user_input == 1:
print("You selected the SNET switch, lets proceed !")
deviceIP = input("Enter the IP address for this device") # I tried changing these to raw_input, I get a syntax issue
deviceUsername = input("Enter the username for this device")
devicePassword = input("Enter the password for this device")
confirm_ping = canPing(deviceIP) # This is a boolean function that works correctly in every script but this one.
if confirm_ping:
ssh_SNET = connectToSSH_SNET(deviceIP, deviceUsername, devicePassword)
else:
print("Sorry, that device is not even ping-able. Figure that issue out and retry the program...")
sys.exit(-1)
while True:
SNET_options()
user_choice_SNET = input("Please select an option")
switch_result = SNET_switch_func(user_choice_SNET)
if switch_result == "displayInterfaceBrief":
time.sleep(5)
displayInterfaceBrief_SNET(ssh_SNET)
elif switch_result == "enablePort":
time.sleep(5)
enablePort_SNET(ssh_SNET)
elif switch_result == "disablePort":
disablePort_SNET(ssh_SNET)
elif switch_result == "switchReboot":
reboot_SNET_switch(ssh_SNET)
else:
print("Exiting program now....")
sys.exit(-1)
Here are relevant issues:
user_input = raw_input("Make your selection") # This does not work if I change to input(), it exits out of the program
deviceIP = input("Enter the IP address for this device") # I tried changing these to raw_input, I get a syntax issue
deviceUsername = input("Enter the username for this device")
devicePassword = input("Enter the password for this device")
confirm_ping = canPing(deviceIP) # This is a boolean function that works correctly in every script but this one.
Conclusion ? There is an issue with input()/raw_input() . What is going on here and how can I fix this ? I can't use python 3.7 and it really is frustrating. Thanks for the help
Try changing if user_input == 1: to if int(user_input) == 1: as the input function takes an input in string format, by default.
And, if you want to use input() instead of raw_input() to take input from users in python 2.x, then you can try below code:
if hasattr(__builtins__, 'raw_input'):
input=raw_input
user_input = input("Enter a number: ")

How can I use the subprocess library to call other python files with command-line arguments in a top-level python file?

So essentially I have 15 or so scripts that can connect to various networking devices using an SSH library. I want to create one top-level python file that can run other python scripts so the user can decide which scripts they want to run. I have been advised to use the subprocess library and this seems to make the most sense for what I want to do. It is important to note that my python scripts contain command-line argparse arguments for it to run, for example:
python reboot_server.py -deviceIP 172.1.1.1 -deviceUsername admin -devicePassword myPassword
So far I have created a top-level python file that is set up to call two python scripts to start with that the user can enter. However, when I run the program and select one of the options I get a "SyntaxError:invalid syntax" Traceback. This happens right when I enter my first argument, which is the device IP address
import subprocess
import os
import sys
def runMain():
scriptName = os.path.basename(__file__)
print("The name of this script: " + scriptName + "\n")
while True:
optionPrinter()
user_input = input("Please select an option for which your heart desires...\n")
switch_result = mySwitch(user_input)
if switch_result == "our_Switch":
deviceIP = str(input("Enter the IP address for the device"))
deviceUsername = str(input("Enter the username for the device"))
devicePassword = str(input("Enter the password for the device"))
subprocess.call(['python', 'our_Switch.py', deviceIP, deviceUsername, devicePassword])
elif switch_result == "San_test":
deviceIP = str(input("Enter the IP address for the device"))
deviceUsername = str(input("Enter the username for the device"))
devicePassword = str(input("Enter the password for the device"))
subprocess.call(['python', 'San_test.py', deviceIP, deviceUsername, devicePassword])
else:
print("Exiting the program now, have a great day !\n")
sys.exit(-1)
Here is the Traceback:
Traceback (most recent call last):
File "C:/myFolder/src/top_level.py", line 57, in <module>
runMain()
File "C:/myFolder/src/top_level.py", line 39, in runMain
deviceIP = str(input("Enter the IP address for the device"))
File "<string>", line 1
172.28.6.21
^
SyntaxError: invalid syntax
Keep in mind that all the scripts that I'm trying to call is in the same source file. Also it is important to note that I have tested each script I have written and they are all fully working. Am I using subprocess.call() right ? How can I fix this issue ? Thanks for the help!
You are using python2. In python2, input not only takes input, it evaluates it as python code. Obviously an IP address is not valid python code. Hence the syntax error.
For python2 you should be using raw_input - and you can drop the str.
deviceIP = raw_input("Enter the IP address for the device")
Or you can switch to python3

Ethical hacking script not working - no error message

I've been taking an Ethical Hacking course. Part of the course is creating a Python script that finds the password for a locked zip file, from a password list text file (hope that makes sense!) - basically iterates through a text file trying each password. The script doesn't work, doesn't error out, and the instructor says "well, it works for me" - not useful. Here's the script:
import optparse
import zipfile
from threading import Thread
def extract_zip(zfile, password):
try:
zfile.extractall(pwd=password)
print("[+] Password Found: " + password + '\n')
except:
pass
def main():
parser = optparse.OptionParser("usage %prog "+\
"-f <zipfile> -d <dictionary>")
parser.add_option('-f', dest='zname', type='string',\
help='specify zip file')
parser.add_option('-d', dest='dname', type='string',\
help='specify dictionary file')
(options, arg) = parser.parse_args()
if (options.zname == None) | (options.dname == None):
print(parser.usage)
exit(0)
else:
zname = options.zname
dname = options.dname
zFile = zipfile.ZipFile(zname)
passFile = open(dname)
for line in passFile.readlines():
password = line.strip('\n')
t = Thread(target=extract_zip, args=(zFile, password))
t.start()
if __name__ == '__main__':
main()
The other two files are a text file with a list of passwords, and a password protected zip file where one of the passwords from the text file will unlock it.
Within the course there's a thread mentioning that optparse is depracated, and argparse is its replacement - but even rewriting the script with that doesn't work.
For want of closing out this part of the course I'm looking for help in why this doesn't work.
Thanks in advance for any help on this.
Per my comment above - I added the code below just below the "try" statement:
password = bytes(password.encode('utf-8'))
...then changed
print('[+] Password Found: ' + password + '\n')
to
print("[+] Password Found: " + (password.decode("utf-8")) + '\n')
Now I get the password printed to the console, and the zip file is unzipped. Here's the final, working code.
import optparse
import zipfile
from threading import Thread
def extract_zip(zfile, password):
try:
password = bytes(password.encode('utf-8'))
zfile.extractall(pwd=password)
print("[+] Password Found: " + (password.decode("utf-8")) + '\n')
except:
pass
def main():
parser = optparse.OptionParser("usage %prog " + '-f <zipfile> -d <dictionary>')
parser.add_option('-f', dest='zname', type='string', help='specify zip file')
parser.add_option('-d', dest='dname', type='string', help='specify dictionary file')
(options, args) = parser.parse_args()
if (options.zname is None) | (options.dname is None):
print(parser.usage)
exit(0)
else:
zname = options.zname
dname = options.dname
zFile = zipfile.ZipFile(zname)
passFile = open(dname)
for line in passFile.readlines():
password = line.strip('\n')
t = Thread(target=extract_zip, args=(zFile, password))
t.start()
if __name__ == '__main__':
main()
The way I found this was by changing the 'except' statement to print exceptions to the console:
except Exception as e: print(e)
From there I had a couple of issues to solve, but at least I had errors to work with. Once the password was being successfully logged to the console I change the exeception statement back to "pass" - don't need to see the passwords that failed!
I hope this helps someone else hitting the same issues I had.
I run your code using python3 it excuted without problem i did this long ago
it is a book called violent something
the password.txt should contain this line
victim: HX9LLTdc/jiDE: 503:100:Iama Victim:/home/victim:/bin/sh
root: DFNFxgW7C05fo: 504:100: Markus Hess:/root:/bin/bash
and the command should look like
python stack.py -f evil.zip -d passwords.txt

Importing a python script/module that uses argparse into another python script

This question may be regarded to be redundant but, to my defense, I've considered similar questions and given solutions but they don't work for me (or I just didn't understand them) as I will show.
What I want to do:
I wrote a couple of python scripts that are each command-line tools (accepting several arguments using argparse) when built with pyinstaller. They all work as expected both from within pycharm's terminal and from the Ubuntu terminal. Now, I would like each of these scripts to be a module that could be called from another python script passing required arguments as I would do in the terminal.
This is one of the original scripts (I've shortened the script a bit so that it serves as a minimal example):
import sys
import argparse
import getpass
if len(sys.argv) < 2:
print "You haven't specified any arguments. Use -h to get more details on how to use this command."
sys.exit(1)
parser = argparse.ArgumentParser()
parser.add_argument('--username', '-u', type=str, default=None, help='Username for the login to the WebCTRL server')
parser.add_argument('--password', '-p', type=str, default=None, help='Password for the login to the WebCTRL server')
parser.add_argument('--node', '-n', type=str, default=None,
help='Path to the point or node whose children you want to retrieve. Start querying at the lowest level with "-n /trees/geographic"')
parser.add_argument('-url', type=str, default='https://my.server.de',
help="URL of the WebCTRL server as e.g. http://google.de")
args = parser.parse_args()
if args.username is None:
print 'No user name specified. Login to WebCTRL needs a user name and password. Check all options for this command via -h'
sys.exit(1)
else:
username = args.username
if args.password is None:
password = getpass.getpass('No password specified via -p. Please enter your WebCTRL login password: ')
else:
password = args.password
if args.node is None:
print 'No path to a node specified. Check all options for this command via -h'
sys.exit(1)
if args.url is None:
print 'No URL given. Specify the URL to the WebCTRL server analogous to http://google.de'
sys.exit(1)
else:
wsdlFile = args.url + '/_common/webservices/Eval?wsdl'
# This doesn't belong to my original code. It's rather for demonstration:
# Print the arguments and leave the script
print 'Username: ' + args.username
print 'Node: ' + args.node
print 'URL: ' + args.url
sys.exit(0)
As I said: From within my IDE (Pycharm) ...
$ python wc_query_test.py -u wsdl -n /trees/geographic
No password specified via -p. Please enter your WebCTRL login password:
Username: wsdl
Node: /trees/geographic
URL: https://my.server.de
... and from the Ubuntu terminal it works just fine:
$ pyinstaller --distpath dist/. wc_query_test.py
$ ./dist/wc_query_test/wc_query_test -u wsdl -n /trees/geographic
No password specified via -p. Please enter your WebCTRL login password:
Username: wsdl
Node: /trees/geographic
URL: https://my.server.de
Coming to the actual problem:
I want the script wc_query_test.py to be a module that can be imported into another python script and executed there passing along the arguments as I do in the command line. To achieve this I followed #Waylan's instructions in this stackoverflow question.
This is the code I came up with (wc_query_test.py):
import sys
import argparse
import getpass
def main(**kwargs):
if kwargs.username is None:
print 'No user name specified. Login to WebCTRL needs a user name and password. Check all options for this command via -h'
sys.exit(1)
else:
username = kwargs.username
if kwargs.password is None:
password = getpass.getpass('No password specified via -p. Please enter your WebCTRL login password: ')
else:
password = kwargs.password
if kwargs.node is None:
print 'No path to a node specified. Check all options for this command via -h'
sys.exit(1)
if kwargs.url is None:
print 'No URL given. Specify the URL to the WebCTRL server analogous to http://google.de'
sys.exit(1)
else:
wsdlFile = kwargs.url + '/_common/webservices/Eval?wsdl'
# This doesn't belong to my original code. It's rather for demonstration:
# Print the arguments and leave the script
print 'Username: ' + username
print 'Node: ' + kwargs.node
print 'URL: ' + kwargs.url
sys.exit(0)
def run():
parser = argparse.ArgumentParser()
parser.add_argument('--username', '-u', type=str, default=None, help='Username for the login to the WebCTRL server')
parser.add_argument('--password', '-p', type=str, default=None, help='Password for the login to the WebCTRL server')
parser.add_argument('--node', '-n', type=str, default=None,
help='Path to the point or node whose children you want to retrieve. Start querying at the lowest level with "-n /trees/geographic"')
parser.add_argument('-url', type=str, default='https://my.server.de',
help="URL of the WebCTRL server as e.g. http://google.de")
args = parser.parse_args()
main(**args)
... and the script that imports the module and calls it (test.py):
import wc_query_test
wc_query_test.main(username='wsdl', password='aaaaaa', node='/trees/geographic')
When I run it in the python terminal I get:
~/PycharmProjects/webctrl$ python wc_query_test.py
~/PycharmProjects/webctrl$ python test.py
Traceback (most recent call last):
File "test.py", line 3, in <module>
wc_query_test.main(username='wsdl', password='aaaaaa', node='/trees/geographic/#geb_g', url='https://webctrl.rz-berlin.mpg.de')
File "/home/stefan/PycharmProjects/webctrl/wc_query_test.py", line 23, in main
if kwargs.username is None:
AttributeError: 'dict' object has no attribute 'username'
Running wc_query_test.py yields no output and I see why this is. That was just a test. But running test.py yields an error as well. I get an idea why this can't work either but I cannot put it into words. What about this run() method? Does it make sense to have it? How would I need to modify my code in order to obtain this dual functionality as described in "What I want to do:"? Thank you in advance for your help!
UPDATE:
I got rid of the error message. I changed e.g. kwargs.username to kwargs.get('username') since kwargs is a dictionary. The code now looks like this:
import sys
import argparse
import getpass
def main(**kwargs):
if kwargs.get('username') is None:
print 'No user name specified. Login to WebCTRL needs a user name and password. Check all options for this command via -h'
sys.exit(1)
else:
username = kwargs.get('username')
if kwargs.get('password') is None:
password = getpass.getpass('No password specified via -p. Please enter your WebCTRL login password: ')
else:
password = kwargs.get('password')
if kwargs.get('node') is None:
print 'No path to a node specified. Check all options for this command via -h'
sys.exit(1)
if kwargs.get('url') is None:
print 'No URL given. Specify the URL to the WebCTRL server analogous to http://google.de'
sys.exit(1)
else:
wsdlFile = kwargs.get('url') + '/_common/webservices/Eval?wsdl'
# This doesn't belong to my original code. It's rather for demonstration:
# Print the arguments and leave the script
print 'Username: ' + username
print 'Node: ' + kwargs.get('node')
print 'URL: ' + kwargs.get('url')
sys.exit(0)
def run():
parser = argparse.ArgumentParser()
parser.add_argument('--username', '-u', type=str, default=None, help='Username for the login to the WebCTRL server')
parser.add_argument('--password', '-p', type=str, default=None, help='Password for the login to the WebCTRL server')
parser.add_argument('--node', '-n', type=str, default=None,
help='Path to the point or node whose children you want to retrieve. Start querying at the lowest level with "-n /trees/geographic"')
parser.add_argument('-url', type=str, default='https://webctrl.rz-berlin.mpg.de',
help="URL of the WebCTRL server as e.g. http://google.de")
args = parser.parse_args()
main(**args)
Running it in the python terminal yields as expected:
$ python test.py
Username: wsdl
Node: /trees/geographic
URL: https://my.server.de
But building it via pyinstaller and running it as command line tool there is no output:
~/PycharmProjects/webctrl$ ./dist/wc_query_test/wc_query_test -h
~/PycharmProjects/webctrl$
How can I modify wc_query_test.py so that it takes arguments and serves as command line tool?
Thanks to everyone who responded. With the help of a colleague I got the answer to my question. This is the functioning code:
wc_query_test.py:
import sys
import argparse
import getpass
def main(args):
if args['username'] is None:
print 'No user name specified. Login to WebCTRL needs a user name and password. Check all options for this command via -h'
sys.exit(1)
else:
username = args['username']
if args['password'] is None:
password = getpass.getpass('No password specified via -p. Please enter your WebCTRL login password: ')
else:
password = args['password']
if args['node'] is None:
print 'No path to a node specified. Check all options for this command via -h'
sys.exit(1)
if args['url'] is None:
print 'No URL given. Specify the URL to the WebCTRL server analogous to http://google.de'
sys.exit(1)
else:
wsdlFile = args['url'] + '/_common/webservices/Eval?wsdl'
# This doesn't belong to my original code. It's rather for demonstration:
# Print the arguments and leave the script
print 'Username: ' + args['username']
print 'Node: ' + args['node']
print 'URL: ' + args['url']
# The parser is only called if this script is called as a script/executable (via command line) but not when imported by another script
if __name__=='__main__':
if len(sys.argv) < 2:
print "You haven't specified any arguments. Use -h to get more details on how to use this command."
sys.exit(1)
parser = argparse.ArgumentParser()
parser.add_argument('--username', '-u', type=str, default=None, help='Username for the login to the WebCTRL server')
parser.add_argument('--password', '-p', type=str, default=None, help='Password for the login to the WebCTRL server')
parser.add_argument('--node', '-n', type=str, default=None,
help='Path to the point or node whose children you want to retrieve. Start querying at the lowest level with "-n /trees/geographic"')
parser.add_argument('-url', type=str, default='https://webctrl.rz-berlin.mpg.de',
help="URL of the WebCTRL server as e.g. http://google.de")
args = parser.parse_args()
# Convert the argparse.Namespace to a dictionary: vars(args)
main(vars(args))
sys.exit(0)
Now, there are three ways of executing wc_query_test which is what I wanted to achive:
1) Calling wc_query_test.py from command line:
~/PycharmProjects/webctrl$ python wc_query_test.py -u aawrg -p wgAWER -n YWERGAEWR
2) Compiling and calling wc_query_test from command line:
~/PycharmProjects/webctrl$ pyinstaller --distpath dist/. wc_query_test.py
~/PycharmProjects/webctrl$ ./dist/wc_query_test/wc_query_test -u aawrg -p wgAWER -n YWERGAEWR
3) Calling wc_query_test from another python script which goes into the direction of a module-type usage:
import wc_query_test
myDictonary = {'username':'wsdl', 'password':'aaaaaa', 'node':'/trees/geographic', 'url':'https://my.server.de'}
wc_query_test.main(myDictonary)
All three versions yield the same output as expected, for example:
~/PycharmProjects/webctrl$ ./dist/wc_query_test/wc_query_test -u aawrg -p wgAWER -n YWERGAEWR
Username: aawrg
Node: YWERGAEWR
URL: https://webctrl.rz-berlin.mpg.de
The **kwargs is for passing a dictionary, or keyword=value pairs to a function. args = parser.parse_args() returns an argparse.Namespace object, not a dictionary. But vars(args) produces a dictionary from it.
In [2]: def foo1(args):
...: print(args)
...: print(args.foo)
...:
In [3]: def foo2(**kwargs):
...: print(kwargs)
...: print(kwargs['foo'])
In [12]: p = argparse.ArgumentParser()
In [13]: p.add_argument('--foo');
In [14]: args = p.parse_args('--foo one'.split())
In [15]: args
Out[15]: Namespace(foo='one')
pass args to foo1:
In [16]: foo1(args)
Namespace(foo='one')
one
try it with foo2
In [17]: foo2(args)
...
TypeError: foo2() takes 0 positional arguments but 1 was given
In [20]: foo2(**args)
TypeError: foo2() argument after ** must be a mapping, not Namespace
but pass the expanded dictionary version:
In [18]: vars(args)
Out[18]: {'foo': 'one'}
In [19]: foo2(**vars(args))
{'foo': 'one'}
one

Python GetHostId.py getting sys.argv[1] IndexError: list index out of range

i am working on a python script to be a multi tool for getting DNS information on servers in a enterprise env. so far the script i have is using python 3.5. i am using argparse for creating command line options, which i am trying to create an if/ elif / else statement which contains the different selections. the main error message i am getting is:
./GetHostName.py
Traceback (most recent call last):
File "./GetHostName.py", line 34, in <module>
remoteServer = sys.argv[1]
IndexError: list index out of range
that is when the command is run by itself.
when it is run with a host name at the end ./GetHostName.py hostName
it gives this message:
GetHostName.py: error: unrecognized arguments: hostName
I didn't put real name of server for security issues....
When i use the argparse options say like the -f option for getting the FQDN, it gives this response...
./GetHostName.py -f hostName
3
-f
from the way it appears, it is taking the -f as input for the server name, when it should only be the input for argparse input. i have tried everything to fix it that i can think of. i have encased the main code body in a main function, that didn't work so i removed it. i use the try: statement and exception statements. that didn't work. i am wondering if there is something just basically wrong with my programming logic at this point...
this here is the code from the script:
#!C:\Bin\Python35\python.exe
#
# import libraries
import sys, os
import argparse as ap
import socket
# Command Line interface setup
def argParse():
#Command Line arg parse
parser=ap.ArgumentParser(description='A tool to get a remote servers DNS information.')
parser.add_argument("-a", "--address", default="fqdn", help="Gets IP address from host name.")
parser.add_argument("-f", "--fqdn", default="fqdn", help="Gets the FQDN address of server.")
parser.add_argument("-d", "--addrinfo", default="fqdn", help="Gets the FQDN address of server.")
parser.add_argument("-l", "--local", default="fqdn", help="Gets info on local host.")
parser.add_argument("-Pr", "--proto", default="fqdn", help="Translate an Internet protocol name to a constant suitable for passing as the (optional) third argument to the socket() function.")
parser.add_argument("-n", "--nameinfo", default="fqdn", help="Gets name and port on remote host.")
parser.add_argument("-Sn", "--servbyname", default="fqdn", help="Translate an Internet service name and protocol name to a port number for that service.")
parser.add_argument("-Sp", "--servbyport", default="fqdn", help="Translate an Internet port number and protocol name to a service name for that service.")
parser.add_argument("-t", "--timeout", default="fqdn", help="Return the default timeout in seconds for new socket objects.")
parser.add_argument("-v", "--verbose", default="fqdn", help="Increase output verbosity")
return parser.parse_args()
#remoteServer = input().strip().split()
args=argParse()
if args.fqdn:
remoteServer = sys.argv[1]
print (len(sys.argv))
remoteServerIP = socket.getfqdn(remoteServer)
print (remoteServerIP)
elif args.address:
remoteServer = sys.argv[2]
print (len(sys.argv))
remoteServerIP = socket.gethostbyname(remoteServer)
print (remoteServerIP)
elif args.addrinfo:
remoteServer = sys.argv[3]
print (len(sys.argv))
remoteServerIP = socket.getaddrinfo(remoteServer)
print (remoteServerIP)
elif args.local:
remoteServer = sys.argv[4]
print (len(sys.argv))
remoteServerIP = socket.gethostname()
print (remoteServerIP)
elif args.proto:
remoteServer = sys.argv[5]
print (len(sys.argv))
remoteServerIP = socket.getprotobyname(remoteServer)
print (remoteServerIP)
elif args.servbyname:
remoteServer = sys.argv[6]
print (len(sys.argv))
remoteServerIP = socket.getservbyname(remoteServer)
print (remoteServerIP)
elif args.servbyport:
remoteServer = sys.argv[7]
print (len(sys.argv))
remoteServerIP = socket.getservbyport(remoteServer)
print (remoteServerIP)
elif args.timeout:
remoteServer = sys.argv[8]
print (len(sys.argv))
remoteServerIP = socket.getdefaulttimeout(remoteServer)
print (remoteServerIP)
elif args.verbose:
remoteServer = sys.argv[9]
print (len(sys.argv))
remoteServerIP = socket.gethostbyaddr(remoteServer)
print (remoteServerIP)
else:
args.nameinfo
remoteServer = sys.argv[10]
print (len(sys.argv))
remoteServerIP = socket.getnameinfo(remoteServer)
print (remoteServerIP)
any help would be appreciated. please note that when i run a script with just this in it, it works just fine:
#!C:\Bin\Python35\python.exe
#
import sys, os
import argparse
import socket
# Command Line interface setup
def main():
remoteServer = sys.argv[1]
remoteServerIP = socket.gethostbyaddr(remoteServer)
print (remoteServerIP)
if __name__ == '__main__':
main()
thanks in advance.
-Betzelel
P.S. the code may look out of format, due to having to copy and paste into this blog, and manually putting 4 spaces on to each line to get it to show up as code lol.
I've had this problem long time ago. To fix this I've changed
parser.add_argument("-a", "--address", default="fqdn", help="Gets IP address from host name.")
in
parser.add_argument("-a", "--address", default="fqdn", help="Gets IP address from host name.", dest=ipfromhostname)
So for getting the value from -a you have to change
remoteServer = sys.argv[1]
in
remoteServer = args.ipfromhostname
where ipfromhostname is the dest value.
EDIT:
You have to do this operation for every parser.add_argument

Categories