|
|
|
|
@ -24,6 +24,7 @@ import signal
|
|
|
|
|
import socket
|
|
|
|
|
import sys
|
|
|
|
|
import threading
|
|
|
|
|
import time
|
|
|
|
|
import warnings
|
|
|
|
|
import webbrowser
|
|
|
|
|
|
|
|
|
|
@ -351,6 +352,51 @@ class NotebookPasswordApp(JupyterApp):
|
|
|
|
|
set_password(config_file=self.config_file)
|
|
|
|
|
self.log.info("Wrote hashed password to %s" % self.config_file)
|
|
|
|
|
|
|
|
|
|
def shutdown_server(server_info, timeout=5, log=None):
|
|
|
|
|
"""Shutdown a notebook server in a separate process.
|
|
|
|
|
|
|
|
|
|
*server_info* should be a dictionary as produced by list_running_servers().
|
|
|
|
|
|
|
|
|
|
Will first try to request shutdown using /api/shutdown .
|
|
|
|
|
On Unix, if the server is still running after *timeout* seconds, it will
|
|
|
|
|
send SIGTERM. After another timeout, it escalates to SIGKILL.
|
|
|
|
|
|
|
|
|
|
Returns True if the server was stopped by any means, False if stopping it
|
|
|
|
|
failed (on Windows).
|
|
|
|
|
"""
|
|
|
|
|
from tornado.httpclient import HTTPClient, HTTPRequest
|
|
|
|
|
url = server_info['url']
|
|
|
|
|
pid = server_info['pid']
|
|
|
|
|
req = HTTPRequest(url + 'api/shutdown', method='POST', body=b'', headers={
|
|
|
|
|
'Authorization': 'token ' + server_info['token']
|
|
|
|
|
})
|
|
|
|
|
if log: log.debug("POST request to %sapi/shutdown", url)
|
|
|
|
|
HTTPClient().fetch(req)
|
|
|
|
|
|
|
|
|
|
# Poll to see if it shut down.
|
|
|
|
|
for _ in range(timeout*10):
|
|
|
|
|
if check_pid(pid):
|
|
|
|
|
if log: log.debug("Server PID %s is gone", pid)
|
|
|
|
|
return True
|
|
|
|
|
time.sleep(0.1)
|
|
|
|
|
|
|
|
|
|
if sys.platform.startswith('win'):
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
if log: log.debug("SIGTERM to PID %s", pid)
|
|
|
|
|
os.kill(pid, signal.SIGTERM)
|
|
|
|
|
|
|
|
|
|
# Poll to see if it shut down.
|
|
|
|
|
for _ in range(timeout * 10):
|
|
|
|
|
if check_pid(pid):
|
|
|
|
|
if log: log.debug("Server PID %s is gone", pid)
|
|
|
|
|
return True
|
|
|
|
|
time.sleep(0.1)
|
|
|
|
|
|
|
|
|
|
if log: log.debug("SIGKILL to PID %s", pid)
|
|
|
|
|
os.kill(pid, signal.SIGKILL)
|
|
|
|
|
return True # SIGKILL cannot be caught
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class NbserverStopApp(JupyterApp):
|
|
|
|
|
version = __version__
|
|
|
|
|
@ -364,14 +410,18 @@ class NbserverStopApp(JupyterApp):
|
|
|
|
|
if self.extra_args:
|
|
|
|
|
self.port=int(self.extra_args[0])
|
|
|
|
|
|
|
|
|
|
def shutdown_server(self, server):
|
|
|
|
|
return shutdown_server(server, log=self.log)
|
|
|
|
|
|
|
|
|
|
def start(self):
|
|
|
|
|
servers = list(list_running_servers(self.runtime_dir))
|
|
|
|
|
if not servers:
|
|
|
|
|
self.exit("There are no running servers")
|
|
|
|
|
for server in servers:
|
|
|
|
|
if server['port'] == self.port:
|
|
|
|
|
self.log.debug("Shutting down notebook server with PID: %i", server['pid'])
|
|
|
|
|
os.kill(server['pid'], signal.SIGTERM)
|
|
|
|
|
print("Shutting down server on port", self.port, "...")
|
|
|
|
|
if not self.shutdown_server(server):
|
|
|
|
|
sys.exit("Could not stop server")
|
|
|
|
|
return
|
|
|
|
|
else:
|
|
|
|
|
print("There is currently no server running on port {}".format(self.port), file=sys.stderr)
|
|
|
|
|
|