I have been working on executing a command on hundreds of remote systems with PsExec via Python 3.4.2. I have been having problems collecting the output in a parsable fashion. I've tried several variations using subprocess.Popen
and os.system
but neither seem to be working exactly how I need them.
As mentioned above, I need to run a command on a few hundred Windows systems. The executable that I need to run and throw arguments against could exist in one of several predictable places. I decided to take inspiration from this SO post and essentially use nested if/else
statements to run the command via PsExec, collect output PsExec/Windows output, and parse output to determine success or failure (if "The system cannot find the path specified." in output:
). If the command failed, then I would run the next command variation. I know this is bad practice and I'm certainly open to alternatives.
Here's my rat's nest code block:
def f_remove_ma():
host = f_get_queue()
g_psexec_location = "PsExec.exe"
# Legacy 32-bit:
ma_install_location = "<install location 1>"
ma_arguments = "/arguments"
output = subprocess.Popen([g_psexec_location, "\\\\" + host, "-accepteula", ma_install_location, ma_arguments], stdout=subprocess.PIPE).communicate()[0]
if 'could not start' in output:
print("Install not found in location 1")
return
# Standard 64-bit:
ma_install_location = "<install location 2>"
ma_arguments = "/arguments"
output = subprocess.Popen([g_psexec_location, "\\\\" + host, "-accepteula", ma_install_location, ma_arguments], stdout=subprocess.PIPE).communicate()[0]
if "The system cannot find the path specified." in output:
# Standard 32-bit:
ma_install_location = "<install location 3>"
ma_arguments = "/arguments"
output = subprocess.Popen([g_psexec_location, "\\\\" + host, "-accepteula", ma_install_location, ma_arguments], stdout=subprocess.PIPE).communicate()[0]
if "The system cannot find the path specified." in output:
# New 32/64-bit:
ma_install_location = "<install location 4>"
ma_arguments = "/arguments"
output = subprocess.Popen([g_psexec_location, "\\\\" + host, "-accepteula", ma_install_location, ma_arguments], stdout=subprocess.PIPE).communicate()[0]
if "The system cannot find the path specified." in output:
# New 32/64-bit:
ma_install_location = "<install location 5>"
ma_arguments = "/arguments"
output = subprocess.Popen([g_psexec_location, "\\\\" + host, "-accepteula", ma_install_location, ma_arguments], stdout=subprocess.PIPE).communicate()[0]
if "The system cannot find the path specified." in output:
print("No known versions of software found.")
else:
print(output)
else:
print(output)
else:
print(output)
else:
print(output)
else:
print(output)
This method seems promising at first, but it is currently hanging for me right after PsExec execution. Below is the output.
PsExec v2.11 - Execute processes remotely
Copyright (C) 2001-2014 Mark Russinovich
Sysinternals - www.sysinternals.com
At one time I got it to actually output something, but since the output was in bytecode it wasn't parsable as a string. At the time, I tried doing .decode(output)
which didn't help me any.
Here are some of the internet research I found on the topic that has helped so far:
Python Popen hanging with psexec - undesired results
Calling psexec from a python script doesn't show the whole output
Why does Popen.communicate() return b'hi\n' instead of 'hi'?
... and finally this one which isn't fully implemented in Python and doesn't seem to work for me anyways.
**Edit: Adding the feeder queue functions for "host"
def f_create_queue(ip_list):
global g_queue
g_queue
for ip in ip_list:
g_queue.put(ip)
print("\nQueue has {} items ready for processing\n".format(g_queue.qsize()))
def f_get_queue():
global g_queue
return g_queue.get()
So with all of this, I have a few questions:
- Why is PsExec hanging after initial execution?
- How do I capture everything (including PsExec output) in Python?
- Is there a better way I can do the multiple nested If/Else statements?
Thanks in advance!