web-dev-qa-db-ja.com

pythonスクリプトからスーパーユーザーとしてコマンドを実行する

だから、サブプロセスを使用して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必要に応じてスーパーユーザーパスワードの入力を求めるスーパーユーザーとして、これを行うにはどうすればよいですか。スクリプトにパスワードを保存するつもりはありません。

編集:

コマンドを文字列として渡し、トークン化してリストに入れてみました。 pythonインタープリターで、文字列を使用してパスワードプロンプトを適切に取得します(元の問題のようにpythonスクリプトではまだ動作しません)、 listはSudoのヘルプ画面を提供するだけです。

編集2:

だから、PopenはShell = Trueの場合に文字列としていくつかのコマンドを処理しますが、

proc = subprocess.Popen(['Sudo','/usr/sbin/Apache2ctl','restart'])

「Shell = True」なしでSudoを動作させます。

ありがとう!

40
Silfheed

Apache2ctlへのフルパスを指定してみてください。

15
dwc

試してください:

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

サブプロセスは、プロンプトを出し、パスワードを読み取るために、実際のstdin/out/errにアクセスする必要があります。それらをパイプとして設定する場合、自分でパスワードをそのパイプに入力する必要があります。

それらを定義しない場合、sys.stdoutなどを取得します...

25
Mike Boers

別の方法は、ユーザーをパスワードなしSudo userにすることです。

コマンドラインで次を入力します。

Sudo visudo

次に、以下を追加して、<username>を自分のものに置き換えます。

<username> ALL=(ALL) NOPASSWD: ALL

これにより、ユーザーはパスワードを要求せずにSudoコマンドを実行できます(このユーザーが起動したアプリケーションを含みます。これはセキュリティ上のリスクかもしれません

12
Michael Loo

次のようにPopenを使用する必要があります。

cmd = ['Sudo', 'Apache2ctl', 'restart']
proc = subprocess.Popen(cmd, Shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

リストが必要です。

5
Harley Holcombe

これをpython 3.5に使用しました。サブプロセスモジュールを使用して実行しました。このようなパスワードは非常にinsecureです。

subprocess モジュールはコマンドを文字列のリストとして受け取り、事前にsplit()を使用してリストを作成するか、リスト全体を渡します後。詳細については、ドキュメントを参照してください。

ここで行っているのは、パスワードをエコーし​​、pipeを使用して '-S'引数でSudoに渡すことです。

#!/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() 
4
Nandesh

すべてのソリューションを試しましたが、うまくいきませんでした。 Celeryで長時間実行されるタスクを実行したかったのですが、これらのためにsubprocess.call()でSudo chownコマンドを実行する必要がありました。

これは私のために働いたものです:

安全な環境変数を追加するには、コマンドラインで次のように入力します。

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

SudoでMidnight Commanderを起動するには

echo $MY_Sudo_PASS | Sudo -S mc

またはpython Shell(または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)

それが役に立てば幸い。

1
jturi

これを行う最も安全な方法は、事前にパスワードを要求し、それをコマンドにパイプすることです。パスワードの入力を求めると、コードのどこにでもパスワードが保存されることを回避でき、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())
1
Josh Correia