如何在C++程序内部重新启动Linux?

21

我有一个基于Qt 4的GUI,需要在下拉菜单中添加一个选项,允许用户选择重新启动计算机。我知道这似乎与通过其他方式重新启动计算机的能力重复,但是这个选项必须保留。我尝试使用system()来调用以下内容:

  1. 一个suid-root shell脚本
  2. 一个非suid shell脚本
  3. 一个suid-root二进制程序

但是所有这些都只会导致输出“reboot: must be superuser”。使用system()直接调用reboot也会产生相同的结果。我并不特别喜欢使用system()来执行此操作,但它似乎是最直接的选择。

我如何从GUI重新启动系统?


15
请按下复位按钮 (Please push the reset button now)。 - Byron Whitlock
2
你尝试以超级用户身份运行它了吗? - fingerprint211b
12
在Windows中有许多方法可以实现这一点,但大多数方法并非故意设计的。 - RickNotFred
http://blogs.msdn.com/oldnewthing/archive/2010/03/24/9983984.aspx - Billy ONeal
这可以在KDE应用程序中完成。例如,KGet和KTorrent都可以在下载完成后关闭计算机。但我不知道它们用于执行此操作的是KDE特定的还是你可以在没有KDE的情况下使用Qt来完成。 - Jonathan M Davis
3
FYI,Linux会忽略脚本上的suid位,因为允许suid脚本存在一个严重的安全问题。请参阅此处的第5.5.3节:http://docstore.mik.ua/orelly/networking/puis/ch05_05.htm - Tyler McHenry
7个回答

20

reboot 函数在 Linux 程序员手册 中有描述。在 glibc 下,可以传递 RB_AUTOBOOT 宏常量来执行重启操作。

请注意,如果在调用 reboot 之前未调用 sync,可能会丢失数据。

Linux 中使用 glibc

#include <unistd.h>
#include <sys/reboot.h>

sync();
reboot(RB_AUTOBOOT);

9
在Linux中:
#define LINUX_REBOOT_CMD_POWER_OFF 0x4321fedc   

sync();
reboot(LINUX_REBOOT_CMD_POWER_OFF);

6
如果您正在使用glibc版本,则应在上述代码中包含#include <sys/reboot.h>...如果是这样,只需在该头文件中使用#define RB_POWER_OFF即可。 - AceFunk

4

您尝试过使用gksudo运行shell脚本吗?类似以下内容:

gksudo shutdown -r

希望这样做可以弹出一个模态对话框,以获取用户凭据。


其实你不需要将它作为一个 shell 脚本运行,只需使用 execv 命令,或者如果你真的需要 shell 脚本所带来的 PATH 功能,可以使用 execvp 命令。 - Cascabel

3
这应该在几乎任何Linux系统上都能行得通。
#include <unistd.h>
#include <sys/reboot.h>

int main () {
  sync();
  setuid(0);
  reboot(RB_AUTOBOOT);
  return(0);
}

然后只需使用gcc reboot.c -o reboot编译,并在二进制文件上执行chmod a+s reboot。 然后像任何用户一样调用重启程序,系统应该会顺利重启。 通过GUI完成此操作的方式因桌面环境而异,例如,如果您的桌面环境是KDE,则与在Fluxbox下执行相同操作有很大不同。

1

像已经提到的那样,对shell脚本进行suid操作是非常危险的(这就是为什么它不起作用的原因)。

我怀疑对二进制文件进行suid操作不起作用,因为系统会使用用户的实际UID而不是suid UID来生成其子进程,同样出于安全原因(这将允许您替换任何要调用并以root身份运行的二进制文件)。

您可以将reboot的副本放在受保护的位置,以便只有您想要的用户才能执行它,并且然后对其进行suid-root操作。

或者,给他们sudoer权限,只允许执行您关心的命令,并将其输出到类似于"ksh -c 'sudo reboot'"的东西。


0

以二进制形式尝试调用

setuid (0);

在 system() 调用之前。


谢谢您的建议,但是当程序从另一个程序调用时,这种方法并不起作用。但是如果直接从命令行调用程序,则可以正常工作。 - Dave K

0
你如何在命令行上重启系统?
基本上只需要执行以下命令:
system( <however you wouuld do it from the command line> );

2
谢谢您的建议,但这正是我们尝试过的,而且它并不起作用。 - Dave K

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接