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.
Related
I am using fabric to automate some deployment stuff. Below is a sample of the code I used:
run(f"sudo -H -u www-data bash -c 'rm -r project_name' ")
run(f"sudo -H -u www-data bash -c '/opt/www-data/project-name/bin/pip install -r requirements.txt' ")
run("sudo systemctl stop gunicorn")
run("sudo systemctl start gunicorn")
Everytime each line of code was ran, the terminal ask for my user password, is there a way I can enter the password just once?
Edit:
I am using python3 and the essence of the script was to run the commands on a different user, rather than my own.
Update:
I achieved this by running fabric with "-I" param.
fabric -I deploy
Using run is not the ideal way to achieve this.
fabric.operations.sudo(*args, **kwargs) is something that can be used to achieve what you are attempting.
Please be careful with sudo :)
Every run() invocation is a separate shell, as would be a sudo() invocation. The sudo credentials are per shell, so they are gone every time.
A quick and dirty way would be to lump all commands into one sudo invocation.
A nicer way would be to have a sudoers file on the target host(s) and give each user the required privileges to run particular commands without entering a password.
You can create a fab script like below and then iterate over the host list you want to run the commands because you can passwd username and password in the script itself so to avoid password invocation:
# testCheck.py
#!/usr/bin/python2.7
import sys
from fabric.api import *
env.skip_bad_hosts=True
env.command_timeout=160
env.user = 'user_name'
env.shell = "/bin/sh -c"
env.warn_only = True
env.password = 'user_password'
def readhost():
env.hosts = [line.strip() for line in sys.stdin.readlines()]
def hosts():
with settings(warn_only=True):
output=sudo("ls -l /myfolder",shell=False)
# cat hostfile.txt| | /usr/local/bin/fab readhost -f testCheck.py hosts -P -z 5
OR supplying password at command line
# cat hostfile.txt | /usr/local/bin/fab readhost -f testCheck.py --password=your_pass hosts -P -z 5
--> argument "-P" refers to parallel execution method
--> argument "-z" refres to the number of concurrent processes to use in parallel mode
exapmle hostfile.txt:
server1
server2
server3
server4
Hope this will help.
If you are using ssh keys, then set the fabric environment variable key_filename:
env.key_filename='/path/to/key.pem'
# set the following as well
env.user='username'
env.host='hostaddr'
It will ask you for the password only one time.
Have a look at this question regarding avoid to enter any sudo password when using fabric.
I was in need of a script to perform certain actions remotely using python and paramiko. I performed sudo operations in remote machine using
'echo '+password+' | sudo -S '+'cmd_to_be_executed'
and tty issue was solved by setting the flag get_pty as true in paramiko. Now there is a remote machine which does not have sudo permission for that user, only way to switch to root is by using su command. So I tried
'echo '+password+' | su -c '+'cmd_to_be_executed'
but it throws tty issue. Now even if I, set pty flag as true in paramiko the same issue appears
standard in must be a tty
Is there any way to solve this ? Any help is much appreciated thanks!!!
Yes. You can use a Python command script achieve this.
Use argparse to accept command line arguments, which will be your password.
Use subprocess.run to call your script. You may need to use the shell=True with subprocess. (Or use Pexpect instead of subprocess).
Try something like this:
import subprocess, argparse
#Set up the command line arguments
parser = argparse.ArgumentParser(description='Provide root password.')
parser.add_argument('--password', help='password help')
# Collect the arguments from the command line
args = parser.parse_args()
# Open a pipe to the command you want to run
p = subprocess.Popen(['su', '-c', !!your command here!!],stdout=subprocess.PIPE,stdin=subprocess.PIPE)
# Prepare the password and write it
pwd = args.password + '\n'
p.stdin.write(pwd)
p.communicate()[0]
p.stdin.close()
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.
Currently I'm working on a Python script to run embed shell scripts, the OS contain root and normal_user.
The problem is, when I try to switch from normal_user to root, using a single command in one line.
I have to only modify the code and nothing like visudo to achieve this and use su only without giving the normal_user any rights outside the coding .
How can I achieve this?
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('172.16.x.x', username='my_name', password='my_password')
***stdin, stdout, stderr = ssh.exec_command('switch to root user && execute a commands as root')***
stdin.flush()
print stdout.readlines()
ssh.close()
Assuming the OS environment has sudo command installed and normal_user is allowed to sudo to root without a password:
stdin, stdout, stderr = ssh.exec_command('sudo -i -H -- echo $USER ; echo $USER')
Options -i simulators root login (prepares .profile, etc. environment variables), option -H sets the $HOME directory the same as the root. These may or may not be necessary depending on your use case.
echo $USER example shows that you are executing that command as root (it should return $USER = root).
As a security measurement you can set the normal_user to have sudo rights only if the user logs in with a correct SSH key.
http://www.evans.io/posts/ssh-agent-for-sudo-authentication/ (complex)
So I'm trying to get a process to be run as a super user from within a python script using subprocess. In the ipython shell something like
proc = subprocess.Popen('sudo apach2ctl restart',
shell=True, stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
works fine, but as soon as I stick it into a script I start getting: sudo: apach2ctl: command not found.
I would guess this is due to the way sudo handles environments on ubuntu. (I've also tried sudo -E apche2ctl restart and sudo env path=$PATH apache2ctl restart with no avail)
So my question is basically, if I want to run apache2ctl restart as super user that prompts the user for the super user password when required, how should I go about doing this? I have no intention of storing passwords in the script.
Edit:
I've tried passing in the commands as both a string and tokenized into a list. In the python interpreter, with a string I'll get the password prompt properly (still doesnt work in a python script as in my original problem), a list just gives the help screen for sudo.
Edit 2:
So what I gather is that while Popen will work with some commands just as strings when shell=True, it takes
proc = subprocess.Popen(['sudo','/usr/sbin/apache2ctl','restart'])
without 'shell=True' to get sudo to work.
Thanks!
Try:
subprocess.call(['sudo', 'apach2ctl', 'restart'])
The subprocess needs to access the real stdin/out/err for it to be able to prompt you, and read in your password. If you set them up as pipes, you need to feed the password into that pipe yourself.
If you don't define them, then it grabs sys.stdout, etc...
Try giving the full path to apache2ctl.
Another way is to make your user a password-less sudo user.
Type the following on command line:
sudo visudo
Then add the following and replace the <username> with yours:
<username> ALL=(ALL) NOPASSWD: ALL
This will allow the user to execute sudo command without having to ask for password (including application launched by the said user. This might be a security risk though
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 more information.
What we are doing here is echoing the password and then using pipe we pass it on to the sudo through '-S' argument.
#!/usr/bin/env python
import subprocess
sudo_password = 'mysecretpass'
command = 'apach2ctl restart'
command = command.split()
cmd1 = subprocess.Popen(['echo',sudo_password], stdout=subprocess.PIPE)
cmd2 = subprocess.Popen(['sudo','-S'] + command, stdin=cmd1.stdout, stdout=subprocess.PIPE)
output = cmd2.stdout.read().decode()
The safest way to do this is to prompt for the password beforehand and then pipe it into the command. Prompting for the password will avoid having the password saved anywhere in your code and it also won't show up in your bash history. Here's an example:
from getpass import getpass
from subprocess import Popen, PIPE
password = getpass("Please enter your password: ")
# sudo requires the flag '-S' in order to take input from stdin
proc = Popen("sudo -S apach2ctl restart".split(), stdin=PIPE, stdout=PIPE, stderr=PIPE)
# Popen only accepts byte-arrays so you must encode the string
proc.communicate(password.encode())
You have to use Popen like this:
cmd = ['sudo', 'apache2ctl', 'restart']
proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
It expects a list.
To run a command as root, and pass it the password at the command prompt, you could do it as so:
import subprocess
from getpass import getpass
ls = "sudo -S ls -al".split()
cmd = subprocess.run(
ls, stdout=subprocess.PIPE, input=getpass("password: "), encoding="ascii",
)
print(cmd.stdout)
For your example, probably something like this:
import subprocess
from getpass import getpass
restart_apache = "sudo /usr/sbin/apache2ctl restart".split()
proc = subprocess.run(
restart_apache,
stdout=subprocess.PIPE,
input=getpass("password: "),
encoding="ascii",
)
I tried all the solutions, but did not work. Wanted to run long running tasks with Celery but for these I needed to run sudo chown command with subprocess.call().
This is what worked for me:
To add safe environment variables, in command line, type:
export MY_SUDO_PASS="user_password_here"
To test if it's working type:
echo $MY_SUDO_PASS
> user_password_here
To run it at system startup add it to the end of this file:
nano ~/.bashrc
#.bashrc
...
existing_content:
elif [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
fi
...
export MY_SUDO_PASS="user_password_here"
You can add all your environment variables passwords, usernames, host, etc here later.
If your variables are ready you can run:
To update:
echo $MY_SUDO_PASS | sudo -S apt-get update
Or to install Midnight Commander
echo $MY_SUDO_PASS | sudo -S apt-get install mc
To start Midnight Commander with sudo
echo $MY_SUDO_PASS | sudo -S mc
Or from python shell (or Django/Celery), to change directory ownership recursively:
python
>> import subprocess
>> subprocess.call('echo $MY_SUDO_PASS | sudo -S chown -R username_here /home/username_here/folder_to_change_ownership_recursivley', shell=True)
Hope it helps.
You can use this way and even catch errors, even can add variables to your commands. -
val = 'xy
response = Popen(f"(sudo {val})", stderr=PIPE, stdout=PIPE, shell=True)
output, errors = response.communicate()
Hope this helps.