在 Mac OS X、Windows 上使用 Python 获取 root 对话框?
我将如何在我的 Python 应用程序中弹出权限提升对话框?我想要 Windows 上的 UAC 对话框和 Mac 上的密码身份验证对话框。
基本上,我的应用程序的一部分需要 root 权限,并且我需要通过 GUI 获得这些权限。我正在使用 wxPython。有什么想法吗?
How would I go about getting a privilege elevation dialog to pop up in my Python app? I want the UAC dialog on Windows and the password authentication dialog on Mac.
Basically, I need root privileges for part of my application and I need to get those privileges through the GUI. I'm using wxPython. Any ideas?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
在 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 上完成的任务的详细信息,我也许能够提供更具体的帮助。
On Windows you cannot get the UAC dialog without starting a new process, and you cannot even start that process with CreateProcess.
The UAC dialog can be brought about by running another application that has the appropriate manifest file - see Running compiled python (py2exe) as administrator in Vista for an example of how to do this with py2exe.
You can also programatically use the runas verb with the win32 api ShellExecute http://msdn.microsoft.com/en-us/library/bb762153(v=vs.85).aspx - you can call this by using ctypes http://python.net/crew/theller/ctypes/ which is part of the standard library on python 2.5+ iirc.
Sorry don't know about Mac. If you give more detail on what you want to accomplish on Windows I might be able to provide more specific help.
我知道这篇文章有点旧,但我写了以下内容作为我的问题的解决方案(在 Linux 和 OS X 上以 root 身份运行 python 脚本)。
我编写了以下 bash 脚本来以管理员权限执行 bash/python 脚本(适用于 Linux 和 OS X 系统):
基本上,我设置系统的方式是在 bin 目录中保留子文件夹(例如 /usr/local /bin/pyscripts in /usr/local/bin),并创建指向可执行文件的符号链接。这对我来说有三个好处:
(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 模块:
在我的实际 python 脚本中,我有以下功能:
因此,如果我有一个名为 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 脚本,
例如
执行:
然后显示获得权限所需的身份验证对话框,以添加:
到我的主机文件(只能由超级用户写入)。
如果您想简化/修改它以仅以 root 身份运行某些命令,您可以简单地将其添加到您的脚本中(使用上面提到的必要导入+导入子进程):
使用上面的内容(在 run_command 模块中):
I know the post is a little old, but I wrote the following as a solution to my problem (running a python script as root on both Linux and OS X).
I wrote the following bash-script to execute bash/python scripts with administrator privileges (works on Linux and OS X systems):
Basically, the way I set up my system is that I keep subfolders inside the bin directories (e.g. /usr/local/bin/pyscripts in /usr/local/bin), and create symbolic links to the executables. This has three benefits for me:
(1) If I have different versions, I can easily switch which one is executed by changing the symbolic link and it keeps the bin directory cleaner (e.g. /usr/local/bin/gcc-versions/4.9/, /usr/local/bin/gcc-versions/4.8/, /usr/local/bin/gcc --> gcc-versions/4.8/gcc)
(2) I can store the scripts with their extension (helpful for syntax highlighting in IDEs), but the executables do not contain them because I like it that way (e.g. svn-tools --> pyscripts/svn-tools.py)
(3) The reason I will show below:
I name the script "run-as-root-wrapper" and place it in a very common path (e.g. /usr/local/bin) so python doesn't need anything special to locate it. Then I have the following run_command.py module:
In my actual python script, I have the following function:
So if I have a script called TrackingBlocker.py (actual script I use to modify the /etc/hosts file to re-route known tracking domains to 127.0.0.1), when I call "sudo /usr/local/bin/pyscripts/TrackingBlocker.py --prefix /usr/local --name ModifyTrackingBlocker install" (arguments handled via argparse module), it installs "/usr/local/bin/ModifyTrackingBlocker", which is a bash script executing
e.g.
executes:
which then displays the authentification dialog needed to get the privileges to add:
to my hosts file (which is only writable by a superuser).
If you want to simplify/modify it to run only certain commands as root, you could simply add this to your script (with the necessary imports noted above + import subprocess):
Using the above (in run_command module):
我在 Mac OS X 上遇到了同样的问题。我有一个有效的解决方案,但它不是最佳的。我将在这里解释我的解决方案,并继续寻找更好的解决方案。
在程序开始时,我通过执行
os.setuid(0) 检查我是否是 root,如果我还不是 root,则会失败,这将触发 _mac_elevate() ,它会以管理员身份从头开始重新启动我的程序osascript 的帮助。 osascript 可用于执行 applescript 和其他东西。我这样使用它:
问题是,如果我像上面那样使用 subprocess.call,我会保持当前进程运行,并且我的应用程序将有两个实例运行,并提供两个停靠图标。如果我使用 subprocess.Popen 并让非特权进程立即终止,我将无法使用退出代码,也无法获取 stdout/stderr 流并传播到启动原始进程的终端。
I'm having the same problem on Mac OS X. I have a working solution, but it's not optimal. I will explain my solution here and continue looking for a better one.
At the beginning of the program I check if I'm root or not by executing
os.setuid(0) will fail if i'm not already root and that will trigger _mac_elevate() which relaunch my program from the start as administrator with the help of osascript. osascript can be used to execute applescript and other stuff. I use it like this:
The problem with this is if I use subprocess.call as above I keep the current process running and there will be two instances of my app running giving two dock icons. If I use subprocess.Popen instead and let the non-priviledged process die instantly I can't make use of the exit code, nor can I fetch the stdout/stderr streams and propagate to the terminal starting the original process.
将 osascript 与具有管理员权限的 osascript 一起使用实际上只是 Apple 脚本包装对
AuthorizationExecuteWithPrivileges()
。但是您可以使用 ctypes 直接从 Python3 调用
AuthorizationExecuteWithPrivileges()
。例如,以下父脚本
spawn_root.py
(以非 root 用户身份运行)生成子进程root_child.py
(以 root 权限运行)。系统将提示用户在操作系统 GUI 弹出窗口中输入密码。请注意,这在无头会话(例如通过 ssh)上不起作用。它必须在GUI 内运行(例如Terminal.app)。
在 MacOS 质询对话框中正确输入用户密码后,
root_child.py
会执行系统软关闭,这需要 MacOS 上的 root 权限。父级 (spawn_root.py)
子级 (root_child.py)
安全说明
显然,任何时候以 root 身份运行某些东西时,都需要非常小心!
AuthorizationExecuteWithPrivileges()
已弃用,但它可以安全使用。但它也可能不安全地使用!它基本上可以归结为:你真的知道你以root身份运行什么吗?如果您以 root 身份运行的脚本位于具有全局可写权限的临时目录中(正如许多 MacOS 应用程序安装程序历史上所做的那样),那么任何恶意进程都可以获得 root 访问权限。
要安全地以 root 身份执行进程:
来源
Using
osascript
withwith administrator privileges
is actually just Apple Script wrapping a call toAuthorizationExecuteWithPrivileges()
.But you can call
AuthorizationExecuteWithPrivileges()
directly from Python3 with ctypes.For example, the following parent script
spawn_root.py
(run as a non-root user) spawns a child processroot_child.py
(run with root privileges).The user will be prompted to enter their password in the OS GUI pop-up. Note that this will not work on a headless session (eg over ssh). It must be run inside the GUI (eg Terminal.app).
After entering the user's password into the MacOS challenge dialog correctly,
root_child.py
executes a soft shutdown of the system, which requires root permission on MacOS.Parent (spawn_root.py)
Child (root_child.py)
Security Note
Obviously, any time you run something as root, you need to be very careful!
AuthorizationExecuteWithPrivileges()
is deprecated, but it can be used safely. But it can also be used unsafely!It basically boils down to: do you actually know what you're running as root? If the script you're running as root is located in a Temp dir that has world-writeable permissions (as a lot of MacOS App installers have done historically), then any malicious process could gain root access.
To execute a process as root safely:
Sources