Not able to execute sudo command using subprocess - python

I'm trying to change brightness by editing the brightness file in intel_backlight folder using Python Subprocess.
Cannot run the script with sudo priv.
Have tried mostly everything but still no luck...
Could you please help me a little as to where I'm going wrong.
Tried following:
With xbacklight package not working.
With xrandr colour getting dim but not brightness.
With changing the value of the file(work in shell with sudo but wanted through python with using sudo for calling python file).
#
command = "sudo echo " + "'" + str(new_brightness_level) + "'" + ">" + "/sys/devices/pci0000:00/0000:00:02.0/drm/card0/card0-eDP-1/intel_backlight/brightness"
subprocess.Popen(command,shell=True)
command2 = "echo {} | sudo -S tee /sys/devices/pci0000:00/0000:00:02.0/drm/card0/card0-eDP-1/intel_backlight/brightness ".format(new_brightness_level).split()
c2 =subprocess.Popen(command2,shell=True,stdin=subprocess.PIPE,universal_newlines=True)
res = c2.communicate(sudo_pass + '\n')[1]
#
command = "echo " + "'" + str(new_brightness_level) + "'" + "sudo -S > /sys/devices/pci0000:00/0000:00:02.0/drm/card0/card0-eDP-1/intel_backlight/brightness"
cmd2 = subprocess.Popen(['sudo', '-S'] + command.split(),stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
Thanks for the help in advance!!!

Was trying different things and finally found a workable solution to it :
command3 = "echo {} | tee /sys/devices/pci0000:00/0000:00:02.0/drm/card0/card0-eDP-1/intel_backlight/brightness ".format(new_brightness_level)
command4 = " sudo -S bash -c '{}' ".format(command3)
c1 =subprocess.Popen(command4,shell=True,stdin=subprocess.PIPE,universal_newlines=True)
res = c1.communicate(sudo_pass + '\n')[1]
In command 3 have created the command without Sudo
In command 4 first have added the sudo with -S(for getting password from
communicate function) and have then used the bash shell which will be executed as sudo so all commands will be running using sudo
Kindly correct me and add further info if anyone feels
Much appreciated

Related

how to enter bash password via python?

I apologize in advance if I'm not clear in this post but I'll try to be as clear as I can.
So I'm making a python script for installing my favourite packages in arch-linux so for eg if I ever have to do a fresh install I can just load my script and all my packages (or just one package) would be installed. I want my script to be able to install packages from different package managers.
So far I have it working with the default pacman when I use the os.system() and run it with sudo
os.system('echo %s; echo y) |sudo -S sudo %s -S %s) % (prefix, package_manager, package_name)
which could translate to
os.system('echo password123; echo y) |sudo -S sudo pacman -S python-setuptools)
But the problem arises when I use it with yaourt ( I know it's unsafe and no longer maintained but I'm just using it for testing purposes )
I can't enter the above command because I get an error message saying I can't run makepkg as root because I could greatly damage my system.
So I've tried it with
y | yaourt -S package_name
It bypasses all the confirmation messages but It get's stuck in the console at the password. I've tried looking for a command that can enter say an x amount of y's and then when it comes to the password I could enter that in with just one line of code.
I've also tried the subprocess module, with the .Popen() and .communicate() methods where I say something like
p = subprocess.Popen('yaourt -S sublime-text-dev', stdin = subprocess.PIPE, stdout=subprocess.PIPE, shell=True)
p.communicate(b'password123')
but it still gets stuck at the password phase.
I don't want to use the Pexpect module because it isn't a default package with python and you have to install pip to get it to work and I want to be able to run my script without having to manually install anything.
Here's my function just in case
def install_package_suggestion(package_dictionary, sudo_password):
package_name = input('Enter name of package to install: ').lower()
if package_name not in package_dictionary:
print(package_name + ' is not in the suggestion list')
else :
package_manager = package_dictionary[package_name][0]
prefix = '(echo %s;echo y;)|sudo -S sudo' % (sudo_password) if package_manager == 'pacman' else 'echo %s|' % (sudo_password)
command = '%s %s -S %s' % (prefix, package_manager, package_name)
res = os.system(command)
If anyone can help me at all I would greatly appreciate it !

remotely executing multiple shell commands including "df -h" using root user in python

I want to do the following thing :
if condition:
cmd="ssh machine1 && sudo su - && df -h PathThatRequiresRootPriv | grep ..."
proc = subprocess.Popen(cmd,shell=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE,env=os.environ)
(out_space,err) = proc.communicate()
if err:
print err
log.warning('%s',err)
exit(1)
But i am clearly missing something because the program doesn't do anything.
Thank you for your help in advance.
You are building commands in the form cmd1 && cmd2 && cmd3. The 3 commands are executed one at a time on the local machine unless one of them return false. And from your title it is not what you expect... And the construct sudo su - will act the same and expect its commands from its own standard input and not from the next command.
The correct way here would be:
if condition:
loc_cmd="ssh machine1"
remcmd="sudo -i 'df -h PathThatRequiresRootPriv | grep ...'"
proc = subprocess.Popen(loc_cmd,shell=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE,env=os.environ)
(out_space,err) = proc.communicate(rem_cmd)
Say differently, you should only execute ssh on the local machine, pass sudo -i to the remote as a request to execute a command after simulating an initial login, and finally pass the pipeline as the parameter to sudo.
You must look fabric - if you want use python
or ansible
in fabric you can do different things on remote server like this:
from fabric.api import *
def check_disk_space(username, passw='none'):
host = '%s#%s' % (env.user, env.host)
env.passwords[host] = 'rootPass'
# run from user
run('df -h')
# run from sudo
sudo('df -h')
host='anyuser#10.10.10.101'
execute(check_disk_space, hosts=[host], username='anyuser', passw='')
Both support 'become' methods for execute remote commands through sudo

form a subprocess.call() statement from system(cmd) command in python

I have a ssh command which I was using in a system() statement but I want to replace it with a subprocess.call() statement. My ssh command is:
cmd ="ssh -i pem-file.pem user#" + hostname + " 'cd /user/home/ && java -cp jar-file.jar com.packg.class -a opt1 -f text-file_" + ts + ".txt'"
system(cmd)
I want to replace above with a subprocess.call() statement as it is giving me some performance issues and I read that subprocess.call() is a much better option to use. I formulated this query but it is not executing:
result = subprocess.call(["ssh","-i", "pem-file.pem","user#" + hostname + " 'cd /user/home/ && java -cp jar-file.jar com.packg.class -a opt1 -f text-file_" + ts + ".txt'"])
What is the mistake I am doing and what is the correct syntax?
The function shlex.split() is useful for parsing command line arguments into the proper format. This should resolve your syntax error:
import shlex
import subprocess
cmd ="ssh -i pem-file.pem user#" + hostname + " 'cd /user/home/ && java -cp jar-file.jar com.packg.class -a opt1 -f text-file_" + ts + ".txt'"
result = subprocess.call(shlex.split(cmd))
If that doesn't fix your error, then you can pass subprocess.call the shell=True argument:
import subprocess
cmd ="ssh -i pem-file.pem user#" + hostname + " 'cd /user/home/ && java -cp jar-file.jar com.packg.class -a opt1 -f text-file_" + ts + ".txt'"
result = subprocess.call(cmd, shell=True)
Using the shell argument will cause your command to be executed through a shell, rather than having the interpreter parse it. However, don't use the shell option if cmd can ever come from an untrusted source. Take at look at the warning in the Python docs.
One more note:
subprocess.system() is newer and more flexible than os.system(), but don't worry too much about "upgrading" to the new function. The advantages of subprocess.call() are in the more flexible options for communicating with your subprocess. If all you're doing is executing a single command and getting the return code, os.system() is probably fine. If you're finding that your command is being flaky and unreliable, switching to subprocess.call() probably isn't going to help much.
Assuming there are no shell meta-characters in hostname (likely), your command could look like this: each command-line argument is a separate list item:
#!/usr/bin/env python
import subprocess
cmd = ["ssh", "-i", "pem-file.pem", "user#" + hostname,
"cd /user/home/ && java -cp jar-file.jar com.packg.class -a opt1 "
"-f text-file_" + ts + ".txt"]
subprocess.check_call(cmd)
Unlike os.system(); it doesn't run the (local) shell.
You could get the argument list using shlex.split(your_original_system_command) (mentioned by #skrrgwasme) but shlex.split() can be fooled and therefore it is mostly useful as a hint on how the result should look like.

Subprocess call providing incorrect parameters compared to ' '.join()

When I run the command
subprocess.call(['intersectBed','-u','-a',out_snv_filter,'-b',cds,'>',out_cds],shell=True)
I get the help menu for intersectBed reported back in the interpreter.
But when I run
>>> ' '.join(['intersectBed','-u','-a',out_snv_filter,'-b',cds,'>',out_cds])
'intersectBed -u -a test/test.out.snv.filter -b gencode7.cds.bed > test/test.out.cds'
$ intersectBed -u -a test/test.out.snv.filter -b gencode7.cds.bed > test/test.out.cds
The program runs normally. What is the difference here?
from subprocess import check_call
args = ['intersectBed','-u','-a',out_snv_filter,'-b',cds]
with open(out_cds, 'wb') as outfile:
check_call(args, stdout=outfile)

Error using rsync with variable concatenation in Python

I'm running the below script from the command line with this:
os.system("rsync -avrz -e \'ssh -i /root/.ssh/keyfile.pem\' /var/www/" + folder_name + " root#server.com:" + destfoldertosync)
and I get this when I print out the rsync:
rsync -avrz -e 'ssh -i /root/.ssh/keyfile.pem' /var/www/folder_name, root#server.com:/var/www/destfoldertosync
"/var/www/folder_name," is breaking rsync. It works fine with the folder name hardcoded in there. Why is it inserting a comma after the path and how can I stop it from doing that?
Note: I can't use paramiko so I want this to work with os.system.
I made the mistake of separating the parameters by commas on the cli. Now it works.

Categories

Resources