81

/ etc内のファイルの移動、apt-getを使用したインストールなど、ルートレベルの権限を必要とする多くのことを実行するPythonスクリプトがあります。私は現在持っています:

if os.geteuid() != 0:
    exit("You need to have root privileges to run this script.\nPlease try again, this time using 'sudo'. Exiting.")

これはチェックを行うための最良の方法ですか?他にベストプラクティスはありますか?

4

10 に答える 10

82

os.geteuid有効なユーザーIDを取得します。これはまさにあなたが望むものであるため、このようなチェックを実行するためのより良い方法は考えられません。不確かな点は、タイトルの「root-like」です。コードは正確 rootにチェックし、「like」はありません。実際、「root-likeがrootではない」が何を意味するのかわかりません。 、「正確にルート」とは異なる意味の場合は、明確にすることができます。ありがとうございます。

于 2010-05-10T22:39:20.520 に答える
34

「許可よりも許しを求めるのが簡単」の原則の下で:

try:
    os.rename('/etc/foo', '/etc/bar')
except IOError as e:
    if (e[0] == errno.EPERM):
       sys.exit("You need root permissions to do this, laterz!")

あなたがあなたの非携帯性について心配しているなら、os.geteuid()おそらくとにかくいじくり回すべきではありませ/etcん。

于 2010-05-10T22:41:07.793 に答える
17

ユーザーにsudoアクセスを求めることができます。

import os, subprocess

def prompt_sudo():
    ret = 0
    if os.geteuid() != 0:
        msg = "[sudo] password for %u:"
        ret = subprocess.check_call("sudo -v -p '%s'" % msg, shell=True)
    return ret

if prompt_sudo() != 0:
    # the user wasn't authenticated as a sudoer, exit?

スイッチはsudo -v、ユーザーのキャッシュされた資格情報を更新します(を参照man sudo)。

于 2013-11-22T20:26:31.307 に答える
9

Linuxの場合:

def is_root():
    return os.geteuid() == 0
于 2018-10-03T07:29:11.657 に答える
8

私は環境変数でsudoをチェックするのが好きです:

os.environ.keys()の「SUDO_UID」でない場合:
  「このプログラムにはスーパーユーザーの特権が必要です。」と印刷します。
  sys.exit(1)
于 2013-07-15T13:26:51.107 に答える
7

さまざまなLinux構成でコードを堅牢にしたい場合は、誰かがSELinux、ファイルシステムACL、またはLinuxカーネルにあった「機能」機能を使用している可能性があるコーナーケースを検討することをお勧めします。 v。2.2以降。プロセスは、SELinuxを使用したラッパー、またはlibcap2 libcap-ngなどのLinux機能ライブラリ、またはNielsProvosの素晴らしくて悲しいことに過小評価されているsystraceシステムなどのよりエキゾチックなものを介したfscapsまたはelfcapで実行されている可能性があります。

これらはすべて、コードが非ルートとして実行されている可能性があるにもかかわらず、EUID==0なしで作業を実行するために必要なアクセスがプロセスに委任されている可能性がある方法です。

したがって、パーミッションやその他の例外処理コードの問題が原因で失敗する可能性のある操作をラップすることにより、コードをよりPython的に記述することを検討することをお勧めします。さまざまな操作を実行するためにシェルアウトする場合(たとえば、subprocessモジュールを使用する場合)、そのようなすべての呼び出しの前に(たとえばsudo、コマンドライン、環境、または.rcファイルオプションとして)プレフィックスを付けることができます。インタラクティブに実行されている場合は、を使用してアクセス許可関連の例外を発生させるコマンドを再実行することを提案できます(オプションでos.environ ['PATH']にあるsudo場合のみ)。sudo

全体として、ほとんどのLinuxおよびUNIXシステムでは、ほとんどの管理が「root」特権ユーザーによって行われていることは事実です。ただし、これは古い学校であり、プログラマーとして、新しいモデルをサポートするように努める必要があります。sudo操作を試して例外処理を実行させることで、必要な操作を透過的に許可する任意のシステムでコードを機能させることができます。システム特権の制御された委任のためのツール)。

于 2010-05-10T23:53:06.467 に答える
5
import os

def check_privileges():

    if not os.environ.get("SUDO_UID") and os.geteuid() != 0:
        raise PermissionError("You need to run this script with sudo or as root.")

SUDO_UIDスクリプトがで実行されていない場合は使用できませんsudo

于 2021-09-10T15:03:24.823 に答える
3

質問の2番目の部分に答える

(コメントボックスが小さすぎて申し訳ありません)

ポールホフマン、あなたは正しいです、私は組み込み関数を扱っているあなたの質問の一部だけに対処しました、しかしそれが処理できなければそれは価値のあるスクリプト言語ではないでしょうapt-get。推奨されるライブラリは少し冗長ですが、次のような役割を果たします。

>>> apt_get = ['/usr/bin/apt-get', 'install', 'python']
>>> p = subprocess.Popen(apt_get, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> p.wait()
100                 # Houston, we have a problem.
>>> p.stderr.read()
'E: Could not open lock file /var/lib/dpkg/lock - open (13: Permission denied)'
'E: Unable to lock the administration directory (/var/lib/dpkg/), are you root?\n'

ただしPopen、これは一般化されたツールであり、便宜上ラップすることができます。

$ cat apt.py
import errno
import subprocess

def get_install(package):
    cmd = '/usr/bin/apt-get install'.split()
    cmd.append(package)
    output_kw = {'stdout': subprocess.PIPE, 'stderr': subprocess.PIPE}
    p = subprocess.Popen(cmd, **output_kw)
    status = p.wait()
    error = p.stderr.read().lower()
    if status and 'permission denied' in error:
        raise OSError(errno.EACCES, 'Permission denied running apt-get')
    # other conditions here as you require
$ python
>>> import apt
>>> apt.get_install('python')
Traceback ...
OSError: [Errno 13] Permission denied running apt-get

そして今、例外処理に戻ります。サブプロセスモジュールのJavaのような過度の一般性についてはコメントしません。

于 2010-05-12T16:15:58.007 に答える
3

私のアプリはこのコードで動作します:

import os
user = os.getenv("SUDO_USER")
if user is None:
    print "This program need 'sudo'"
    exit()
于 2014-10-03T16:24:18.300 に答える
0

それはすべて、アプリをどれだけポータブルにするかによって異なります。忙しさを意味する場合、管理者アカウントが常に0に等しいとは限らないと想定する必要があります。これは、euid0をチェックするだけでは不十分であることを意味します。問題は、あるコマンドがrootであるかのように動作し、次のコマンドが許可を拒否して失敗する場合があることです(SELinuxなどを考えてみてください)。したがって、適切に失敗し、適切な場合はいつでもEPERMerrnoをチェックすることをお勧めします。

于 2010-05-10T22:52:27.850 に答える