如何在不使用命令的情况下以编程方式关闭/重启 linux 机器(运行时)

Posted

技术标签:

【中文标题】如何在不使用命令的情况下以编程方式关闭/重启 linux 机器(运行时)【英文标题】:How to shutdown/reboot linux machine programatically without using commands(Runtime) 【发布时间】:2017-03-14 02:17:28 【问题描述】:

在 Windows 中,可以通过 Java 程序通过本地 (JNA) 调用 Windows API 中的 ExitWindowsEx 函数来关闭机器。我在linux中寻找类似的东西。我知道这可以通过执行命令来完成,但是我不能依赖解析人类可读的文本。

IPC(DBus) 是唯一的方法,还是可以本地加载一些库并本地调用关闭方法。如果有更简单的方法,请告诉我。

Using JNA or similar to shutdown and restart computer in linux and mac

我之前看过这个问题,但它没有提供有关如何以编程方式执行此操作的答案。

【问题讨论】:

看看busybox halt.c 你可以使用 SSH 吗?这可能是您将获得的最佳人类可读解析。它会给你一切,直到关机的那一刻。有很多种口味:Python、Java、C# @ThisClark 我正在尝试自动管理我的服务器。该程序存在,因此我不必登录。我将通过 java 套接字发送命令来关闭机器。我有一个桌面应用程序连接到我发送命令的套接字。 【参考方案1】:

你的程序不能只调用sh 并执行关机命令吗?像那样(需要root):

system("shutdown");

或者如果是桌面会话:

system("dbus-send --system --print-reply --dest=org.freedesktop.login1 /org/freedesktop/login1 "org.freedesktop.login1.Manager.PowerOff" boolean:true");

或者您可以改为包含一个 DBus 连接器库并进行适当的 IPC 调用。

【讨论】:

是否有提供我可以通过 dbus 访问的各种功能的文档? DBus 是一种调用机制。可访问的内容取决于安装的服务。我通常通过d-feet dbus GUI 浏览器程序(或gdbus introspect,如果在命令行中)查看可用的内容,然后找出对象对应的服务。服务在某处有他们的文档(如freedesktop.org/wiki/Software/systemd/logind)。 DBus 中的每个类都由一个 xml 文件定义(login1 为“org.freedesktop.login1.xml”)。编程语言的绑定是从这些 xml 文件中生成的(就像在 SOAP 中一样)。 不幸的是,我找不到能够与 DBus 连接的准备就绪的 Java 库。也许在我的产品 SDLC 的下一次迭代中,我将在现有 DBus 库的基础上构建它以使其正常工作。设法通过 POSIX 找到解决方案。【参考方案2】:

所以我在网上做了一些研究后自己设法找到了解决方案。有一个名为 JNA(Java Native Access)的库,可让您本地加载库并解析和依赖关系。使用 JNA,我通过接口在 java 上加载了 POSIX 库。以 sudo 运行代码将让您关闭或重新启动机器。这是代码。

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
import com.sun.jna.ptr.IntByReference;

public interface CLibrary extends Library 
public CLibrary INSTANCE = (CLibrary) Native.loadLibrary(Platform.isWindows()?"msvcrt":"c",CLibrary.class);

int kill(long pid, int sig);
int reboot(int magic, int magic2, int cmd, IntByReference arg);
int reboot(int cmd);

int LINUX_REBOOT_MAGIC1 = 0xfee1dead;
int LINUX_REBOOT_MAGIC2 = 672274793;
int LINUX_REBOOT_MAGIC2A = 85072278;
int LINUX_REBOOT_MAGIC2B = 369367448;
int LINUX_REBOOT_MAGIC2C = 537993216;

int LINUX_REBOOT_CMD_RESTART = 0x01234567;
int LINUX_REBOOT_CMD_HALT = 0xCDEF0123;
int LINUX_REBOOT_CMD_CAD_ON =0x89ABCDEF;
int LINUX_REBOOT_CMD_CAD_OFF = 0x00000000;
int LINUX_REBOOT_CMD_POWER_OFF = 0x4321FEDC;
int LINUX_REBOOT_CMD_RESTART2 = 0xA1B2C3D4;
int LINUX_REBOOT_CMD_SW_SUSPEND = 0xD000FCE2;
int LINUX_REBOOT_CMD_KEXEC = 0x45584543;



p s v main()
   CLibrary.INSTANCE.reboot(Clibrary.LINUX_REBOOT_CMD_POWER_OFF);

注意:这仅适用于 Linux,不适用于 Windows。要以编程方式关闭机器,请查找ExitWindowsEx。内置于 JNA 库中。

所有C POSIX头文件都可以找到C POSIX Library - Wikipedia

【讨论】:

以上是关于如何在不使用命令的情况下以编程方式关闭/重启 linux 机器(运行时)的主要内容,如果未能解决你的问题,请参考以下文章

如何在不使用 UINavigationController 的情况下以编程方式进入 rootViewController

如何在不使用外部主机的情况下以编程方式查找设备的外部 IP 地址?

如何在不使用第三方的情况下以编程方式从 Chase 下载我的银行交易?

如何在不使用 HTML 表单的情况下以编程方式将 POST 请求发送到 JSF 页面?

如何在不使用 Facebook 登录/注销按钮的情况下以编程方式从 Facebook SDK 3.0 注销?

如何在不使用 rest admin api 的情况下以编程方式(java)更新 keycloak 的用户详细信息?