簡體   English   中英

在Mac OS X,Windows上用Python獲取root對話框?

[英]Get root dialog in Python on Mac OS X, Windows?

我如何獲得在我的Python應用程序中彈出的權限提升對話框? 我想要Windows上的UAC對話框和Mac上的密碼驗證對話框。

基本上,我需要部分應用程序的root權限,我需要通過GUI獲得這些權限。 我正在使用wxPython。 有任何想法嗎?

在Windows上,如果不啟動新進程,則無法獲取UAC對話框,甚至無法使用CreateProcess啟動該進程。

可以通過運行具有相應清單文件的另一個應用程序來實現UAC對話框 - 請參閱在Vista中管理員身份運行編譯的python(py2exe),以獲取如何使用py2exe執行此操作的示例。

你也可以編程方式使用runas動詞與win32 api ShellExecute http://msdn.microsoft.com/en-us/library/bb762153(v=vs.85).aspx - 你可以通過使用ctypes來調用它:http:/ /python.net/crew/theller/ctypes/是python 2.5+ iirc上標准庫的一部分。

抱歉,不知道Mac。 如果您提供有關要在Windows上完成的內容的更多詳細信息,我可以提供更具體的幫助。

我知道帖子有點舊,但我寫了以下內容作為我的問題的解決方案(在Linux和OS X上以root身份運行python腳本)。

我編寫了以下bash腳本來執行具有管理員權限的bash / python腳本(適用於Linux和OS X系統):

#!/bin/bash

if [ -z "$1" ]; then
    echo "Specify executable"
    exit 1
fi

EXE=$1

available(){
    which $1 >/dev/null 2>&1
}

platform=`uname`

if [ "$platform" == "Darwin" ]; then
    MESSAGE="Please run $1 as root with sudo or install osascript (should be installed by default)"
else
    MESSAGE="Please run $1 as root with sudo or install gksu / kdesudo!"
fi

if [ `whoami` != "root" ]; then

    if [ "$platform" == "Darwin" ]; then
        # Apple
        if available osascript
        then
            SUDO=`which osascript`
        fi

    else # assume Linux
        # choose either gksudo or kdesudo
        # if both are avilable check whoch desktop is running
        if available gksudo
        then
            SUDO=`which gksudo`
        fi
        if available kdesudo
        then
            SUDO=`which kdesudo`
        fi
        if ( available gksudo && available kdesudo )
        then
            if [ $XDG_CURRENT_DESKTOP = "KDE" ]; then
                SUDO=`which kdesudo`;
            else
                SUDO=`which gksudo`
            fi
        fi

        # prefer polkit if available
        if available pkexec
        then
           SUDO=`which pkexec`
        fi

    fi

    if [ -z $SUDO ]; then
        if available zenity; then
            zenity --info --text "$MESSAGE"
            exit 0
        elif available notify-send; then
            notify-send "$MESSAGE"
            exit 0
        elif available xmessage notify-send; then
            xmessage -buttons Ok:0 "$MESSAGE"
            exit 0
        else
            echo "$MESSAGE"
        fi
    fi

fi

if [ "$platform" == "Darwin" ]
then
    $SUDO -e "do shell script \"$*\" with administrator privileges"
else
    $SUDO $@
fi

基本上,我設置系統的方式是將子文件夾保存在bin目錄中(例如/ usr / local / bin中的/ usr / local / bin / pyscripts),並創建指向可執行文件的符號鏈接。 這對我有三個好處:

(1)如果我有不同的版本,我可以通過更改符號鏈接輕松切換執行哪個版本,並使bin目錄保持清潔(例如/usr/local/bin/gcc-versions/4.9/,/ usr / local / bin / gcc-versions / 4.8 /,/ usr / local / bin / gcc - > gcc-versions / 4.8 / gcc)

(2)我可以使用它們的擴展名存儲腳本(有助於IDE中的語法高亮顯示),但可執行文件不包含它們,因為我喜歡它(例如svn-tools - > pyscripts / svn-tools.py)

(3)我將在下面顯示的原因:

我將腳本命名為“run-as-root-wrapper”並將其放在一個非常常見的路徑中(例如/ usr / local / bin),因此python不需要任何特殊的東西來定位它。 然后我有以下run_command.py模塊:

import os
import sys
from distutils.spawn import find_executable

#===========================================================================#

def wrap_to_run_as_root(exe_install_path, true_command, expand_path = True):
    run_as_root_path = find_executable("run-as-root-wrapper")

    if(not run_as_root_path):
        return False
    else:
        if(os.path.exists(exe_install_path)):
            os.unlink(exe_install_path)

        if(expand_path):
            true_command = os.path.realpath(true_command)
            true_command = os.path.abspath(true_command)
            true_command = os.path.normpath(true_command)

        f = open(exe_install_path, 'w')
        f.write("#!/bin/bash\n\n")
        f.write(run_as_root_path + " " + true_command + " $@\n\n")
        f.close()
        os.chmod(exe_install_path, 0755)

        return True

在我的實際python腳本中,我有以下功能:

def install_cmd(args):
    exe_install_path = os.path.join(args.prefix, 
                                    os.path.join("bin", args.name))

    if(not run_command.wrap_to_run_as_root(exe_install_path, sys.argv[0])):
        os.symlink(os.path.realpath(sys.argv[0]), exe_install_path)

因此,如果我有一個名為TrackingBlocker.py的腳本(我用來修改/ etc / hosts文件以將已知跟蹤域重新路由到127.0.0.1的實際腳本),當我調用“sudo / usr / local / bin / pyscripts /”時TrackingBlocker.py --prefix / usr / local --name ModifyTrackingBlocker install“(通過argparse模塊處理的參數),它安裝”/ usr / local / bin / ModifyTrackingBlocker“,這是一個bash腳本執行

/usr/local/bin/run-as-root-wrapper /usr/local/bin/pyscripts/TrackingBlocker.py [args]

例如

ModifyTrackingBlocker add tracker.ads.com

執行:

/usr/local/bin/run-as-root-wrapper /usr/local/bin/pyscripts/TrackingBlocker.py add tracker.ads.com

然后顯示獲取添加權限所需的身份驗證對話框:

127.0.0.1  tracker.ads.com

到我的主機文件(只能由超級用戶寫入)。

如果您想簡化/修改它以僅以root身份運行某些命令,您只需將其添加到您的腳本中(使用上面提到的必要導入+ import subprocess):

def run_as_root(command, args, expand_path = True):
    run_as_root_path = find_executable("run-as-root-wrapper")

    if(not run_as_root_path):
        return 1
    else:
        if(expand_path):
            command = os.path.realpath(command)
            command = os.path.abspath(command)
            command = os.path.normpath(command)

        cmd = []
        cmd.append(run_as_root_path)
        cmd.append(command)
        cmd.extend(args)

        return subprocess.call(' '.join(cmd), shell=True)

使用上面的(在run_command模塊中):

>>> ret = run_command.run_as_root("/usr/local/bin/pyscripts/TrackingBlocker.py", ["status", "display"])
>>> /etc/hosts is blocking approximately 16147 domains

我在Mac OS X上遇到了同樣的問題。我有一個可行的解決方案,但它並不是最佳的。 我將在這里解釋我的解決方案並繼續尋找更好的解決方案。

在程序開始時,我通過執行檢查我是否是root用戶

def _elevate():
    """Elevate user permissions if needed"""
    if platform.system() == 'Darwin':
        try:
            os.setuid(0)
        except OSError:
            _mac_elevate()

os.setuid(0)將失敗,如果我還不是root,那將觸發_mac_elevate(),它在管理員的幫助下從osascript開始重新啟動我的程序。 osascript可用於執行applescript和其他東西。 我這樣使用它:

def _mac_elevate():
    """Relaunch asking for root privileges."""
    print "Relaunching with root permissions"
    applescript = ('do shell script "./my_program" '
                   'with administrator privileges')
    exit_code = subprocess.call(['osascript', '-e', applescript])
    sys.exit(exit_code)

這個問題是如果我使用subprocess.call,如上所述我保持當前進程運行,我的應用程序將運行兩個實例,給出兩個停靠圖標。 如果我使用subprocess.Popen而讓非特權進程立即死亡我無法使用退出代碼,也無法獲取stdout / stderr流並傳播到終端開始原始進程。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM