Sé que la publicación es un poco antigua, pero escribí lo siguiente como una solución a mi problema (ejecutar un script de python como root en Linux y OS X).
me escribió lo siguiente bash script para ejecutar secuencias de comandos bash/pitón con privilegios de administrador (funciona en los sistemas Linux y OS X):
#!/bin/bash
if [ -z "$1" ]; then
echo "Specify executable"
exit 1
fi
EXE=$1
available(){
which $1 >/dev/null 2>&1
}
platform=`uname`
if [ "$platform" == "Darwin" ]; then
MESSAGE="Please run $1 as root with sudo or install osascript (should be installed by default)"
else
MESSAGE="Please run $1 as root with sudo or install gksu/kdesudo!"
fi
if [ `whoami` != "root" ]; then
if [ "$platform" == "Darwin" ]; then
# Apple
if available osascript
then
SUDO=`which osascript`
fi
else # assume Linux
# choose either gksudo or kdesudo
# if both are avilable check whoch desktop is running
if available gksudo
then
SUDO=`which gksudo`
fi
if available kdesudo
then
SUDO=`which kdesudo`
fi
if (available gksudo && available kdesudo)
then
if [ $XDG_CURRENT_DESKTOP = "KDE" ]; then
SUDO=`which kdesudo`;
else
SUDO=`which gksudo`
fi
fi
# prefer polkit if available
if available pkexec
then
SUDO=`which pkexec`
fi
fi
if [ -z $SUDO ]; then
if available zenity; then
zenity --info --text "$MESSAGE"
exit 0
elif available notify-send; then
notify-send "$MESSAGE"
exit 0
elif available xmessage notify-send; then
xmessage -buttons Ok:0 "$MESSAGE"
exit 0
else
echo "$MESSAGE"
fi
fi
fi
if [ "$platform" == "Darwin" ]
then
$SUDO -e "do shell script \"$*\" with administrator privileges"
else
$SUDO [email protected]
fi
Básicamente, la forma en que puedo configurar mi sistema es que sigo subcarpetas dentro de los directorios bin (por ejemplo,/usr/local/bin/pyscripts en/usr/local/bin) y crear enlaces simbólicos a los ejecutables. Esto tiene tres beneficios para mí:
(1) Si tengo diferentes versiones, puedo cambiar fácilmente cuál se ejecuta cambiando el enlace simbólico y mantiene el directorio bin más limpio (por ejemplo/usr/local/bin/gcc -versions/4.9 /, /usr/local/bin/gcc-versions/4.8/,/usr/local/bin/gcc -> gcc-versions/4.8/gcc)
(2) Puedo almacenar el scripts con su extensión (útil para resaltar la sintaxis en IDE), pero los ejecutables no los contienen porque me gusta de esa manera (por ejemplo, svn-tools -> pyscripts/svn-tools.PY)
(3) La razón por la que voy a mostrar a continuación:
i el nombre del script "run-as-root-contenedor" y colocarlo en un camino muy común (por ejemplo,/usr/local/bin) entonces Python no necesita nada especial para localizarlo. Entonces tengo el siguiente módulo run_command.py:
import os
import sys
from distutils.spawn import find_executable
#===========================================================================#
def wrap_to_run_as_root(exe_install_path, true_command, expand_path = True):
run_as_root_path = find_executable("run-as-root-wrapper")
if(not run_as_root_path):
return False
else:
if(os.path.exists(exe_install_path)):
os.unlink(exe_install_path)
if(expand_path):
true_command = os.path.realpath(true_command)
true_command = os.path.abspath(true_command)
true_command = os.path.normpath(true_command)
f = open(exe_install_path, 'w')
f.write("#!/bin/bash\n\n")
f.write(run_as_root_path + " " + true_command + " [email protected]\n\n")
f.close()
os.chmod(exe_install_path, 0755)
return True
En mi script en Python real, tengo la siguiente función:
def install_cmd(args):
exe_install_path = os.path.join(args.prefix,
os.path.join("bin", args.name))
if(not run_command.wrap_to_run_as_root(exe_install_path, sys.argv[0])):
os.symlink(os.path.realpath(sys.argv[0]), exe_install_path)
Así que si tengo un script llamado TrackingBlocker.py (guión real que utilizar para modificar el archivo/etc/hosts para redirigir dominios de rastreo conocidos a 127.0.0.1), cuando llamo "sudo /usr/local/bin/pyscripts/TrackingBlocker.py --prefix/usr/local --name ModifyTrackingBlocker instalar"(argumentos manejados a través de argparse módulo), se instala "/ usr/local/bin/ModifyTrackingBlocker", que es un script bash ejecutar
/usr/local/bin/run-as-root-wrapper /usr/local/bin/pyscripts/TrackingBlocker.py [args]
por ejemplo
ModifyTrackingBlocker add tracker.ads.com
ejecuta:
/usr/local/bin/run-as-root-wrapper /usr/local/bin/pyscripts/TrackingBlocker.py add tracker.ads.com
que luego se muestra el diálogo de autentificación necesaria para obtener los privilegios de añadir:
127.0.0.1 tracker.ads.com
a mi archivo de hosts (que sólo puede ser escrito por un superusuario) .
Si desea simplificar/modificarlo para que se ejecute sólo ciertos comandos como root, simplemente puede añadir esto a su script (con las importaciones necesarias se señaló anteriormente subproceso + importación):
def run_as_root(command, args, expand_path = True):
run_as_root_path = find_executable("run-as-root-wrapper")
if(not run_as_root_path):
return 1
else:
if(expand_path):
command = os.path.realpath(command)
command = os.path.abspath(command)
command = os.path.normpath(command)
cmd = []
cmd.append(run_as_root_path)
cmd.append(command)
cmd.extend(args)
return subprocess.call(' '.join(cmd), shell=True)
Usando los anteriores (en el módulo run_command):
>>> ret = run_command.run_as_root("/usr/local/bin/pyscripts/TrackingBlocker.py", ["status", "display"])
>>> /etc/hosts is blocking approximately 16147 domains
No estoy seguro si puede hacerlo a través de la secuencia de comandos python en OSX. Bajo algún sistema operativo tipo Unix (OS X incluido), los scripts (como shell, perl, python, ...) no pueden ser otorgados para llamar a chown/chgrp, que le da otros privilegios. – Drake