Про находчивость и нежелание читать документацию

newbie

Опубликован:  2018-11-26T06:52:24.967851Z

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

На сей раз я покажу ещё одно решение этой задачи, которое мне посчастливилось найти на просторах google.com, и хоть это решение в сути является кривым велосипедом, оно, тем не менее, интересно и заслуживает внимания, благодаря находчивости своего автора.

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

Итак, решение найденное на просторах сети.

Импортирую инструменты shlex и subprocess из стандартной библиотеки.

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

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

>>> passwd = 'XXXXXX'
>>> 

Формирую команду целевого процесса, которую необходимо исполнить по условию задачи.

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

А теперь автор решения предлагает сделать финт.., отдать пароль пользователя программе sudo при помощи ещё одного процесса. Формирую команду этого процесса.

>>> e_cmd = shlex.split('echo {}'.format(passwd))
>>> 

Создаю первый процесс.

>>> echo = Popen(e_cmd, stdout=PIPE)
>>> 

Первым процессом будет исполнена команда echo, которая просто печатает на экран переданный ей аргумент, стандартный поток вывода этого процесса задан при помощи специального значение PIPE.

Следующим запускаю целевой процесс.

>>> whoami = Popen(cmd, stdin=echo.stdout, stdout=PIPE, stderr=PIPE)
>>> 

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

>>> whoami.wait()
0
>>> 

Метод wait возвращает код возврата исполненного процесса. Код возврата хранится в соответствующем свойстве процесса.

>>> whoami.returncode
0
>>> 

Содержимое стандартного потока вывода и стандартного потока ошибок исполненного процесса тоже можно увидеть.

>>> whoami.stdout.read().decode('utf-8').strip()
'root'
>>> whoami.stderr.read().decode('utf-8')
'[sudo] пароль для newbie: '
>>> 

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

WmMzFVWgfc.png

В общем-то решение вполне себе рабочее, но с точки зрения чистоты и безупречности кода всё же выглядит не очень презентабельно на мой взгляд, потому что во-первых запускает два процесса вместо одного, во-вторых не использует метод communicate, как рекомендует официальная документация subprocess, и в-третьих пренебрегает свойствами контекстного менеджера класса Popen. И хоть решение рабочее, в некоторых случаях находчивость и нежелание читать документацию могут сыграть злую шутку, которую потом устанешь отлавливать и отлаживать.

Комментарии: