Why does python's Popen fail to pass environment variables on Mac OS X? - python-3.x

I am writing a program that needs to spawn a new terminal window and launch a server in this new terminal window (with environment variables passed to the child process).
I have been able to achieve this on windows 10 and linux without much trouble but on Mac OS X (Big Sur) the environment variables are not being passed to the child process. Here is an example code snippet capturing the behaviour I want to achieve:
#!/usr/bin/python3
import subprocess
import os
command = "bash -c 'export'"
env = os.environ.copy()
env["MYVAR"] = "VAL"
process = subprocess.Popen(['osascript', '-e', f"tell application \"Terminal\" to do script \"{command}\""], env=env)
Unfortunately, MYVAR is not present in the exported environment variables.
Any ideas if I am doing something wrong here?
Is this a bug in python's standard library ('subprocess' module)?
edit - thank you Ben Paterson (previously my example code had a bug) - I have updated the code example but I still have the same issue.
edit - I have narrowed this down further. subprocess.Popen is doing what it is supposed to do with environment variables when I do:
command = "bash -c 'export > c.txt'"
process = subprocess.Popen(shlex.split(command, posix=1), env=env)
But when I try to wrap the command with osascript -e ... (to spawn it in a new terminal window) the environment variable "MYVAR" does not appear in the c.txt file.
command = "bash -c 'export > c.txt'"
process = subprocess.Popen(['osascript', '-e', f"tell application \"Terminal\" to do script \"{command}\""], env=env)

dict.update returns None, so the OP code is equivalent to passing env=None to subprocess.Popen. Write instead:
env = os.environ.copy()
env["MYVAR"] = "VAL"
subprocess.Popen(..., env=env)

Related

Looking for more efficient way to pass arguments to subprocess.Popen

I have received a task that requires a python script to run on devices in our environment. The script should check for a certain criteria and generate an empty file in a subdirectory of /var/opt.
The script is called by a 3rd party application which results in the file being generated with this selinux context type "unconfined_u:object_r:var_t:s0". The script should update the selinux context type to "system_u:object_r:var_t:s0"
I originally create the script to use the python selinux module, but during testing we found that a large number of devices do not have the selinux module installed.
I modified the script to use the Linux commands (semanage and restorecon) and although it works, it just does not look right. I am still learning so if any guidance on how this code could be more efficient, it would be greatly appreciated.
Current Code:
if os.path.isfile("/usr/sbin/selinuxenabled"):
userdir = "/var/opt/abcdir"
check_se = subprocess.run(["/usr/sbin/selinuxenabled"]).returncode
# Set command and arguments for semanage command
se_cmd = "/usr/sbin/semanage"
se_args1 = "fcontext"
se_args2 = "-a"
se_args3 = "-t"
se_args4 = "var_t"
se_args5 = "-s system_u"
# Set command and arguments for restorecon command
re_cmd = "/usr/sbin/restorecon"
re_args1 = "-FR"
if check_se == 0:
log.info("selinux enabled")
subprocess.Popen([se_cmd,
se_args1,
se_args2,
se_args3,
se_args4,
se_args5,
userdir],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL)

SSH command varaible not being seen

I am trying to pass a variable using a remote SSH command connection. I want to rename the data file with the station variable. The SSH command is being run on a Windows PC to a Ubuntu PC. When the script is run from Python on the Windows PC it makes the connection but won’t rename the file. Can someone suggest what I am doing wrong?
import paramiko
ssh_client =paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_client.connect(hostname="192.168.1.xx",username="xx",password="xxxx")
station = "NAA"
stdin,stdout,stderr=ssh_client.exec_command(
"mv /home/pi/vlfrx-tools/data/station.data \
/home/pi/vlfrx-tools/data/$station.dat")
station is variable in Python, not in shell - and you need Python functions, not shell $
string-formatting ("{}".format(station))
cmd = "mv /home/pi/vlfrx-tools/data/station.data \
/home/pi/vlfrx-tools/data/{}.dat".format(station)
print("CMD:", cmd)
stdin, stdout, stderr = ssh_client.exec_command(cmd)
or f-string (f"{station}")
cmd = f"mv /home/pi/vlfrx-tools/data/station.data \
/home/pi/vlfrx-tools/data/{station}.dat"
print("CMD:", cmd)
stdin, stdout, stderr = ssh_client.exec_command(cmd)
or old method with % and %s ("%s" % station)
cmd = "mv /home/pi/vlfrx-tools/data/station.data \
/home/pi/vlfrx-tools/data/%s.dat" % station
print("CMD:", cmd)
stdin, stdout, stderr = ssh_client.exec_command(cmd)
See more on page PyFormat.info
EDIT:
It is not tested but probably you could use $station if you set shell variable using EXPORT - but it still need to use Python to format string.
cmd = "EXPORT station={} ; mv ... .../$station.dat".format(station)
I'm not sure but this shell variable can be temporary and you may n need to set it in every exec_command() which need it.

how to get a variable of a python file from bash script

I have a python file, conf.py which is used to store configuration variables. conf.py is given below:
import os
step_number=100
I have a bash script runner.sh which tries to reach the variables from conf.py:
#! /bin/bash
#get step_number from conf file
step_number_=$(python ./conf.py step_number)
However, if I try to print the step_number_ with echo $step_number_, it returns empty value. Can you please help me to fix it?
$(command) is replaced with the standard output of the command. So the Python script needs to print the variable so you can substitute it this way.
import os
step_number = 100
print(step_number)

Can i access the variables of the python script after run that python script with console?

I run the python script using terminal command
python3 myScript.py
It's simply run my program but if i want to open python console after complete run of my script so that i can access my script's variables.
So, What should i do ? and How can i get my script's variables after run the code using terminal ?
Open a python terminal (type 'python' in cmd);
Paste this (replace 'myScript.py' with your script filename):
def run():
t = ""
with open('myScript.py') as f:
t = f.read()
return t
Type exec(run()). Now you will have access to the variables defined in myScript.py.
I needed to do this so I could explore the result of a request from the requests library, without having to paste the code to make the requests every time.
Make the program run the other program you want with the variables as arguments. For example:
#program1
var1=7
var2="hi"
import os
os.system("python %s %d %s" % (filename, var1, var2))
#program2
import sys
#do something such as:
print(sys.argv[1]) #for var1
print(sys.argv[2]) #for var2
Basically, you are running program2 with arguments that can be referenced later.
Hope this helps :)

remote powershell scripts on windows not running through python script in linux

I have a python script written using paramiko and pysphere.this script is in linnux box.i have some powershell scripts on windows machine which i have to run one after the other(after each script ends obviously),but the point here is through my pythonscript it is not running the powershell scripts on windows machine.Kindly help.
PS;i have to run python script fromlinux and powershell scriupts on windows.
Here is a snippet of code for running powershell scripts:
target_vm1 = connect_Esxi_Server(return_list[0])
print "Again connected to vm:" + return_list[0]
target_vm1.login_in_guest(vmUser,vmPass)
list_scripts = target_vm1.list_files(VM_SCRIPT_LOCATION)
for f in list_scripts:
size = f['size']
**if size <> 0:**
paths = f['path']
print paths
#for all_scripts in paths:
*****print "script running is :" , paths*****
path_l = os.path.join(VM_SCRIPT_LOCATION + '\\'+ paths)
*****print path_l*****
run_script =
subprocess.Popen([r'c:\\Windows\\system32\\WindowsPowerShell\\v1.0\\powershell.exe',". path_l"], shell=True)
result = run_script.wait()
print "result is:", result
I doubt whether subprocess will work.
Please note that the bold prints given above are giving the correct script to run.there are many powershell scriptsinside the fo;der,so looping throught it and running each one of them.
Any help would be appreciated,this thing is eating my heads off.....argghhhhhhhh..
Cheers,
NJ
I run powershell commands directly using paramiko:
import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('10.10.0.2', username='vipul', password='password')
cmd = "powershell -InputFormat none -OutputFormat text echo Hello"
stdin, stdout, stderr = self.ssh.exec_command(cmd)
print stdout.readlines()
Here 10.10.0.2 is my windows machine. Using cygwin sshd server for ssh.

Resources