【发布时间】:2016-12-17 19:21:52
【问题描述】:
我正在尝试在运行 python 客户端程序的 Windows 机器上运行命令。它需要在执行命令之前向服务器返回一个值。
def shutdown():
if OS_LINUX:
os.system("sleep 10s && sudo shutdown &")
elif OS_WIN:
os.system(<What to put HERE>)
return (1,"Shutting down")
如您所见,unix 命令运行良好。
在后台,它会运行 sleep 10 秒,然后运行 sudo shutdown。该函数被允许正确返回,并且在运行“sudo shutdown”之前,服务器会收到客户端正在关闭的通知。
但是,在 Windows 方面,我似乎无法在延迟后运行 shutdown -s 并在后台运行它。
这是我目前所拥有的:
start /b /wait timeout 10 && shutdown -s
我尝试了它的许多变体:带/不带 /wait 和 /b,使用 ping 代替超时,将 ping/timeout 的输出发送到“nul”等。
这个是最接近我想要的,但是 timeout 接管命令行直到它完成,这不允许我的 return 语句在运行“shutdown -s”之前在 shutdown() 中被覆盖。这会使服务器一直挂起,直到超时,这不是我希望用户看到的,尤其是因为我不能保证客户端没有在服务器告诉它关闭的同时失去连接。
我可以通过在批处理脚本中抛出“timeout 10 && shutdown -s”并使用 os.system("start /b shutdown_script.bat") 在后台运行它来解决问题,但是这个客户端程序出于分发原因,需要只是一个可移植文件。
unix 上的解决方案很简单,我在 dos 上缺少什么?
编辑:运行 os.system("shutdown -s") 命令(至少在 win10 上)会导致一个屏幕显示给用户,说系统将被关闭。这允许我的函数正常工作并向服务器返回一个值。对于像休眠(“shutdown -h”)这样的其他命令,情况并非如此,在旧版本的 Windows 上也不一定如此。其他命令仍然存在问题,例如远程关闭客户端程序。
EDIT2:我还需要运行休眠和注销命令。分别关闭 -h 和 -l。 shutdown 的 -t 参数仅适用于 -s 和 -r (至少在 windows 10 上)
【问题讨论】:
-
/l(注销)和/p(关机)调用ExitWindowsEx,不支持超时。/h(休眠),如果支持和启用,通过NtInitiatePowerAction系统调用实现,不支持超时。/s(关机)和/r(重启)调用InitiateSystemShutdownEx,除了/s与/hybrid配对调用InitiateShutdown。两者都支持最长 10 年的超时。 -
您可以使用 Python 内部的通用解决方案,例如
threading.Timer,它通过subprocess.check_call执行关机命令。如果您正在运行/s或/r,它们支持超时并向用户发出系统范围的警告,那么您可以跳过计时器。
标签: python windows command-line