запуск команды как суперпользователь из скрипта Python - PullRequest
38 голосов
/ 20 февраля 2009

Итак, я пытаюсь заставить процесс запускаться как суперпользователь из скрипта Python, используя подпроцесс. В оболочке ipython что-то вроде

proc = subprocess.Popen('sudo apach2ctl restart',
                        shell=True, stdin=subprocess.PIPE,
                        stdout=subprocess.PIPE,
                        stderr=subprocess.PIPE)

работает нормально, но как только я вставляю его в скрипт, я начинаю получать: sudo: apach2ctl: command not found.

Я думаю, это связано с тем, как sudo обрабатывает окружение в Ubuntu. (Я также пробовал sudo -E apche2ctl restart и sudo env path=$PATH apache2ctl restart безрезультатно)

Таким образом, мой вопрос в основном, если я хочу запустить apache2ctl restart от имени суперпользователя, который запрашивает у пользователя пароль суперпользователя, когда это необходимо, как мне это сделать? Я не собираюсь хранить пароли в скрипте.

Edit:

Я попытался передать команды как строку и как токен в список. В интерпретаторе python со строкой я получу запрос пароля правильно (все еще не работает в сценарии python, как в моей первоначальной задаче), список просто отображает экран справки для sudo.

Редактировать 2:

Итак, я понял, что хотя Popen будет работать с некоторыми командами в виде строк, когда shell = True, для этого требуется

proc = subprocess.Popen(['sudo','/usr/sbin/apache2ctl','restart'])

без 'shell = True', чтобы заставить sudo работать.

Спасибо!

Ответы [ 7 ]

23 голосов
/ 20 февраля 2009

Попробуйте:

subprocess.call(['sudo', 'apach2ctl', 'restart'])

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

Если вы их не определили, он захватывает sys.stdout и т. Д. *

14 голосов
/ 20 февраля 2009

Попробуйте указать полный путь к apache2ctl.

11 голосов
/ 09 июля 2014

Другой способ - сделать вашего пользователя без пароля sudo user.

Введите в командной строке следующее:

sudo visudo

Затем добавьте следующее и замените <username> на ваше:

<username> ALL=(ALL) NOPASSWD: ALL

Это позволит пользователю выполнить команду sudo без запроса пароля (включая приложение, запущенное указанным пользователем. Хотя это может представлять угрозу безопасности

5 голосов
/ 20 февраля 2009

Вы должны использовать Popen так:

cmd = ['sudo', 'apache2ctl', 'restart']
proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

Ожидается список.

4 голосов
/ 05 апреля 2018

Я использовал это для Python 3.5. Я сделал это с помощью подпроцесса модуля. Использование такого пароля очень небезопасно .

Модуль подпроцесса принимает команду как список строк, поэтому либо создайте список заранее, используя split () , либо передайте весь список позже. Прочитайте документацию для получения дополнительной информации.

Здесь мы повторяем пароль, а затем, используя pipe , передаем его в sudo с помощью аргумента '-S'.

#!/usr/bin/env python
import subprocess

sudo_password = 'mysecretpass'
command = 'apach2ctl restart'
command = command.split()

cmd1 = subprocess.Popen(['echo',sudo_password], stdout=subprocess.PIPE)
cmd2 = subprocess.Popen(['sudo','-S'] + command, stdin=cmd1.stdout, stdout=subprocess.PIPE)

output = cmd2.stdout.read().decode() 
2 голосов
/ 15 марта 2018

Я перепробовал все решения, но не сработало. Хотел запускать долго выполняющиеся задачи с Celery, но для этого мне нужно было запустить команду sudo chown с subprocess.call ().

Вот что у меня сработало:

Чтобы добавить безопасные переменные среды, в командной строке введите:

export MY_SUDO_PASS="user_password_here"

Чтобы проверить, работает ли он, введите:

echo $MY_SUDO_PASS
 > user_password_here

Чтобы запустить его при запуске системы, добавьте его в конец этого файла:

nano ~/.bashrc  

#.bashrc
...
existing_content:

  elif [ -f /etc/bash_completion ]; then
    . /etc/bash_completion
  fi
fi
...

export MY_SUDO_PASS="user_password_here"

Здесь вы можете добавить все переменные окружения, пароли, имена пользователей, хосты и т. Д. Здесь.

Если ваши переменные готовы, вы можете запустить:

Для обновления:

echo $MY_SUDO_PASS | sudo -S apt-get update

Или установить Midnight Commander

echo $MY_SUDO_PASS | sudo -S apt-get install mc

Для запуска Midnight Commander с sudo

echo $MY_SUDO_PASS | sudo -S mc

Или из оболочки Python (или Django / Celery), чтобы рекурсивно изменить владельца каталога:

python
>> import subprocess
>> subprocess.call('echo $MY_SUDO_PASS | sudo -S chown -R username_here /home/username_here/folder_to_change_ownership_recursivley', shell=True)

Надеюсь, это поможет.

0 голосов
/ 29 мая 2019

Самый безопасный способ сделать это - запросить пароль заранее и затем передать его в команду. Запрос пароля не позволит сохранить пароль где-либо в вашем коде, а также не будет отображаться в вашей истории bash. Вот пример:

from getpass import getpass
from subprocess import Popen, PIPE

password = getpass("Please enter your password: ")
# sudo requires the flag '-S' in order to take input from stdin
proc = Popen("sudo -S apach2ctl restart".split(), stdin=PIPE, stdout=PIPE, stderr=PIPE)
# Popen only accepts byte-arrays so you must encode the string
proc.communicate(password.encode())
...