ejecutar un comando como superusuario desde un script en Python
-
05-09-2019 - |
Pregunta
Así que estoy tratando de ejecutar un proceso como superusuario desde un script de Python usando un subproceso.En el shell de ipython algo como
proc = subprocess.Popen('sudo apach2ctl restart',
shell=True, stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
funciona bien, pero tan pronto como lo inserto en un script empiezo a recibir: sudo: apach2ctl: command not found
.
Supongo que esto se debe a la forma en que Sudo maneja los entornos en Ubuntu.(También lo he intentado sudo -E apche2ctl restart
y sudo env path=$PATH apache2ctl restart
sin resultado)
Entonces mi pregunta es básicamente, si quiero ejecutar apache2ctl restart
como superusuario que solicita al usuario la contraseña de superusuario cuando es necesario, ¿cómo debo hacer esto?No tengo intención de almacenar contraseñas en el script.
Editar:
Intenté pasar los comandos como una cadena y tokenizados en una lista.En el intérprete de Python, con una cadena obtendré la solicitud de contraseña correctamente (todavía no funciona en un script de Python como en mi problema original), una lista solo muestra la pantalla de ayuda para sudo.
Edición 2:
Entonces, lo que deduzco es que, si bien Popen trabajará con algunos comandos como cadenas cuando shell=True, se necesita
proc = subprocess.Popen(['sudo','/usr/sbin/apache2ctl','restart'])
sin 'shell=True' para que sudo funcione.
¡Gracias!
Solución
Trate de darle la ruta completa a apache2ctl.
Otros consejos
Probar:
subprocess.call(['sudo', 'apach2ctl', 'restart'])
El subproceso necesita acceder a la verdadera entrada estándar de entrada / salida / err para que sea capaz de incitar usted, y leer en su contraseña. Si les configura como tuberías, es necesario alimentar la contraseña en esa tubería mismo.
Si no se define, entonces se agarra sys.stdout, etc ...
Otra forma es hacer que su usuario una sudo user
sin contraseña.
Escriba lo siguiente en la línea de comandos:
sudo visudo
A continuación, agregue el siguiente y reemplazar el <username>
con la suya:
<username> ALL=(ALL) NOPASSWD: ALL
Esto permitirá al usuario ejecutar comandos sudo
sin tener que pedir la contraseña (incluyendo la aplicación lanzada por dicho usuario. Esto podría ser un riesgo para la seguridad, aunque
Usted tiene que usar Popen como esto:
cmd = ['sudo', 'apache2ctl', 'restart']
proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
Se espera una lista.
He utilizado este para Python 3.5. Lo hice usando subproceso module.Using la contraseña de este tipo es muy insegura .
El subproceso módulo toma el mando como una lista de cadenas así que o crear una lista utilizando antemano split () o pasar toda la lista más adelante. Lea la documentación para obtener más información.
Lo que estamos haciendo aquí se hace eco de la contraseña y luego usando tubería que lo transmiten a través de la argumentación del sudo '-S'.
#!/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()
He intentado todas las soluciones, pero no funcionó. Quería ejecutar tareas de larga ejecución con apio pero para éstos que necesitaba para ejecutar el comando sudo chown con subprocess.call ().
Esto es lo que funcionó para mí:
Para añadir variables de entorno de seguridad, en la línea de comandos, escriba:
export MY_SUDO_PASS="user_password_here"
Para probar si es el tipo de trabajo:
echo $MY_SUDO_PASS
> user_password_here
Para ejecutarlo al inicio del sistema añadirlo al final de este archivo:
nano ~/.bashrc
#.bashrc
...
existing_content:
elif [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
fi
...
export MY_SUDO_PASS="user_password_here"
Puede agregar todas las variables de entorno contraseñas, nombres de usuario, anfitrión, etc aquí más tarde.
Si las variables están listos puede ejecutar:
Para actualizar:
echo $MY_SUDO_PASS | sudo -S apt-get update
O para instalar Midnight Commander
echo $MY_SUDO_PASS | sudo -S apt-get install mc
Para iniciar Midnight Commander con sudo
echo $MY_SUDO_PASS | sudo -S mc
O de Shell pitón (o Django / apio), para cambiar la propiedad de directorio de forma recursiva:
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)
Espero que ayuda.
La forma más segura de hacer esto es solicitar la contraseña de antemano y luego tubería en el comando. Solicita la contraseña evitará tener la contraseña guardada en cualquier lugar en el código y también no se mostrará en su historial de bash. He aquí un ejemplo:
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())