There are 3 ways of using
sudo to execute commands in your script. These
are listed in order of usefuless and security. In most cases, you should just
use a variation of sh.contrib.sudo.
sudo is so frequently used, we have added a contrib version of the
command to make sudo usage more intuitive. This contrib version is simply a
wrapper around the sh.sudo raw command, but we bake in some
special keyword argument to make it well-behaved. In
particular, the contrib version allows you to specify your password at execution
time via terminal input, or as a string in your script.
Via a with context:
import sh with sh.contrib.sudo: print(ls("/root"))
Or alternatively via subcommands:
import sh print(sh.contrib.sudo.ls("/root"))
[sudo] password for youruser: ************* your_root_files.txt
In the above example,
sh.contrib.sudo automatically asks you for a password
getpass.getpass() under the hood.
This method is the most secure, because it lowers the chances of doing something insecure, like including your password in your python script, or by saying that a particular user can execute anything inside of a particular script (the NOPASSWD method).
sh.contrib.sudo does not do password caching like the sudo binary does.
Thie means that each time a sudo command is run in your script, you will be
asked to type in a password.
You may also specify your password to
sh.contrib.sudo as a string:
import sh password = get_your_password() with sh.contrib.sudo(password, _with=True): print(ls("/root"))
This method is less secure because it becomes tempting to hard-code your password into the python script, and that’s a bad idea. However, it is more flexible, because it allows you to obtain your password from another source, so long as the end result is a string.
With this method, you can use the raw
sh.sudo command directly, because
you’re being guaranteed that the system will not ask you for a password. It
first requires you set up your user to have root execution privileges
Edit your sudoers file:
$> sudo visudo
Add or edit the line describing your user’s permissions:
yourusername ALL = (root) NOPASSWD: /path/to/your/program
ALL hosts will be able to run as root, but
(root) (no other users), and that no password
NOPASSWD will be
This method can be insecure if an unprivileged user can edit your script, because the entire script will be exited as a privileged user. A malicious user could put something bad in this script.
Using the raw command
sh.sudo (which resolves directly to the system’s
sudo binary) without NOPASSWD is possible, provided you wire up the special
keyword arguments on your own to make it behave correctly. This method is
discussed generally for educational purposes; if you take the time to wire up
sh.sudo on your own, then you have in essence just recreated
import sh # password must end in a newline my_password = "password\n" # -S says "get the password from stdin" my_sudo = sh.sudo.bake("-S", _in=my_password) print(my_sudo.ls("root"))
Another less-obvious way of using sudo is by executing the raw
command but also putting it in the foreground. This way, sudo will work
correctly automatically, by hooking up stdin/out/err automatically, and by
asking you for a password if it requires one. The downsides of using
_fg=True, however, are that you cannot capture its output – everything is
just printed to your terminal as if you ran it from a shell.
import sh sh.sudo.ls("/root", _fg=True)