だから、サブプロセスを使用して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を動作させます。
ありがとう!
Apache2ctlへのフルパスを指定してみてください。
試してください:
subprocess.call(['Sudo', 'apach2ctl', 'restart'])
サブプロセスは、プロンプトを出し、パスワードを読み取るために、実際のstdin/out/errにアクセスする必要があります。それらをパイプとして設定する場合、自分でパスワードをそのパイプに入力する必要があります。
それらを定義しない場合、sys.stdoutなどを取得します...
別の方法は、ユーザーをパスワードなしSudo user
にすることです。
コマンドラインで次を入力します。
Sudo visudo
次に、以下を追加して、<username>
を自分のものに置き換えます。
<username> ALL=(ALL) NOPASSWD: ALL
これにより、ユーザーはパスワードを要求せずにSudo
コマンドを実行できます(このユーザーが起動したアプリケーションを含みます。これはセキュリティ上のリスクかもしれません
次のようにPopenを使用する必要があります。
cmd = ['Sudo', 'Apache2ctl', 'restart']
proc = subprocess.Popen(cmd, Shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
リストが必要です。
これを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()
すべてのソリューションを試しましたが、うまくいきませんでした。 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)
それが役に立てば幸い。
これを行う最も安全な方法は、事前にパスワードを要求し、それをコマンドにパイプすることです。パスワードの入力を求めると、コードのどこにでもパスワードが保存されることを回避でき、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())