检查脚本用户是否具有 root 权限的最佳方法是什么?
我有一个 Python 脚本,它将执行许多需要根级权限的操作,例如移动 /etc 中的文件、使用 apt-get 安装等。我目前有:
if os.geteuid() != 0:
exit("You need to have root privileges to run this script.\nPlease try again, this time using 'sudo'. Exiting.")
这是进行检查的最佳方式吗?还有其他最佳实践吗?
I have a Python script that will be doing a lot of things that would require root-level privileges, such as moving files in /etc, installing with apt-get, and so on. I currently have:
if os.geteuid() != 0:
exit("You need to have root privileges to run this script.\nPlease try again, this time using 'sudo'. Exiting.")
Is this the best way to do the check? Are there other best practices?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
os.geteuid 获取有效的用户id,这正是你想要的,所以我想不出任何更好的方法来执行这样的检查。不确定的一点是标题中的“类似 root”:您的代码完全
root
检查它,没有“类似”,事实上我不会知道“类似根但不是根”是什么意思 - 所以,如果您的意思与“完全根”不同,也许您可以澄清,谢谢!os.geteuid
gets the effective user id, which is exactly what you want, so I can't think of any better way to perform such a check. The one bit that's uncertain is that "root-like' in the title: your code checks for exactlyroot
, no "like" about it, and indeed I wouldn't know what "root-like but not root" would mean -- so, if you mean something different than "exactly root", perhaps you can clarify, thanks!根据 EAFP(请求宽恕比请求许可更容易)原则:
如果您担心
os.geteuid()
的不可移植性,您可能不应该搞砸无论如何/etc
。Under the EAFP (Easier to Ask Forgiveness than Permission) principle:
If you are concerned about the non-portability of
os.geteuid()
you probably shouldn't be mucking with/etc
anyway.您可以提示用户进行 sudo 访问:
sudo -v
开关更新用户的缓存凭据(请参阅man sudo
)。You can prompt the user for sudo access:
The
sudo -v
switch update the user's cached credentials (seeman sudo
).对于Linux:
For linux:
我喜欢检查环境变量中的 sudo:
I like to check for sudo in the environmental variables:
如果您确实希望您的代码在各种 Linux 配置中都具有鲁棒性,我建议您考虑一些极端情况,即有人可能使用 SELinux、文件系统 ACL 或 Linux 内核中的“功能”功能从 v.2.2 左右开始。您的进程可能在使用 SELinux 的某些包装器或某些 Linux 功能库下运行,例如 libcap2 libcap-ng,或 fscaps 或 elfcap 通过更多内容像尼尔斯·普罗沃斯那样充满异国情调的美妙但令人遗憾的低估 systrace 系统上的 systrace 结果。
所有这些都是您的代码可能以非 root 身份运行的方式,但您的进程可能已被委派必要的访问权限来执行其工作,而无需 EUID==0。
因此,我建议您考虑以更 Python 的方式编写代码,通过使用异常处理代码包装可能因权限或其他问题而失败的操作。如果您要执行各种操作(例如使用
subprocess
模块),您可能会为所有此类调用添加前缀sudo
(作为命令行、环境或例如,.rc 文件选项)。如果以交互方式运行,您可以使用sudo
重新执行任何引发权限相关异常的命令(可选地,仅当您在 os.environ['PATH 上找到sudo
时) '])。总的来说,大多数 Linux 和 UNIX 系统的大部分管理工作仍然由“root”特权用户完成。然而,这是老派的做法,作为程序员,我们应该尝试支持更新的模型。尝试您的操作并让异常处理完成其工作,使您的代码可以在任何透明地允许您需要的操作的系统下工作,并且了解并准备使用 sudo 是一个很好的接触(因为它是迄今为止最广泛的受控系统权限委派工具)。
If you really want your code to be robust across a wide variety of Linux configurations I'd suggest that you consider the corner cases where someone may be using SELinux, or filesystem ACLs, or the "capabilities" features that have been in the Linux kernel since v. 2.2 or so. Your process might be running under some wrapper that has used SELinux, or some Linux capabilities library, such as libcap2 libcap-ng, or fscaps or elfcap via something more exotic like Niels Provos' wonderful and sadly under-appreciated systrace system.
All of these are ways that you code might be running as non-root and yet your process might have been delegated the necessary access to perform its work without EUID==0.
So I'd suggest that you consider writing your code more Pythonically, by wrapping operations that may fail due to permissions or other issues with exception handling code. If you're shelling out to perform various operations (e.g. using the
subprocess
module) you might offer to prefix all such calls withsudo
(as a command line, environment, or .rc file option, for example). If it's being run interactively you can offer to re-execute any commands that raise permissions related exceptions usingsudo
(optionally only if you findsudo
on the os.environ['PATH']).Overall it's true that most Linux and UNIX systems still have most of their administration done by a 'root' privileged user. However, it's old school and we, as programmers, should try to support newer models. Trying your operations and letting the exception handling do its job allows your code to work under any system that transparently permits the operations you need, and being aware of and ready to use
sudo
is a nice touch (as it is, by far, the most widespread tool for controlled delegation of system privileges).如果脚本未使用
sudo
运行,则SUDO_UID
不可用。SUDO_UID
is not available if script is not run withsudo
.回答问题的第二部分
(抱歉评论框太小)
Paul Hoffman,你是对的,我只解决了你的问题中涉及内在函数的一部分,但如果不能的话,它就不是一种有价值的脚本语言。 t 处理
apt-get
。首选库有点冗长,但它可以完成工作:但是
Popen
是一个通用工具,可以为方便起见进行包装:现在我们回到异常处理。我将拒绝对 subprocess 模块类似 Java 的过度通用性发表评论。
Answer to the second part of the question
(sorry the comment box was too small)
Paul Hoffman, you are correct, I only addressed one part of your question dealing with intrinsics, but it wouldn't be a worthy scripting language if it couldn't handle
apt-get
. The preferred library is a tad verbose but it does the job:But
Popen
is a generalized tool and can be wrapped for convenience:And now we're back to exception handling. I will decline to comment on the Java-like over-generality of the subprocess module.
我的应用程序使用此代码:
My app works with this code:
这完全取决于您希望应用程序的便携性。如果您指的是业务,我们必须假设管理员帐户并不总是等于 0。这意味着检查 euid 0 是不够的。问题是,在某些情况下,一个命令的行为就像您是 root 一样,而下一个命令会因权限被拒绝而失败(想想 SELinux 等)。因此,最好是优雅地失败并在适当的时候检查 EPERM errno。
It all depends how portable you want you app to be. If you mean bussiness, the we have to assume that administrator account does not always equal 0. This means that checking for euid 0 is not enough. Problem is, there are situations where one command will behave as if you are root and next will fail with permission denied (think SELinux & co.). Therefore it's really better to fail gracefully and check for EPERM errno whenever it's appropriate.
我们不需要把事情复杂化..
We don't need to complicate things..
您可以使用此函数来检查:
参考:
此代码片段取自
github.com/zulip/zulip
https://github.com/zulip/ zulip/blob/39c6a01c7493ba55277c31ba9034ebc05dcbd9c3/scripts/lib/zulip_tools.py#L545-L548
You can use this function to check:
Reference:
This code snippet was taken from
github.com/zulip/zulip
https://github.com/zulip/zulip/blob/39c6a01c7493ba55277c31ba9034ebc05dcbd9c3/scripts/lib/zulip_tools.py#L545-L548