I am trying to run a command on a windows machine running a python client program. It needs to return a value to the server before executing the command.
def shutdown():
if OS_LINUX:
os.system("sleep 10s && sudo shutdown &")
elif OS_WIN:
os.system(<What to put HERE>)
return (1,"Shutting down")
As you can see, the unix command works just fine.
In the background, it runs sleep for 10 seconds and after that is done, it runs sudo shutdown. The function is allowed to return properly and the server gets notice that the client is shutting down BEFORE "sudo shutdown" is run.
However, on the windows side of things, I can't seem to run shutdown -s after a delay AND run it in the background.
This is what I have so far:
start /b /wait timeout 10 && shutdown -s
I have tried many variations of it: with/without /wait and /b, using ping instead of timeout, sending the output of ping/timeout to ">nul", etc.
This one has been the closest to what I want, but timeout takes over the command line until it is done, which doesn't allow my return statement to be covered in shutdown() before "shutdown -s" is run. This leaves the server hanging until it times out, which is not what I want the user to see, especially because I can't guarantee that the client didn't just loose connection at the same time the server told it to shutdown.
I might be able to solve the problem by throwing "timeout 10 && shutdown -s" in a batch script and running that in the background using os.system("start /b shutdown_script.bat"), but this client program needs to be just a single portable file for distribution reasons.
The solution is easy on unix, what am I missing on dos?
EDIT: Running os.system("shutdown -s") command (at least on win10) causes a screen to show to the user saying that the system will be shutdown. This allows my function to work properly and return a value to the server. This is NOT the case for other commands like hibernate ("shutdown -h"), and not necessarily the case on older version of windows either. The problem still remains for other commands, such as closing the client program remotely.
EDIT2: I also need to run commands for hibernate, and logoff. Shutdown -h and -l respectively. The -t parameter of shutdown only works with -s and -r (At least on windows 10)
I ended up solving the problem using schtasks because shutdown only supports a timeout for /s and /r.
The python code adds a 1 minute offset to the current time (schtasks doesn't deal in seconds), then calls os.system("schtasks.....") with a /f parameter to avoid schtasks holding up the console asking for a y/n overwrite.
def get_time_offset(offset):
now = datetime.datetime.now()
offset_now = now + datetime.timedelta(minutes=offset)
offset_now_time = offset_now.time()
future_time = (str(offset_now_time.hour) + ":" + str(offset_now_time.minute) + ":" + str(offset_now_time.second) )
return future_time
def sch_task(name, time, task):
os.system("schtasks /create /tn \"" + str(name) + "\" /sc once /st " + str(time) + " /tr \"" + str(task) + "\" /f")
The final call looks like this:
sch_task("client_hibernate", get_time_offset(1), "shutdown /h")
It will run 1 minute after the call is made.
The only problem with this solution is that schtasks only has precision by the minute, so you can't schedule a task for less than a minute in the future.
I will probably write a multithreaded timer in python to run the command instead of relying on schtasks for windows and sleep for linux.