Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NbserverStopApp: stop notebooks through cli - jupyter notebook stop <… #2388

Merged
merged 8 commits into from Apr 11, 2017

Conversation

@brookisme
Copy link
Contributor

@brookisme brookisme commented Apr 8, 2017

  • usage: jupyter notebook stop <PORT>
  • defaults to 8888
  • no tests (sorry)
@gnestor
Copy link
Contributor

@gnestor gnestor commented Apr 8, 2017

Thanks @brookisme! I tested and it's working for me!

@minrk Can you review?

Copy link
Member

@minrk minrk left a comment

Thanks! I think this makes sense in principle. I've made some comments in-line for updating the PR.

If you would like any help addressing the comments, feel free to ask.

"Produce machine-readable JSON output."),
)

json = Bool(True, config=True,

This comment has been minimized.

@minrk

minrk Apr 8, 2017
Member

json is unused and can be removed

version = __version__
description="Stop currently running notebook server for a given port"
kill_cmd='kill'
kill_signal='-3'

This comment has been minimized.

@minrk

minrk Apr 8, 2017
Member

signal should be an integer from the signal module, e.g.signal.SIGTERM

This comment has been minimized.

@brookisme

brookisme Apr 8, 2017
Author Contributor

using signal.SIGQUIT since signal.SIGTERM requests confirmation
UPDATE: SIGQUIT works fine. See comment below.

def start(self):
server=next((server for server in list_running_servers(self.runtime_dir) if server.get('port')==self.port),None)
if server:
subprocess.Popen([self.kill_cmd,self.kill_signal,str(server.get('pid'))],stdout=subprocess.PIPE).communicate()

This comment has been minimized.

@minrk

minrk Apr 8, 2017
Member

Rather than Popen(['kill', ...]), it would be better to use os.kill here.


flags = dict(
json=({'NbserverStopApp': {'json': True}},
"Produce machine-readable JSON output."),

This comment has been minimized.

@minrk

minrk Apr 8, 2017
Member

flags here are also unused and can be removed

else:
ports=[s.get('port') for s in list_running_servers(self.runtime_dir)]
if ports:
print("There is currently no server running on port {}.".format(self.port))

This comment has been minimized.

@minrk

minrk Apr 8, 2017
Member

This print statement can be moved up one level, and only print ports below.

This comment has been minimized.

@minrk

minrk Apr 8, 2017
Member

These print statements should also go on stderr, since they are error output.

This comment has been minimized.

@brookisme

brookisme Apr 8, 2017
Author Contributor

It we move this above if ports: the output for no running servers will be

There is currently no server running on port 8888
There are currently no running servers

Its seems the

There are currently no running servers

might be better. Thoughts?

print("Ports currently in use:")
for port in ports: print("\t* {}".format(port))
else:
print("There are currently no running servers")

This comment has been minimized.

@minrk

minrk Apr 8, 2017
Member

This should also end with self.exit(1) when no server can be found to stop.

@brookisme
Copy link
Contributor Author

@brookisme brookisme commented Apr 8, 2017

@minrk thanks for the feedback. This should be complete apart from the minor no servers running issue commented on above.

@gnestor
gnestor approved these changes Apr 9, 2017
@gnestor
Copy link
Contributor

@gnestor gnestor commented Apr 9, 2017

Should to docs be updated to reflect this new subcommand?


def start(self):
server=next((server for server in list_running_servers(self.runtime_dir) if server.get('port')==self.port),None)
if server: os.kill(server.get('pid'), signal.SIGQUIT)

This comment has been minimized.

@minrk

minrk Apr 10, 2017
Member

I think SIGTERM is probably the right signal here, instead of SIGQUIT.

This comment has been minimized.

@brookisme

brookisme Apr 10, 2017
Author Contributor

So strange... I could swear my initial tests requested confirmation after sending sigterm (which is why I switched to sigquit) but I just double checked and sigterm worked fine. Anyway its fixed now.

This comment has been minimized.

@takluyver

takluyver Apr 11, 2017
Member

Is it possible you tested with SIGINT initially? IIRC that's the one that asks for confirmation.

This comment has been minimized.

@brookisme

brookisme Apr 11, 2017
Author Contributor

probably something like that. apologies for confusion though - glad it worked in the end :)

@minrk minrk added this to the 5.1 milestone Apr 10, 2017
Copy link
Member

@takluyver takluyver left a comment

Other than these things, this looks good to me.

self.port=int(self.extra_args[0])

def start(self):
server=next((server for server in list_running_servers(self.runtime_dir) if server.get('port')==self.port),None)

This comment has been minimized.

@takluyver

takluyver Apr 11, 2017
Member

Can this line be broken up a bit? We're not strict about any particular code style, but this isn't super readable.

This comment has been minimized.

@brookisme

brookisme Apr 11, 2017
Author Contributor

i pulled list_running_servers out of the list comprehension so its a little bit shorter but i'm not sure if you'd like more.

if ports:
print("There is currently no server running on port {}.".format(self.port))
print("Ports currently in use:")
for port in ports: print("\t* {}".format(port))

This comment has been minimized.

@takluyver

takluyver Apr 11, 2017
Member

This branch should have exit code 1 as well.

This comment has been minimized.

@brookisme

brookisme Apr 11, 2017
Author Contributor

fixed.

server=next((server for server in servers if server.get('port')==self.port),None)
if server: os.kill(server.get('pid'), signal.SIGTERM)
else:
ports=[s.get('port') for s in list_running_servers(self.runtime_dir)]

This comment has been minimized.

@takluyver

takluyver Apr 11, 2017
Member

You can now reuse the servers variable here.

This comment has been minimized.

@brookisme

brookisme Apr 11, 2017
Author Contributor

ha - yeah, that was the very first thing i did, back before my initial commit, but list_running_servers returns an iterator so it doesn't work...

In [1]: from notebook.notebookapp import *

In [2]: nbstop=NbserverStopApp()

In [3]: servers=list_running_servers(nbstop.runtime_dir)

In [4]: [s for s in servers]
Out[4]: 
[{u'base_url': u'/',
  u'hostname': u'localhost',
  u'notebook_dir': u'/Users/brook/code/jupyter/notebook',
  u'password': False,
  u'pid': 27105,
  u'port': 8888,
  u'secure': False,
  u'token': u'48019c94f11b76fa4690c1a7d431bf58e4b2fb2d0cd65ae5',
  u'url': u'http://localhost:8888/'},
 {u'base_url': u'/',
  u'hostname': u'localhost',
  u'notebook_dir': u'/Users/brook/code/jupyter/notebook',
  u'password': False,
  u'pid': 27213,
  u'port': 8889,
  u'secure': False,
  u'token': u'4c1588c1139d214b9d1eb432fd000270e2645a226633fde5',
  u'url': u'http://localhost:8889/'},
 {u'base_url': u'/',
  u'hostname': u'localhost',
  u'notebook_dir': u'/Users/brook/code/jupyter/notebook',
  u'password': False,
  u'pid': 27238,
  u'port': 8890,
  u'secure': False,
  u'token': u'db40ac85ddd5694cc4f67d9c4a18f4c066b63887f6d9fb9b',
  u'url': u'http://localhost:8890/'}]

In [5]: [s for s in servers]
Out[5]: []

This comment has been minimized.

@takluyver

takluyver Apr 11, 2017
Member

Aha, OK then. Thanks, merging :-)

@takluyver takluyver merged commit d00b7e3 into jupyter:master Apr 11, 2017
4 checks passed
4 checks passed
codecov/patch 31.57% of diff hit (target 0%)
Details
codecov/project 77.97% (-0.13%) compared to b140790
Details
continuous-integration/appveyor/pr AppVeyor build succeeded
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
@gnestor gnestor mentioned this pull request Aug 3, 2017
@isabeaups
Copy link

@isabeaups isabeaups commented Sep 21, 2017

starting from which version of jupyter is this feature available?
When I try to use it I get the error

NotebookApp] No such file or directory: /Users/default/Workspace/project/stop

@takluyver
Copy link
Member

@takluyver takluyver commented Sep 25, 2017

It should be available from notebook 5.1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet

5 participants
You can’t perform that action at this time.