Python3, subprocess и sudo

webmaster

Опубликован:  2021-05-27T08:43:20.606518Z
Отредактирован:  2021-05-27T08:47:53.793873Z
0
0
0
Вы неавторизованы, рекомендую зарегистрироваться и авторизоваться.

Вы когда-нибудь пробовали внутри программы на Питоне, в сессии рядового пользователя запускать программы с правами root? В этой демонстрации я покажу, как можно выполнить программу sudo с автоматическим вводом пароля прямо в интерактивной сессии Питона.

Питон, в силу своего простого синтаксиса и низкого порога входа, является великолепным инструментом для автоматизации рутинных действий, и поэтому достаточно часто используется для реализации сложных административных задач с одновременным мониторингом ресурсов системы. При этом иногда хочется, чтобы программа в целом исполнялась с правами обычного пользователя, и только некоторые действия в ней выполнялись с правами суперпользователя и автоматическим вводом пароля. Посмотрим, как это можно реализовать, попытаемся исполнить консольную программу whoami с правами root внутри программы на Питоне.

Программа whoami выводит на экран имя действующего пользователя. Если эту программу запустить в обёртке sudo, она выведет на экран имя суперпользователя.

naY5FTr3Rs.png

Проблема при выполнении аналогичных действий внутри программы на Питоне заключается в том, что sudo запрашивает пароль, а значит ввод пароля необходимо автоматизировать.

Как вообще исполнить консольную программу whoami внутри программы на Питоне? Есть несколько вариантов. Первый вариант - это функция system из модуля os стандартной библиотеки Питона.

>>> import os
>>> os.system('whoami')
debianeach
0
>>> 

gW8vvxRrcp.png

И этот вариант в сочетании с sudo мне видится весьма проблемным.

Второй вариант - это инструменты модуля subprocess стандартной библиотеки Питона. Этот модуль позволяет порождать новые процессы, управлять ими, подключаться к их вводу, выводу, потоку ошибок и получать код возврата. Давайте попробуем воспользоваться этими инструментами для решения нашей маленькой задачи.

Первое, что мне потребуется - модуль shlex, при помощи которого я получу исполняемую программу в виде списка аргументов. Импортирую его.

>>> import shlex
>>>

Далее, мне необходимы следующие инструменты из модуля subprocess: Popen и PIPE. Импортирую их.

>>> from subprocess import Popen, PIPE
>>> 

Готовлю целевую команду, которую необходимо исполнить в порождённом под-процессе.

>>> cmd = shlex.split('sudo -S whoami')
>>> 

Здесь следует отметить, что sudo будет исполнена с опцией -S.

Gl9x3SNPiR.png

Опция -S позволяет взять пароль из стандартного ввода, а приглашение на ввод пароля отдать в стандартный поток ошибок.

Пароль... Передать пароль в программу и при этом не печатать его в тексте программы можно различными методами:

  • стандартным запросом на ввод пароля перед исполнением кода программы;
  • посредством аргумента командной строки;
  • из переменной окружения и так далее...

В рамках этой демонстрации, поскольку все действия выполняются в интерактивной сессии интерпретатора на стендовой машине, я просто вобью пароль пользователя в качестве значения соответствующей переменной прямо в сессии.

>>> passwd = 'kWWar4Sm' + '\n'
>>> 

Замечание: следует обратить внимание, что к паролю пользователя я присоединил символ окончания строки, сделано намеренно, и важно это понимать.

Все подготовительные действия выполнены. Остаётся исполнить задуманную команду.

>>> with Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE) as whoami:
...     result = whoami.communicate(input=passwd.encode('utf-8'))
... 
>>> 

При помощи класса Popen, который поддерживает свойства контекстного менеджера, я создал процесс whoami, который исполняет команду cmd. Стандартные потоки ввода/вывода/ошибок этого процесса заданы при помощи специального значения PIPE. Метод communicate даёт возможность передать этому процессу заданный пароль на стандартный поток ввода, при этом передаваемое значение должно быть байт-строкой соответствующей кодировки и содержать символ конца строки.

После завершения процесса можно получить доступ к коду возврата.

>>> whoami.returncode
0
>>> 

Код возврата в данном случае подтверждает, что программа исполнена без ошибок.

В результате выполненного процесса в переменной result хранятся два значения:

  • стандартный вывод исполненного процесса;
  • стандартный поток ошибок.
>>> result
(b'root\n', b'[sudo] \xd0\xbf\xd0\xb0\xd1\x80\xd0\xbe\xd0\xbb\xd1\x8c \xd0\xb4\xd0\xbb\xd1\x8f debianeach: ')
>>> 

При необходимости эти значения можно вывести на экран.

>>> result[0].decode('utf-8').strip()
'root'
>>> result[1].decode('utf-8')
'[sudo] пароль для debianeach: '
>>> 

Вся отладка выглядит следующим образом.

07UQlFstCH.png

Таким образом я констатирую, что консольная программа whoami исполнена в рамках программы на Python3 от имени суперпользователя, с автоматическим вводом пароля в запрос sudo, а полученные в результате этих действий данные сохранены в соответствующих переменных. Задача оказалась несложной.

1. Важная информация для постоянных читателей

Уважаемый читатель, списки auriz.ru не имеет спонсоров и финансирования, и чтобы выжить мы можем рассчитывать только на поддержку своих постоянных читателей и их пожертвования. Если вам оказалась полезна эта или другая статья этого сайта, и вы хотите больше интересных материалов на auriz.ru, поддержите нас рублём, ваша поддержка даст нам шанс выжить, оплатить продление домена и VDS, написать и опубликовать для вас другие интересные материалы.

Поддержать нас можно переводом любой приемлемой для вас суммы на мой кошелёк yoomoney. Важно помнить, что перевод на пять рублей - лучше, чем никакого перевода, а без вашей помощи проект почти наверняка загнётся и прекратит существование очень скоро.

Важное замечание: оригинальные статьи блогов auriz.ru являются авторским контентом и защищены авторским правом, не допускается копирование и тиражирование материалов сайта на других ресурсах сети или в печатных изданиях без согласования с автором блога и администратором этого сайта, не воруйте у нас оригинальные материалы, мы создаём их только и исключительно для читателей нашего сайта.

Метки:  newbie, sudo, python3x, linux, os, subprocess, whoami
Комментарии: