Есть 3 способа использования команды терминала sudo
для выполнения команд в скрипте, требующих прав суперпользователя. Они перечислены в порядке полезности и безопасности. В большинстве случаев следует просто использовать вариант sh.contrib.sudo()
.
sh.contrib.sudo()
Так как команда sudo
используется очень часто, разработчики модуля sh
добавили версию этой команды в подмодуль contrib
, чтобы сделать использование sudo
более интуитивным. Версия contrib
представляет собой обычную обертку для команды sh.sudo raw
со специальным ключевым аргументом для ввода пароля суперпользователя, чтобы она работала правильно.
Выполнение sh.contrib.sudo()
через менеджер контекста with
с вводом пароля через терминал:
import sh with sh.contrib.sudo: print(ls("/root")) # [sudo] password for youruser: ************* # your_root_files.txt
Или, альтернативно, с помощью подкоманд:
import sh print(sh.contrib.sudo.ls("/root")) # [sudo] password for youruser: ************* # your_root_files.txt
В приведенном выше примере вызов sh.contrib.sudo
автоматически запрашивает пароль, используя под капотом встроенный модуль Python getpass.getpass()
.
Этот метод является наиболее безопасным, потому что он снижает шансы сделать что-то небезопасное, например, включить ваш пароль в скрипт python или сказать, что конкретный пользователь может выполнить что-либо внутри конкретного скрипта (метод NOPASSWD
).
Примечание. sh.contrib.sudo
не выполняет кэширование паролей, как это делает двоичный файл sudo
. Это означает, что каждый раз, когда в скрипте запускается команда sudo
, будет предложено ввести пароль.
Также можно указать пароль к sh.contrib.sudo
в виде строки:
import sh password = 'password' with sh.contrib.sudo(password, _with=True): print(ls("/root"))
Предупреждение. Этот метод менее безопасен, потому что явно указывается пароль в скрипте python, а это плохая идея. Однако он более гибкий, поскольку позволяет получить пароль из другого источника, если конечным результатом является строка.
/etc/sudoers NOPASSWD
.С помощью этого метода можно использовать необработанную команду sh.sudo
напрямую, потому что гарантировано, что система не будет запрашивать пароль. Для этого сначала необходимо настроить пользователя на получение привилегий выполнения root
.
Отредактируйте свой файл sudoers
:
$ sudo visudo # Добавьте или отредактируйте строку, # описывающую права доступа пользователя: yourusername ALL = (root) NOPASSWD: /path/to/your/program
Добавляемая строка говорит о том, что при вводе команды терминала sudo
пользователь yourusername
на ВСЕХ ALL
хостах сможет работать как (root)
, и что не будет запрашиваться пароль NOPASSWD
для выполнения /path/to/your/program
.
Предупреждение. Этот метод может быть небезопасным, если непривилегированный пользователь сможет редактировать этот сценарий и таким образом поместит что-то плохое в этот сценарий.
Использование необработанной команды sh.sudo
(которая преобразуется непосредственно в двоичный файл sudo
) без метода NOPASSWD
возможно при условии, если самостоятельно подключить специальный ключевой аргумент. Этот метод обсуждается в основном в образовательных целях. Если вы потратите время на то, чтобы подключить ключевой аргумент к sh.sudo
самостоятельно, то вы, по сути, воссоздали sh.contrib.sudo
.
import sh # пароль должен заканчиваться новой строкой my_password = "password\n" # `-S` говорит: "получите пароль от `stdin`" # метод `.bake` аналогичен `functools.partial()` my_sudo = sh.sudo.bake("-S", _in=my_password) # вызываем созданную функцию `my_sudo` # с зашитыми в нее параметрами my_sudo.ls("root")
По сути метод .bake
делает то же самое что и functools.partial()
.
_fg=True
Еще один менее очевидный способ использования sudo
- выполнить необработанную команду sh.sudo
, но также вывести ее на передний план. Таким образом, sudo
будет работать правильно, автоматически подключая stdin/out/err
и запрашивая пароль, если он требуется. Однако недостатком использования _fg=True
является то, что нельзя записать куда либо его вывод - все просто выводится на терминал.
import sh sh.sudo.ls("/root", _fg=True)