Calling a subprocess in python with environmental variables - python

I am trying to write a python script to automatically scan a section of plex using the Plex Media Scanner. To do so, I must run the scanner as the user running plex (in this case it is 'plex') as well as provide it with the environment variable 'LD_LIBRARY_PATH'. I've tried using both subprocess.call and subprocess.Popen with no difference. In either case, I am not getting any output.
Here is the code I am using:
#!/usr/bin/python
import os
import subprocess
import shlex
env = os.environ.copy()
env['LD_LIBRARY_PATH'] = '/usr/lib/plexmediaserver'
s = "/bin/su - plex -c '/usr/lib/plexmediaserver/Plex\ Media\ Scanner -s -c 2'"
task = shlex.split(s)
exitCode = subprocess.call(task, env=env, shell=True)
Now I already have a working version that does what I want it to do but I had to resort to using a wrapper bash script to do so. You can see the code below:
#!/bin/sh
export LD_LIBRARY_PATH=/usr/lib/plexmediaserver
/usr/lib/plexmediaserver/Plex\ Media\ Scanner $#
And the relevant line of the script which calls it:
exitCode = subprocess.call("/bin/su - plex -c '/var/lib/deluge/delugeScripts/pms.sh -s -c 2'", shell=True)
Thanks for your help.

As jordanm noted in his comment:
the - in su makes it a login shell which re-initializes the environment.

Related

python http server hide console

I am trying to do a script that is hosting my file on my local network, here's my code :
import os
import getpass
os.system('python -m http.server --directory C:/Users/'+getpass.getuser())
But the probleme is that the http console is showing on my Desktop and that's annoying ! so I tried to hide by renaming the file in .pyw but it's not working.
Have you any idea on how to hide this console ? Thank you :D
On Linux you can use Nohup to ignore the HUP signal.
You could add nohup on your code like this:
import os
import getpass
os.system('nohup python -m http.server --directory C:/Users/'+getpass.getuser())
Update
Solution for windows
import os
import subprocess
import getpass
env = os.environ
directory = 'C:/Users/'+getpass.getuser()
proc = subprocess.Popen(['python', '-m', 'http.server', '--directory', directory], env=env)
Assuming you're on Linux (or other unix based OS), you can detach the process from the console after starting the server.
Here is one way to do it with screen command
sudo apt install -Y screen
And then
screen -d -m "python3 script.py"
Where script.py is the snippet you have shared.
Reference for the flags
...
-d -m
Start screen in detached mode. This creates a new session but doesn’t attach to it. This is useful for system startup scripts.
I found a way to do it, with a VBS script:
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run chr(34) & "main.py" & Chr(34), 0
Set WshShell = Nothing
Just replace main.py with the path of your script.

Python script for Network Packet Capture in Nifi

I am new to the nifi platform.
I am trying to use a python script to capture network packet which works on VScode and want to implement same script using NiFi but unable to do so.
This python code I used:
import os, subprocess
from subprocess import PIPE
from datetime import datetime
n = 10
filename = str(datetime.now()).replace(" ","")
b = subprocess.run(f'sudo tcpdump udp -e -i wlp6s0 -nn -vvv -c {n} -w {filename}.raw',shell=True)
c = '"X%02x"'
a = subprocess.run(f"sudo hexdump -v -e '1/1 {c}' {filename}.raw| sed -e 's/\s\+//g' -e 's/X/\\x/g' ", shell=True , stdout=PIPE, stderr=PIPE)
output_file = open (f'{filename}.txt', 'w')
output_file.write(str(a.stdout))
# print("*************************File Created*************************")
output_file.close()
I am using Execute Script Processor for implementing the python script. But it doesn't seem to be working. For executing the "sudo command" I have set to use no password so that no input is needed while executing the script.
Thank you!
Since you're just calling shell commands, you might consider ExecuteStreamCommand instead. You can still run the top-level Python script to call the subprocesses, but since you're not working with flowfile attributes you might be better served being able to call "real" Python. In ExecuteScript the engine is actually Jython and it doesn't let you import native (CPython) modules such as scikit, you can only import pure Python modules (Python scripts that don't themselves import native modules)

How to run sudo commands in shell/linux using python script

How to run sudo bash using python script
import subprocess
import os
sudoPassword2 = 'abcd1234'
command2 = 'sudo bash'
p2 = os.system('echo %s|sudo -S %s' % (sudoPassword2, command2))
I'm getting this error:
bash: line 1: abcd1234: command not found
when i tried to this also its giving error
import shlex
import subprocess
command1 = shlex.split('cd /home/backups')
subprocess.call(command1)
error cd no file or dir
tried also this :
import shlex
import subprocess
subprocess.call(["cd","/home","/backups"])
You can use os module
import os
os.system("sudo and the code you want to run")
in example:
import os
os.system("sudo apt-get vlc")
You are receiving this error because your command posts the password to the cli first without being asked for it. So bash will interpret it as a command which, obviously, can not be executed.
Better do os.system('sudo command') and call the script as root or via sudo. This will make sure you have the necessary privileges within the script immediately at run time.
Another reason why you definitely want to refrain from doing what you do is the necessity of having the sudo password for your machine written into the script in plain text. Never do that. It's evil.
If there is no way around you can make sudo execute a command without asking for a password by adding NOPASSWD directives to the /etc/sudoers by using the editor visudo (never use anything different) like so:
user host = (root) NOPASSWD: /sbin/shutdown
user host = (root) NOPASSWD: /sbin/reboot
But if you do make sure you know that this opens the execution of this command to anyone on the system without needing elevated rights. This can be a huge security risk.

Using subprocess to execute shell script with sudo [duplicate]

I'm trying to write a small script to mount a VirtualBox shared folder each time I execute the script. I want to do it with Python, because I'm trying to learn it for scripting.
The problem is that I need privileges to launch mount command. I could run the script as sudo, but I prefer it to make sudo by its own.
I already know that it is not safe to write your password into a .py file, but we are talking about a virtual machine that is not critical at all: I just want to click the .py script and get it working.
This is my attempt:
#!/usr/bin/env python
import subprocess
sudoPassword = 'mypass'
command = 'mount -t vboxsf myfolder /home/myuser/myfolder'
subprocess.Popen('sudo -S' , shell=True,stdout=subprocess.PIPE)
subprocess.Popen(sudoPassword , shell=True,stdout=subprocess.PIPE)
subprocess.Popen(command , shell=True,stdout=subprocess.PIPE)
My python version is 2.6
Many answers focus on how to make your solution work, while very few suggest that your solution is a very bad approach. If you really want to "practice to learn", why not practice using good solutions? Hardcoding your password is learning the wrong approach!
If what you really want is a password-less mount for that volume, maybe sudo isn't needed at all! So may I suggest other approaches?
Use /etc/fstab as mensi suggested. Use options user and noauto to let regular users mount that volume.
Use Polkit for passwordless actions: Configure a .policy file for your script with <allow_any>yes</allow_any> and drop at /usr/share/polkit-1/actions
Edit /etc/sudoers to allow your user to use sudo without typing your password. As #Anders suggested, you can restrict such usage to specific commands, thus avoiding unlimited passwordless root priviledges in your account. See this answer for more details on /etc/sudoers.
All the above allow passwordless root privilege, none require you to hardcode your password. Choose any approach and I can explain it in more detail.
As for why it is a very bad idea to hardcode passwords, here are a few good links for further reading:
Why You Shouldn’t Hard Code Your Passwords When Programming
How to keep secrets secret
(Alternatives to Hardcoding Passwords)
What's more secure? Hard coding credentials or storing them in a database?
Use of hard-coded credentials, a dangerous programming error: CWE
Hard-coded passwords remain a key security flaw
sudoPassword = 'mypass'
command = 'mount -t vboxsf myfolder /home/myuser/myfolder'
p = os.system('echo %s|sudo -S %s' % (sudoPassword, command))
Try this and let me know if it works. :-)
And this one:
os.popen("sudo -S %s"%(command), 'w').write('mypass')
To pass the password to sudo's stdin:
#!/usr/bin/env python
from subprocess import Popen, PIPE
sudo_password = 'mypass'
command = 'mount -t vboxsf myfolder /home/myuser/myfolder'.split()
p = Popen(['sudo', '-S'] + command, stdin=PIPE, stderr=PIPE,
universal_newlines=True)
sudo_prompt = p.communicate(sudo_password + '\n')[1]
Note: you could probably configure passwordless sudo or SUDO_ASKPASS command instead of hardcoding your password in the source code.
Use -S option in the sudo command which tells to read the password from 'stdin' instead of the terminal device.
Tell Popen to read stdin from PIPE.
Send the Password to the stdin PIPE of the process by using it as an argument to communicate method. Do not forget to add a new line character, '\n', at the end of the password.
sp = Popen(cmd , shell=True, stdin=PIPE)
out, err = sp.communicate(_user_pass+'\n')
subprocess.Popen creates a process and opens pipes and stuff. What you are doing is:
Start a process sudo -S
Start a process mypass
Start a process mount -t vboxsf myfolder /home/myuser/myfolder
which is obviously not going to work. You need to pass the arguments to Popen. If you look at its documentation, you will notice that the first argument is actually a list of the arguments.
I used this for python 3.5. I did it using subprocess module.Using the password like this is very insecure.
The subprocess module takes command as a list of strings so either create a list beforehand using split() or pass the whole list later. Read the documentation for moreinformation.
#!/usr/bin/env python
import subprocess
sudoPassword = 'mypass'
command = 'mount -t vboxsf myfolder /home/myuser/myfolder'.split()
cmd1 = subprocess.Popen(['echo',sudoPassword], stdout=subprocess.PIPE)
cmd2 = subprocess.Popen(['sudo','-S'] + command, stdin=cmd1.stdout, stdout=subprocess.PIPE)
output = cmd2.stdout.read.decode()
sometimes require a carriage return:
os.popen("sudo -S %s"%(command), 'w').write('mypass\n')
Please try module pexpect. Here is my code:
import pexpect
remove = pexpect.spawn('sudo dpkg --purge mytool.deb')
remove.logfile = open('log/expect-uninstall-deb.log', 'w')
remove.logfile.write('try to dpkg --purge mytool\n')
if remove.expect(['(?i)password.*']) == 0:
# print "successfull"
remove.sendline('mypassword')
time.sleep(2)
remove.expect(pexpect.EOF,5)
else:
raise AssertionError("Fail to Uninstall deb package !")
To limit what you run as sudo, you could run
python non_sudo_stuff.py
sudo -E python -c "import os; os.system('sudo echo 1')"
without needing to store the password. The -E parameter passes your current user's env to the process. Note that your shell will have sudo priveleges after the second command, so use with caution!
I know it is always preferred not to hardcode the sudo password in the script. However, for some reason, if you have no permission to modify /etc/sudoers or change file owner, Pexpect is a feasible alternative.
Here is a Python function sudo_exec for your reference:
import platform, os, logging
import subprocess, pexpect
log = logging.getLogger(__name__)
def sudo_exec(cmdline, passwd):
osname = platform.system()
if osname == 'Linux':
prompt = r'\[sudo\] password for %s: ' % os.environ['USER']
elif osname == 'Darwin':
prompt = 'Password:'
else:
assert False, osname
child = pexpect.spawn(cmdline)
idx = child.expect([prompt, pexpect.EOF], 3)
if idx == 0: # if prompted for the sudo password
log.debug('sudo password was asked.')
child.sendline(passwd)
child.expect(pexpect.EOF)
return child.before
It works in python 2.7 and 3.8:
from subprocess import Popen, PIPE
from shlex import split
proc = Popen(split('sudo -S %s' % command), bufsize=0, stdout=PIPE, stdin=PIPE, stderr=PIPE)
proc.stdin.write((password +'\n').encode()) # write as bytes
proc.stdin.flush() # need if not bufsize=0 (unbuffered stdin)
without .flush() password will not reach sudo if stdin buffered.
In python 2.7 Popen by default used bufsize=0 and stdin.flush() was not needed.
For secure using, create password file in protected directory:
mkdir --mode=700 ~/.prot_dir
nano ~/.prot_dir/passwd.txt
chmod 600 ~/.prot_dir/passwd.txt
at start your py-script read password from ~/.prot_dir/passwd.txt
with open(os.environ['HOME'] +'/.prot_dir/passwd.txt') as f:
password = f.readline().rstrip()
import os
os.system("echo TYPE_YOUR_PASSWORD_HERE | sudo -S TYPE_YOUR_LINUX_COMMAND")
Open your ide and run the above code. Please change TYPE_YOUR_PASSWORD_HERE and TYPE_YOUR_LINUX_COMMAND to your linux admin password and your desired linux command after that run your python script. Your output will show on terminal. Happy Coding :)
You can use SSHScript . Below are example codes:
## filename: example.spy
sudoPassword = 'mypass'
command = 'mount -t vboxsf myfolder /home/myuser/myfolder'
$$echo #{sudoPassword} | sudo -S #{command}
or, simply one line (almost the same as running on console)
## filename: example.spy
$$echo mypass | sudo -S mount -t vboxsf myfolder /home/myuser/myfolder
Then, run it on console
sshscript example.spy
Where "sshscript" is the CLI of SSHScript (installed by pip).
solution im going with,because password in plain txt in an env file on dev pc is ok, and variable in the repo and gitlab runner is masked.
use .dotenv put pass in .env on local machine, DONT COMMIT .env to git.
add same var in gitlab variable
.env file has:
PASSWORD=superpass
from dotenv import load_dotenv
load_dotenv()
subprocess.run(f'echo {os.getenv("PASSWORD")} | sudo -S rm /home//folder/filetodelete_created_as_root.txt', shell=True, check=True)
this works locally and in gitlab. no plain password is committed to repo.
yes, you can argue running a sudo command w shell true is kind of crazy, but if you have files written to host from a docker w root, and you need to pro-grammatically delete them, this is functional.

Python - Executing shell command does not work on Linux

I like to run a shell command from Python on my Linux Mint system.
Specifically the command runs all Bleachbit cleaners and works perfectly
fine when run maually.
Yet, trying to run the same command via the subprocess.call module
always results in an exception raised.
I just can not see why it should not work.
The command does not require sudo rights, so not requiring
right not given.
I also have firefox/browsers closed when executing the python command.
Anybody, any suggestions how to fix this issue?
My code:
try:
subprocess.call('bleachbit -c firefox.*')
except:
print "Error."
subprocess module does not run the shell by default therefore the shell wildcards (globbing patterns) such as * are not expanded. You could use glob to expand it manually:
#!/usr/bin/env python
import glob
import subprocess
pattern = 'firefox.*'
files = glob.glob(pattern) or [pattern]
subprocess.check_call(["bleachbit", "-c"] + files)
If the command is more complex and you have full control about its content then you could use shell=True to run it in the shell:
subprocess.check_call("bleachbit -c firefox.*", shell=True)
When shell is False you need to pass a list of args:
import subprocess
try:
subprocess.call(["bleachbit", "-c","firefox.*"])
except:
print ("Error.")

Categories

Resources