web-dev-qa-db-ja.com

PythonスクリプトでのSudoの使用

スクリプトを実行するたびにVirtualBox共有フォルダーをマウントする小さなスクリプトを作成しようとしています。 Pythonでそれをやりたいのは、スクリプトのためにそれを学ぼうとしているからです。

問題は、mountコマンドを起動するために特権が必要なことです。スクリプトをSudoとして実行することもできますが、Sudoを独自に作成することを好みます。

パスワードを.pyファイルに書き込むのは安全ではないことは既に知っていますが、重要ではない仮想マシンについて説明しています。pyスクリプトをクリックして機能させるだけです。

これは私の試みです:

#!/usr/bin/env python
import subprocess

sudoPassword = 'mypass'
command = 'mount -t vboxsf myfolder /home/myuser/myfolder'

subprocess.Popen('Sudo -S' , Shell=True,stdout=subprocess.PIPE)
subprocess.Popen(sudoPassword , Shell=True,stdout=subprocess.PIPE)
subprocess.Popen(command , Shell=True,stdout=subprocess.PIPE)

My pythonバージョンは2.6

30
Roman Rdgz
_sudoPassword = 'mypass'
command = 'mount -t vboxsf myfolder /home/myuser/myfolder'
p = os.system('echo %s|Sudo -S %s' % (sudoPassword, command))
_

これを試して、動作するかどうかを教えてください。 :-)

そしてこれは:

os.popen("Sudo -S %s"%(command), 'w').write('mypass')

31
Aniket Inge

多くの回答はソリューションを機能させる方法に焦点を当てていますが、ソリューションが非常に悪いアプローチであることを示唆するものはほとんどありません。あなたが本当に「学ぶ練習」をしたいなら、良い解決策を使って練習してみませんか?パスワードをハードコーディングすると、 wrong アプローチが学習されます!

本当に必要なのがそのボリュームのパスワードなしのmountである場合、多分Sudoは必要ありません at /!他のアプローチを提案できますか?

  • /etc/fstabmensi として使用します。オプションuserおよびnoautoを使用して、通常のユーザーがそのボリュームをマウントできるようにします。

  • パスワードなしのアクションにはPolkitを使用します。.policyを使用してスクリプトの<allow_any>yes</allow_any>ファイルを構成し、/usr/share/polkit-1/actionsにドロップします

  • /etc/sudoersを編集して、ユーザーがパスワードを入力せずにSudoを使用できるようにします。

上記のすべてでパスワードなしのルート権限が許可されますが、パスワードをハードコードする必要はありません。任意のアプローチを選択してください。詳細を説明できます。

why に関しては、パスワードをハードコーディングすることは非常に悪い考えです。さらに読むためのいくつかの良いリンクがあります。

47
MestreLion

Sudoのstdinにパスワードを渡すには:

#!/usr/bin/env python
from subprocess import Popen, PIPE

Sudo_password = 'mypass'
command = 'mount -t vboxsf myfolder /home/myuser/myfolder'.split()

p = Popen(['Sudo', '-S'] + command, stdin=PIPE, stderr=PIPE,
          universal_newlines=True)
Sudo_Prompt = p.communicate(Sudo_password + '\n')[1]

注:おそらくパスワードなしのSudoまたはSudo_ASKPASSコマンドをソースコードにパスワードをハードコーディングする代わりに使用します。

15
jfs
  • 端末デバイスの代わりに「stdin」からパスワードを読み取るように指示するSudoコマンドで-Sオプションを使用します。

  • PIPEからstdinを読み込むようPopenに指示します。

  • パスワードを通信メソッドへの引数として使用して、プロセスのstdin PIPEにパスワードを送信します。パスワードの最後に改行文字「\ n」を追加することを忘れないでください。

sp = Popen(cmd , Shell=True, stdin=PIPE)
out, err = sp.communicate(_user_pass+'\n')   
3
Hubert Vijay

subprocess.Popenはプロセスを作成し、パイプやものを開きます。あなたがしていることは:

  • プロセスを開始するSudo -S
  • プロセスを開始mypass
  • プロセスを開始するmount -t vboxsf myfolder /home/myuser/myfolder

これは明らかに機能しません。引数をPopenに渡す必要があります。 そのドキュメント を見ると、最初の引数は実際には引数のリストであることがわかります。

3
mensi

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

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

#!/usr/bin/env python
import subprocess

sudoPassword = 'mypass'
command = 'mount -t vboxsf myfolder /home/myuser/myfolder'.split()

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

output = cmd2.stdout.read.decode()
2
Nandesh

モジュールpexpectを試してください。ここに私のコードがあります:

import pexpect
remove = pexpect.spawn('Sudo dpkg --purge mytool.deb')
remove.logfile = open('log/expect-uninstall-deb.log', 'w')
remove.logfile.write('try to dpkg --purge mytool\n')
if remove.expect(['(?i)password.*']) == 0:
    # print "successfull"
    remove.sendline('mypassword')
    time.sleep(2)
    remove.expect(pexpect.EOF,5)
else:
    raise AssertionError("Fail to Uninstall deb package !")
1
user2951688

Sudoとして実行するものを制限するには、次を実行できます。

python non_Sudo_stuff.py
Sudo -E python -c "import os; os.system('Sudo echo 1')"

パスワードを保存する必要はありません。 -Eパラメーターは、現在のユーザーのenvをプロセスに渡します。シェルには2番目のコマンドの後にSudo特権が付与されるため、注意して使用してください。

1
crizCraig

時にはキャリッジリターンが必要です:

os.popen("Sudo -S %s"%(command), 'w').write('mypass\n')
0
user2095717

スクリプトでSudoパスワードをハードコードしないことが常に好ましいことを知っています。ただし、何らかの理由で、_/etc/sudoersまたはファイル所有者の変更、Pexpectは実行可能な代替手段です。

Python function Sudo_exec ご参考までに:

import platform, os, logging
import subprocess, pexpect

log = logging.getLogger(__name__)

def Sudo_exec(cmdline, passwd):
    osname = platform.system()
    if osname == 'Linux':
        Prompt = r'\[Sudo\] password for %s: ' % os.environ['USER']
    Elif osname == 'Darwin':
        Prompt = 'Password:'
    else:
        assert False, osname

    child = pexpect.spawn(cmdline)
    idx = child.expect([Prompt, pexpect.EOF], 3)
    if idx == 0: # if prompted for the Sudo password
        log.debug('Sudo password was asked.')
        child.sendline(passwd)
        child.expect(pexpect.EOF)
return child.before
0
Jeremy Kao