使用python关闭计算机(linux)

Posted

技术标签:

【中文标题】使用python关闭计算机(linux)【英文标题】:shutting down computer (linux) using python 【发布时间】:2014-05-25 15:35:05 【问题描述】:

我正在尝试编写一个脚本,如果该命令满足一些要求,它将关闭计算机

    os.system("poweroff")

也试过

    os.system("shutdown now -h")

还有其他一些。但是当我运行它时没有任何反应,计算机通过代码而不会崩溃或产生任何错误消息并正常终止脚本,而不会关闭计算机。

在python中如何关闭计算机?

编辑:

似乎我尝试过的命令需要root访问权限。有没有办法在没有提升权限的情况下从脚本关闭机器?

【问题讨论】:

poweroffshutdown 需要特权。您使用哪个用户来执行脚本? 我一直以“普通用户”的身份运行它...谢谢,将编辑问题以反映该解决方案应该在没有 root 访问权限的情况下工作 您不能以普通用户权限关闭系统。你的最终目标是什么? 如果您的脚本还执行其他不应以特权运行的操作,您可能需要查看 polkit 或 sudo。如果您在使用 systemd 的发行版上,它的 API 也可以帮助您 - 默认情况下,如果非特权用户是唯一登录的用户,它会尊重来自非特权用户的关闭请求。无论如何,您总是至少需要help 来自运行特权的东西(systemd 和 polkit 是具有 dbus apis 的长时间运行的特权进程,sudo 和 su 是 setuid 根二进制文件),因为关闭 特权操作。 好的,谢谢。最终目标是让脚本在完成一项耗时的任务后关闭计算机,以免它过热;)......以 sudo 运行它可以满足我的要求 【参考方案1】:
import os
os.system("shutdown now -h")

以 root 权限执行您的脚本。

【讨论】:

os.system("sudo shutdown now -h") #为我工作 ;-)【参考方案2】:

那里的许多 Linux 发行版都需要超级用户权限才能执行 shutdownhalt,但是,如果您坐在计算机上,为什么不用 root 就可以关闭它?你打开一个菜单,点击Shutdown,它会在你没有变成root的情况下关闭,对吧?

嗯...这背后的基本原理是,如果您可以物理访问计算机,则几乎可以拉电源线并将其关闭,所以现在,许多发行版都允许电源-off 尽管可以通过dbus 访问本地系统总线。 dbus(或者通过它公开的服务)有问题吗?它在不断变化。我建议安装一个 dbus 查看器工具,例如 D-feet(请注意:它仍然很难可视化,但它可能会有所帮助)

看看these Dbus shutdown scripts。

如果您的分发版中仍有 HAL(即将被弃用),请尝试以下操作:

import dbus
sys_bus = dbus.SystemBus()
hal_srvc = sys_bus.get_object('org.freedesktop.Hal',
                              '/org/freedesktop/Hal/devices/computer')
pwr_mgmt =  dbus.Interface(hal_srvc,
                'org.freedesktop.Hal.Device.SystemPowerManagement')
shutdown_method = pwr_mgmt.get_dbus_method("Shutdown")
shutdown_method()

这适用于 Ubuntu 12.04(我刚刚关闭计算机以确保它正常工作)。如果你有更新的东西......好吧,它可能无法正常工作。这是这种方法的缺点:它是非常特定于分布的。

您可能需要安装 dbus-python 软件包才能使其正常工作 (http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.html)

更新 1:

我一直在做一些研究,看起来这是通过ConsoleKit 在较新的 Ubuntu 版本中完成的。我已经在我的 Ubuntu 12.04(它具有已弃用的 HAL 和更新的 ConsoleKit)中测试了以下代码,它确实关闭了我的计算机:

>>> import dbus
>>> sys_bus = dbus.SystemBus()
>>> ck_srv = sys_bus.get_object('org.freedesktop.ConsoleKit',
                                '/org/freedesktop/ConsoleKit/Manager')
>>> ck_iface = dbus.Interface(ck_srv, 'org.freedesktop.ConsoleKit.Manager')
>>> stop_method = ck_iface.get_dbus_method("Stop")
>>> stop_method()

更新 2:

可能为什么你可以做到这一点而不是root 值得更广泛的解释。让我们关注较新的ConsoleKitHAL 更加复杂和混乱,恕我直言)。

ConsoleKit 是在您的系统中以root 运行的服务:

borrajax@borrajax:/tmp$ ps aux|grep console-kit
root 1590  0.0  0.0 1043056 3876 ? Sl   Dec05   0:00 /usr/sbin/console-kit-daemon --no-daemon

现在,d-bus 只是一个消息传递系统。您有一个服务,例如 ConsoleKit,它向d-bus 公开了一个接口。公开的方法之一是Stop(如上所示)。 ConsoleKit 的权限由 PolKit 控制,它(尽管基于常规 Linux 权限)为 “谁可以做什么”。例如,PolKit 可以说 “如果用户登录到计算机,则允许他做某事。如果它是远程连接的,则不要。” .如果PolKit 确定您的用户可以调用ConsoleKitStop 方法,则该请求将通过(或通过)@ 987654351@ 到 ConsoleKit(随后会关闭您的计算机,因为它可以...因为它值得...因为它是 root

进一步阅读:

What are ConsoleKit and PolicyKit? How do they work? ArchWiki PolKit

总结一下:如果没有root,您将无法关闭计算机。但是您可以告诉以root 运行的服务为您关闭系统。

更新 3:

2021 年 12 月,也就是原始答案写完七年后,我不得不再次这样做。这一次,在 Ubuntu 18.04 中。

不出所料,事情似乎发生了一些变化:

PowerOff 功能似乎是通过新的org.freedesktop.login1 服务处理的,该服务是“新”(咳!咳!) SystemD 机器 的一部分em>。 dbus Python 包似乎是deprecated and/or considered "legacy"。但是,可以使用新的 PyDbus library 代替。

所以我们仍然可以使用非特权脚本关闭机器:

#! /usr/bin/python3
from pydbus import SystemBus
bus = SystemBus()

proxy = bus.get('org.freedesktop.login1', '/org/freedesktop/login1')
if proxy.CanPowerOff() == 'yes':
    proxy.PowerOff(False)  # False for 'NOT interactive'

更新 3.1:

它看起来不像我想的那样 X-D

@Roeften 在同一线程中已经有an answer。

奖金

我在您的一个 cmet 中读到,您想在完成一项耗时的任务后关闭计算机以防止其过热...您是否知道您可以可能在给定的时间打开它使用 RTC 的时间? (见this 和this)很酷,嗯? (当我发现我可以做到这一点时,我非常兴奋......):-D

【讨论】:

@black:再来一次? 熟悉 是不是太严重了?如果是这样的话,那么是的。编程很有趣!和令人兴奋的!!!而且很酷 :-) 我实际上指的是 DaveHax。不用担心?【参考方案3】:

关闭系统的最佳方法是使用以下代码

import os
os.system('systemctl poweroff') 

【讨论】:

这仅在您使用 systemd 时有效。不是所有的 linux 发行版都有这个。【参考方案4】:

任何关闭...没有提升权限的方法?

不,没有(幸运的是!)。

请记住,您可以使用多种系统功能来简化普通用户的权限升级:

sudo setuid setcap

【讨论】:

【参考方案5】:

只是为使用 logind(较新的 fedora 系统)的用户添加 @BorrajaX 的答案:

import dbus
sys_bus = dbus.SystemBus()
lg = sys_bus.get_object('org.freedesktop.login1','/org/freedesktop/login1')
pwr_mgmt =  dbus.Interface(lg,'org.freedesktop.login1.Manager')
shutdown_method = pwr_mgmt.get_dbus_method("PowerOff")
shutdown_method(True)

【讨论】:

【参考方案6】:

Linux:

import subprocess
cmdCommand = "shutdown -h now"
process = subprocess.Popen(cmdCommand.split(), stdout=subprocess.PIPE)

窗户:

import subprocess
cmdCommand = "shutdown -s"
process = subprocess.Popen(cmdCommand.split(), stdout=subprocess.PIPE)

【讨论】:

【参考方案7】: 如果您想从根目录执行它,@Rahul R Dhobi 的回答效果很好:
import os
os.system("shutdown now -h")

执行: sudo python_script.py


如果您需要在没有 root 权限的情况下执行它:
import subprocess
import shlex
cmd = shlex.split("sudo shutdown -h now")
subprocess.call(cmd)

执行: $ python_script.py # no sudo required

【讨论】:

【参考方案8】:

我正在使用 Fedora,它适用于我。我需要做的就是在终端中写下这一行:

$ sudo python  yourScript.py

【讨论】:

【参考方案9】:

有一种方法可以在不使用提升权限的情况下关闭计算机。

import os
subprocess.call(['osascript', '-e', 'tell app "system events" to shut down'])

【讨论】:

osascript 不是 linux 啊,对不起,我还是新手:D

以上是关于使用python关闭计算机(linux)的主要内容,如果未能解决你的问题,请参考以下文章

Python初学心得体会

计算Linux目录中的文件数? [关闭]

debian关闭log

如何在 Linux 中控制计算机 RGB LED [关闭]

具有两个浮点数作为参数的python计算器[关闭]

使用python计算从gps轨迹点行进的距离[关闭]