This question already has answers here:
Why does passing variables to subprocess.Popen not work despite passing a list of arguments?
(5 answers)
Closed 1 year ago.
When I pass a variable to a BAT file using the following:
from subprocess import call
# Prompt for UID
UID = raw_input('Enter UID: ')
# Prompt for password
PSWD= raw_input('Enter your password: ')
dir = r"f:\_Python"
cmdline = "setENVvariables.bat UID, PSWD"
rc=call("start cmd /K " + cmdline, cwd=dir, shell=True)
.. the values are not passed. When I echo the input in the BAT file, I get the Python variable name
BAT file
echo %1
echo %2
BAT File output
f:\_Python>echo UID
UID
f:\_Python>echo PSWD
PSWD
f:\_Python>
You're invoking a shell to run start that will run a CMD to run your BAT file!
That means you want to run a subprocess, but end up starting FOUR instead!
Don't use shell=True
Don't use start unless you really need it
Don't execute CMD
By doing this you can just pass your parameters as a list and it will work:
dir = r"f:\_Python"
cmdline = ["setENVvariables.bat", UID, PSWD]
rc = call(cmdline, cwd=dir)
Related
Python 3.10.6
Windows 10
I have a python function that executes a DXL script using subsystem.run() or os.system() (whichever works best I guess). The problem is that when I run a custom command using python it does not work, but when I paste the same command in the command prompt, it works. I should also clarify that command prompt is not the ms store windows terminal (cannot run ibm doors commands there for some reason). It is the OG prompt
I need to use both python and IBM Doors for the solution.
Here is a summer version of my code (Obviously, the access values are not real):
#staticmethod
def run_dxl_importRTF():
dquotes = chr(0x22) # ASCII --> "
module_name = "TEST_TEMP"
script_path = "importRTF.dxl"
script_do_nothing_path = "doNothing.dxl"
user = "user"
password = "pass"
database_config = "11111#11.11.1111.0"
doors_path = dquotes + r"C:\Program Files\IBM\Rational\DOORS\9.7\bin\doors.exe" + dquotes
file_name = "LIBC_String.rtf"
# Based On:
# "C:\Program Files\IBM\Rational\DOORS\9.7\\bin\doors.exe" -dxl "string pModuleName = \"%~1\";string pFilename = \"%~2\";#include <importRTF.dxl>" -f "%TEMP%" -b "doNothing.dxl" -d 11111#11.11.1111.0 -user USER -password PASSWORD
script_arguments = f"{dquotes}string pModuleName=\{dquotes}{module_name}\{dquotes};string pFileName=\{dquotes}{file_name}\{dquotes};#include <{script_path}>{dquotes}"
command = [doors_path, "-dxl", script_arguments, "-f", "%TEMP%", "-b", script_do_nothing_path, '-d', database_config, '-user', user, '-password', password]
res = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
print(f"COMMAND:\n{' '.join(res.args)}")
print(f"STDERR: {repr(res.stderr)}")
print(f'STDOUT: {res.stdout}')
print(f'RETURN CODE: {res.returncode}')
return
PYTHON SCRIPT OUTPUT:
COMMAND:
"C:\Program Files\IBM\Rational\DOORS\9.7\bin\doors.exe" -dxl "string pModuleName=\"TEST_TEMP\";string pFileName=\"LIBC_String.rtf\";#include <importRTF.dxl>" -f %TEMP% -b doNothing.dxl -d 11111#11.11.1111.0 -user USER_TEMP -password PASS_TEMP
STDERR: 'The system cannot find the path specified.\n'
STDOUT:
RETURN CODE: 1
When I run the same command in the command prompt, it works (dxl script is compiled).
I identified the problem which is the script_argument variable. Meaning that, when I try to just enter the IBM Doors server without compiling a DXL script, it works on python and the command prompt.
The python script needs to be dynamic meaning that all of the initial declared variables can change value and have a path string in it. I am also trying to avoid .bat files. They also did not work with dynamic path values
Thanks for your time
I tried:
Changing CurrentDirectory (cwd) to IBM Doors
os.system()
Multiple workarounds
Tried IBM Doors path without double quotes (it doesnt work because of the whitespaces)
.bat files
When calling subprocess.run with a command list and shell=True, python will expand the command list to a string, adding more quoting along the way. The details are OS dependent (on Windows, you always have to expand the list to a command) but you can see the result via the subprocess.list2cmdline() function.
Your problem is these extra escapes. Instead of using a list, build a shell command string that already contains the escaping you want. You can also use ' for quoting strings so that internal " needed for shell quoting can be entered literally.
Putting it all together (and likely messing something up here), you would get
#staticmethod
def run_dxl_importRTF():
module_name = "TEST_TEMP"
script_path = "importRTF.dxl"
script_do_nothing_path = "doNothing.dxl"
user = "user"
password = "pass"
database_config = "11111#11.11.1111.0"
doors_path = r"C:\Program Files\IBM\Rational\DOORS\9.7\bin\doors.exe"
file_name = "LIBC_String.rtf"
script_arguments = (rf'string pModuleName=\"{module_name}\";'
'string pFileName=\"{file_name}\";'
'#include <{script_path}>')
command = (f'"{doors_path}" -dxl "{script_arguments}" -f "%TEMP%"'
' -b "{script_do_nothing_path}" -d {database_config}'
' -user {user} -password {pass}')
res = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
print(f"COMMAND:\n{' '.join(res.args)}")
print(f"STDERR: {repr(res.stderr)}")
print(f'STDOUT: {res.stdout}')
print(f'RETURN CODE: {res.returncode}')
This question already has answers here:
Running shell command and capturing the output
(21 answers)
Closed 2 years ago.
Below is the script for searching a input data in a given OS.system command ( copied to file out.txt) and prints the line of the given input data. Now I want to put the output i.e line in another OS.system command. For example symaccess -sid 567 show -name xxx -type init where xxx is the output of the previous OS.system command i.e line.
Note - I can use only python 2.6.6 and the scripts related to storage
import os
os.system('symaccess -sid 456 list -type init > out.txt')
server = raw_input("server name:")
with open('out.txt', 'rt') as in_f:
for line in in_f:
if server in line:
print line
I used another method as below
import os server = raw_input("server name:")
var = "symaccess -sid 239 list -type init | grep \"{0}\"".format(server)
wwn = os.system(var)
init = 'symaccess -sid 239 -type init show {0}'.format(wwn) print init os.system(init)
above is the script i used to add a output of one os.system to another os.syste,. i got the first os.system executed but for the second one i.e os.system(init) is not coming because os.system(var) should be assigned as a variable.could someone tell how to assign a variable to os.system(init)
import subprocess
cmd= 'ls'
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
std_out = p.communicate()
Here is a possible way to access the output in Python.
Try using "subprocess.checkoutput()".
import subprocess
import os
output = subprocess.check_output(['symaccess -sid 456 list -type init'])
os.system(output)
I am writing a python script that uses plink to ssh into a linux box, execute a command, then write the output of that command to a string and return to my python script.
I would also like to not print the commands I am running to the terminal.
I have the following which executes the command and prints to terminal, but it does not return to my python script, nor can I figure out how to store the output of my command to a string.
while(True):
network_name = raw_input('\nEnter test network: ')
network_name_check = raw_input('\nYou want to test on the %s network. Is this correct? (Y/N): ' %(network_name))
if inputYNChecker(network_name_check):
print "\nVerifying Network exists as Group_Name on Control VM..."
sshCommand = "plink root#Control -pw PASSWORD"
lsCommand = "ls -1 --color=never -d */ | grep " + network_name +"\n"
sshProcess = Popen(sshCommand,shell=False,stdin=PIPE)
sshProcess.stdin.write("cd /mnt/PCAPS/GroupSetup\n")
#sshProcess.communicate("cd /mnt/PCAPS/GroupSetup\n")
sshProcess.stdin.write(lsCommand)
sshProcess.stdin.write("exit\n")
sshProcess.stdin.close()
break
print "Back to python script"
I guess I really don't understand how pipes work, as when I have stdin=PIPE and stdout=PIPE, nothing is displayed in terminal except for "Using username "root"." and then it gets hung up.
How can I:
a) Not display the commands I'm sending to the ssh session
b) Store the output of the commands (which would be a folder name) to a string
c) return to my original python program
I have this Python3 code which use Pexpect.
import pexpect
import getpass
import sys
def ssh(username,password,host,port,command,writeline):
child = pexpect.spawn("ssh -p {} {}#{} '{}'".format(port,username,host,command))
child.expect("password: ")
child.sendline(password)
if(writeline):
print(child.read())
def scp(username,password,host,port,file,dest):
child = pexpect.spawn("scp -P {} {} {}#{}:{}".format(port,file,username,host,dest))
child.expect("password: ")
child.sendline(password)
try:
filename = sys.argv[1]
print("=== sendhw remote commander ===")
username = input("Username: ")
password = getpass.getpass("Password: ")
ssh(username,password,"some.host.net","22","mkdir ~/srakrnSRV",False)
scp(username,password,"some.host.net","22",filename,"~/srakrnSRV")
ssh(username,password,"some.host.net","22","cd srakrnSRV && sendhw {}".format(filename),True)
except IndexError:
print("No homework name specified.")
My aim is to:
SSH into the host with the ssh function, create the directory srakrnSRV, then
upload a file into the srakrnSRV directory, which is previously created
cd into srakrnSRV, and execute the sendhw <filename> command. The filename variable is defined by command line parameteres, and print the result out.
After running the entire code, Python prints out
b'\r\nbash: line 0: cd: srakrnSRV: No such file or directory\r\n'
which is not expected, as the directory should be previously created.
Also, I tried manually creating the srakrnSRV folder in my remote host. After running the command again, it appears that scp function is also not running. The only runnning pexpect coomand was the last ssh function.
How to make it execute in order? Thanks in advance!
You may lack permission for executing commands through ssh. Also there is possibility that your program sends scp before prompt occurs.
This question already has answers here:
How do I pipe a subprocess call to a text file?
(2 answers)
Closed 7 years ago.
I am trying to write a python script to test a 4 digit pincode with brute forcing(and a password) when connecting to local host. The command that needs to be run is:
echo password pincode | nc localhost 30002 >> /tmp/joesPin/pinNumber
(writes response to a new file).
This worked when written as a bash script, but I am struggling with the subprocess module in Python.
import subprocess
password = "UoMYTrfrBFHyQXmg6gzctqAwOmw1IohZ"
for i in range(10000):
pincode = str('{0:04}'.format(i)) #changes 4 to 0004
subprocess.call('echo', password, pincode,'|','nc localhost 30002 >> /tmp/joesPin/' + pincode,shell=True)
I want it to call:
echo UoMYTrfrBFHyQXmg6gzctqAwOmw1IohZ 0001 | nc localhost 30002 >> /tmp/joesPin/0001
There are different ways to pipe the output of a command in Python.
Option 1: You can set the stdout argument of the subprocess.call command and write the output somewhere.
Option 2: You can use subprocess.PIPE in the Popencall and save the output to use with another command.
proc = subprocess.Popen(['echo', password, pincode], stdout=subprocess.PIPE)
output = proc.communicate()[0] # now contains the output of running "proc"
file = '/tmp/joesPin/pinNumber'
with open(file, 'a+') as out:
subprocess.call(['nc localhost 30002'], stdout=out, shell=True)
Setting the stdout field in subprocess.call writes the output of the subprocess to the file descriptor given in stdout.
To use the output of the 1st process as the stdin input of the 2nd process:
proc = subprocess.Popen(['echo', password, pincode], stdout=subprocess.PIPE)
output = proc.communicate()[0] # now contains the output of running "proc"
file = '/tmp/joesPin/pinNumber'
proc2 = subprocess.Popen(['nc localhost 30002'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=True)
proc2.stdin.write(output)
result = proc2.communicate()[0]
# now you can write the output to the file:
with open (file, 'a+') as outfile:
outfile.write(result)