为什么我们需要在终端中以root身份执行关机和重启操作?

当我们安装/删除/更新软件包或进行任何需要管理员权限的更改时,系统会提示我们输入具有sudo特权的管理员用户的密码 - 这在图形界面和终端中都会发生。

prompt via gui

然而,如果我们尝试通过终端关机和重新启动,它会抱怨我们需要是root

$ reboot
reboot: Need to be root

$ shutdown now
shutdown: Need to be root

但是当我们通过右上角的齿轮执行这些操作时,从来没有要求输入密码。

cog-wheel menu

为什么会有这个差异呢?

5好问题..你知道吗,我刚要问同样的问题。我的情况是使用快捷键关闭Ubuntu。也就是说,每当我按下一些指定的键,比如ctrl+super+s时,它会执行命令sudo shutdown -h now,但问题是,如果没有对shutdown的访问权限,它永远不会生效。因为在按下快捷键之后,它将在哪里/如何询问密码以进入系统。希望你明白我的处境.. :) - Saurav Kumar
参见:http://askubuntu.com/questions/1190/how-can-i-make-shutdown-not-require-admin-password - Takkat
另请参阅:http://unix.stackexchange.com/questions/18503/how-does-the-power-button-shut-the-computer-down-without-root-permission - amyassin
6个回答

关于齿轮的关闭检查是为了确定您是否被允许关闭机器。这是通过PolicyKit完成的。在关机时,会检查文件/usr/share/polkit-1/actions/org.freedesktop.consolekit.policy中的语句。
<action id="org.freedesktop.consolekit.system.stop">
  <description>Stop the system</description>
  <message>System policy prevents stopping the system</message>
  <defaults>
    <allow_inactive>no</allow_inactive>
    <allow_active>yes</allow_active>
  </defaults>
</action>

PolicyKit触发dbus-send命令。在关机情况下,它将是:

dbus-send --system --print-reply --dest=org.freedesktop.Hal /org/freedesktop/Hal/devices/computer org.freedesktop.Hal.Device.SystemPowerManagement.Shutdown

有一个以root权限在后台运行的守护进程,可以为您调用关机命令。
当您希望能够通过命令行“一种传统方式”关闭机器(如shutdown、reboot、halt等),您需要为这些命令添加suid位。但请注意,系统中任何具有shell访问权限的用户都可以关闭您的机器。

15一个稍微更安全的选择是允许sudoers无需密码即可进行关机等操作。这很容易实现:输入sudo visudo,添加%sudo ALL = NOPASSWD: /sbin/shutdown, /sbin/poweroff, /sbin/halt, /sbin/reboot,保存并退出。这样,命令行重启仍然需要使用sudo reboot,但您不必输入密码。 - Sebastian Thürrschmidt

Ubuntu是GNU/Linux操作系统的一个发行版,它属于Unix系统家族,这是一种现代操作系统的常见架构。
传统上,Unix运行在大型机上。中央计算设施通过远程终端为数十个或数百个用户提供服务。由于所有用户都依赖于大型机的可用性,因此不允许任何单个用户发出关机命令。这是Unix架构的基本思想 - 除非超级用户进程调用相应的函数,否则系统内核永远不会初始化关机。
在当代桌面系统中,开发人员经历了一些困难,以使关机对普通桌面用户可用。一种常见的技术是让登录管理器(通常在root用户的安全上下文中运行)处理关机和重启。在这种情况下,图形界面发出请求给登录管理器来关机。这涉及使用进程间通信(IPC),通常通过dbus服务进行。
上述的policykit通过提供一个标准化的框架来扩展这个过程,通过该框架,登录管理器(或提供关机服务的其他程序)可以检查哪些用户被允许引起关机,并且管理员可以相应地配置这些权限。
一些桌面环境不使用基于IPC的服务,而是使用一组辅助程序来提供相同或类似的功能。这些辅助程序可以通过机制调用,允许切换到超级用户上下文,例如sudo、suid或类似sudo的policykit机制。
无论如何,在shell上愚蠢的传统关机程序不是以这种方式工作,它要求您确保它在超级用户上下文中运行。

因为Linux通常用作服务器或类似的用途,而且SSH登录到Linux系统,即使是普通的Ubuntu笔记本电脑也很常见。
问题是,您可能不希望具有SSH访问权限的人能够关闭它,特别是当可能有其他远程登录用户在使用时。拥有GUI访问权限的人——嗯,他可以使用物理电源按钮自行关闭它。
此外,远程登录的用户将无法重新启动它。

当我提出这个问题的时候,我没有想到过,但我猜在Ubuntu中有选项可以安装GUI包在远程服务器上,并使用远程服务器上的GUI而不是命令行。(类似于Windows远程桌面或Teamviewer的工作方式)。所以这将否定一个使用Ubuntu的人可以通过物理电源按钮关机的假设。 - Aditya
@aditya 需要以那种方式设置服务器,这是管理员必须决定的。 - Manishearth
是的。要能够安装软件包并进行必要的配置,需要获取root权限。但是昨天在阅读你的回答时,我想到了这种情况,所以想与你分享一下 :-) - Aditya

当我通过图形界面重新启动时,我可以在不输入sudo密码的情况下进行操作。
只有当你是唯一登录的用户时才能这样做。如果有其他用户(包括控制台用户),你可能需要输入root密码。这在OS X和较新的Windows版本上都是一样的。

为什么会这样?Ubuntu系统内部发生了什么事情?以下是相应的命令:
/usr/bin/dbus-send --system --print-reply --dest="org.freedesktop.ConsoleKit" /org/freedesktop/ConsoleKit/Manager org.freedesktop.ConsoleKit.Manager.Stop

D-Bus是一种进程间通信机制,用于同一主机上运行的进程之间的本地通信。
D-Bus比UDP等底层消息传递协议更"智能"。另一方面,它将消息作为离散项传递,而不是连续的数据流。
D-Bus对其传递的数据具有结构化视图,并以二进制形式处理数据;包括各种宽度的整数、字符串等。由于数据对于D-Bus来说不仅仅是"原始字节",因此可以验证消息。
-- Free Desktop 为什么"shutdown"命令不只是检查是否有用户登录呢?老实说,这似乎是一个不太周到的功能。我可以想象有时候这样做可以节省时间,但一致的控制台通常更受欢迎。我不希望命令在运行后有时需要密码,有时则不需要。
我的代词是他/他。

还有通过 qdbus 应用程序的更短版本。 - Sergiy Kolodyazhnyy
当从DE(在这种情况下为GNOME)关闭/注销时,无论是通过GDM登录的另一个用户还是通过tty登录的另一个用户,我都不需要输入root /用户的sudo密码。 - kos
@kos hu,这很奇怪。那个截图是Gnome 3的,而且我同时在gui和tty登录着。 - Tim
我的意思是我收到了相同的信息,但是点击“关机”按钮后系统就会立即关闭。我还请Fabby测试了一下,他也遇到了同样的情况,不太清楚是怎么回事。 - kos
@kos 哦,等一下。 - Tim

你不需要以 root (超级用户) 的身份通过图形界面发起关机的原因主要是出于方便普通桌面用户的考虑。系统“知道”你是登录在控制台上的用户,所以如果你错误地关闭了计算机,可以假设你能够重新打开它。

对于在 shell (命令行界面) 下的用户,你很可能是远程登录的,所以系统要求你必须以 root 的身份登录才能执行关机命令。这样可以防止其他人在使用服务器时,被一个普通用户关闭而没有人在那里重新启动计算机。

关于为什么关机操作没有提供超级用户密码的图形提示,可能只是因为在那里获得不到真正的实用性 - 如果你在控制台上,图形提示会出现,你可以直接使用齿轮菜单。如果你想要在关机时使用超级用户密码的命令行提示符,已经可以通过 "sudo shutdown" 命令实现。


在一个多用户系统中,你最不希望的就是用户随机重启服务器,因此Reboot命令的命令行版本只能由超级用户执行,所以你需要以root身份登录或拥有sudo权限。
同样适用于Halt和PowerOff命令。

2谢谢你的回答,我明白作为一个使用被数十人共用的机器的用户,我不应该有权限重新启动机器。但是当我选择通过鼠标而不是键盘来重新启动时,Ubuntu(或几乎所有桌面发行版)会做什么呢?它们允许这样做而无需特权。 - fweigl
3诸如systemctl、loginctl、systemd、系统策略等组件都允许当前登录的用户在不明确要求根访问权限的情况下访问某些根功能,以使桌面体验更加用户友好,但这些组件不一定调用命令行命令来执行这些任务。 - Jeff Sereno