(这是一份面向零基础读者的教程)
在前面的工作中,我们已经详细介绍了如何零起步安装Jupyter Notebook。具备了这样的基础,下面我们就来讨论一下,如何配置能够远程访问Jupyter Notebook服务器。
5.修改配置文件
5.1 配置文件所在路径
首先,我们需要修改一个名为“upyter_notebook_config.py”的文件,从其命名规则可以看出,这是有关Notebook的配置文件。
其实,在本质上,它是一个由Python编写的脚本文档。
通常,这个文档位于我们的家目录(home directory)之下,不同的操作系统,它所处的位置稍有不同,大致如下:
• Windows: C:\Users\USERNAME\.jupyter\jupyter_notebook_config.py
• OS X: /Users/USERNAME/.jupyter/jupyter_notebook_config.py
• Linux: /home/USERNAME/.jupyter/jupyter_notebook_config.py
上面的「USERNAME」就是前面我们提到的诸如‘jpnb’这样的用户名,我们根据实际情况替换为实际路径即可。
如果你在上述路径下没有找到这个配置文件,那么就需要在终端运行如下命令:[jpnb@centos-7 ~]$jupyter notebook --generate-config
Writing default config to: /home/jpnb/.jupyter/jupyter_notebook_config.py
这个命令的功能,就是创建Jupyter文件夹和配置文件「jupyter_notebook_config.py」。
5.2 设置Jupyter远程访问密码
对于Jupyter服务器,有时候,我们并不想让非授权的用户访问我们的Jupyter文档,这时该怎么办呢?
(1)设置访问密码
最简单的办法,莫过于设置一个访问密码。
在notebook 5.0版本以后,我们可以通过在终端输入命令“jupyter notebook password”来生成一个访问密码:[jpnb@centos-7 ~]$ jupyter notebook password
Enter password: ****
Verify password: ****
[NotebookPasswordApp] Wrote hashed password to /home/jpnb/.jupyter/jupyter_notebook_config.json
下面我们还需要手动生成一个hash密码。
可能你会问,为什么前面我们生成了一个Jupyter密码,这里还需生成一个hash密码呢?
原因很简单,如果你没有生成这么一个hash密码的话,那么每次通过浏览器远程访问Jupyter时,你都需要输入一次密码,这很繁琐!
但如果我们启用了这个hash密码,只需要首次远程访问Jupyter文档时,输入一次密码,在下次访问时,这个hash密码就好比一个钥匙(token),替我们打开密码之门,也就是免密码登录。
为了生成这个hash密码,我们需要在终端输入“ipython”(全部小写)命令,以进入IPython的交互shell。
然后在IPython中,依次输入如下代码:
In [1]: from notebook.auth import passwd
In [2]: passwd()
Enter password:
Verify password:
Out[2]: 'sha1:67c9e60bb8b6:9ffede0825894254b2e042ea597d771089e11aed'
这个在Out[2]显示的长长的hash密码,在后面大有用途,所以我们需要提前复制这个哈希字符串。
然后输入exit()命令, 退出IPython。
(2)将hash密码添加到配置文件中
下面,我们把前面生成的hash密码,添加到前面生成的配置文件:jupyter_notebook_config.py,
如前所述,这个文件就在我们家目录~/.jupyter中。通过vim打开这个文件:vim ~/.jupyter/jupyter_notebook_config.py
(Windows用户可以用诸如Notepad++等可视化效果更好的编辑器打开这个文件)。
在270行左右,找到c.NotebookApp.password 所在行,将如下代码:
#c.NotebookApp.password = ' '
前面的注释符号“#”去掉,然后将“=”右边的赋值,由空字符串’’,修改为前面生成的hash密码(注意,每个用户每次重新生成的hash值都是不同的):c.NotebookApp.password = u'sha1:67c9e60bb8b6:9ffede0825894254b2e042ea597d771089e11aed'
这里,特别需要注意的是,hash密码字符串前面的那个u不可省略。
这里我们简单介绍一下,Python字符串前常添加的三类辅助解析提示符号的含义,它们都不属于字符串的一部分,而是提示Python编译器,要按照给定的方式来解析引号中的字符串:
1)字符串前加 u
表示后面字符串以 Unicode 格式进行编码(这是Python 3的默认编码方式),防止因为字符串存储格式不同而导致解析出错。
特别是跨语系编号,如果不使用统一的编码方式,在一方界面显示正常的字符,在另一方显示的则可能是乱码。
2)字符串前加r
表示后面的字符串是原生(raw)编码,不需要做任何转义。例如r"\n\n\n”,它表示一个包含3个反斜杠‘\’和3个‘n’组成的普通(长度为6)字符串,而如果字符串不加前面不添加解析引导字符‘r’,则表示3个换行符号(长度自然为3)。这种模式,常用于正则表达式,对应着re(正则表达式)模块。
3)字符串前加 b
b" "前缀表示:后面字符串是bytes(字节)类型,即一个字符就是一个字节,(这是Python 2的默认编码方式)。
例: response = b'
这种模式,有时还用在NumPy或TensorFlow字符数组的输出上。
(3)编辑配置文件
在jupyter_notebook_config.py 中,除了添加前面提及的hash密码之外,还要修改如下部分代码(如果这些代码前有注释符号‘#’,则首先将其删除,表示启用这些设置):
#将默认值False修改为True,表示允许外部访问,这个设置和下面IP设置,双重保障外部用户访问的可达性:c.NotebookApp.allow_remote_access = True
# 等号右边的‘localhost’(仅仅运行本地访问),修改为‘*’,表示允许所有IP皆可访问c.NotebookApp.ip='*'
# 禁止自动打开浏览器c.NotebookApp.open_browser = False
#设置一个固定的notebook服务会监听的IP端口(这里设置为9999),这个值可以任意,只要保证不和其他已经启用的端口号冲突即可。c.NotebookApp.port = 9999
做完上述配置之后,保存文件并退出。
但此时修改的配置并没有生效,我们还需要在终端输入“jupyter notebook”命令,这样确保Jupyter重新加载jupyter_notebook_config.py,进而使得新配置起效。
(4)放行Linux防火墙的端口
截止到第(3)步,Jupyter Notebook的设置已经接近尾声。
但工作还没有做完。虽然我们开启了访问的端口,但Jupyter Notebook毕竟仅是Linux的一个应用程序,仅仅是它许可开放某个端口,这还不够。
Linux还得有个“外交部”——防火墙,只有它许可开放,那才是真的开放。
因此,下面的工作就是设置防火墙的端口开放。倘若开放某个端口(如9999),使用如下命令jpnb@centos-7 .jupyter]$ sudo firewall-cmd --zone=public --add-port=9999/tcp --permanent
[sudo] jpnb 的密码:****
Success
如果我们开放的不是9999,则修改上述端口号即可。
同样,有了新设置,我们还需要重新启动防火墙,使之生效。使用下面的命令,即可达到重启防火墙的功效:[jpnb@centos-7 .jupyter]$ sudo systemctl restart firewalld
(5)网页访问远程Jupyter文档
“是骡子是马,拉出来溜溜”。
配置了半天,我们看看能不能访问远程的Jupyter文档呢。我们先通过“ifconfig”来查看一下本机IP,这个流程并不是必需的,它主要是要证明,下面Jupyter文档的访问不是本地完成的。
图6 显示本地IP
现在我们远程SSH登录Jupyter服务器(IP地址为192.168.31.176):YHMacBookPro:~ yhilly$ ssh jpnb@192.168.31.176
jpnb@192.168.31.176's password:
Last login: Thu May 2 14:20:19 2019 from 192.168.31.194
在登录之后,我们启动Jupyter服务器,并让这个服务器后台运行:[jpnb@centos-7 ~]$ nohup jupyter notebook &
[1] 18505
[jpnb@centos-7 ~]$ nohup: 忽略输入并把输出追加到"nohup.out"
这里简单解释一下nohup的含义,nohup就是不挂起的意思( no hang up)。该命令的一般形式为:nohup command &
使用&命令后,作业被提交到后台运行,当前控制台没有被占用,否则,一旦把当前终端关掉(退出帐户时),作业就会停止运行。
nohup命令可以在你退出帐户之后继续运行相应的进程。
然后,我们在地址栏中输入远程服务器的IP和端口号:“http://192.168.31.176:9999/”,如图7所示图7 输入远程Jupyter服务器密码
Jupyter会提示我们输入先前设置的密码。一旦输入密码后,就可以在浏览器上看到运行的Jupyter文档,如图8所示。图8 访问并运行远程Jupyter文档
6.小结
终于,从零开始,经过一番折腾,我们能远程访问Jupyter服务器了。从效果上看,它和本地访问Jupyter没有什么差别,但是它“自有妙用”,即它能达到共享计算能力和共享编程环境的功效。
比如说,你租用了一台具备GPU云服务器,其价格不菲。于是,你想让一帮人(如你一个班的学生/学员)都有机会使用一把GPU(哪怕是分时复用也好)。
再比如,如果你辛辛苦苦配置好一个编程环境,装了各类类库(如TensorFlow、Keras、Caffe),还搭配了数十G级别的训练集,别人如果也想折腾出同样的环境,估计也得大半天。如果一帮人都这么折腾,这多浪费啊!
这时,我们可以让所有人访问这么一个可以共享的服务器,只要大家读写的Jupyter文档不一样,基本可以达到共享环境的目的——各玩个程序,而彼此不受影响,多好!
如此看来,Jupyter服务器的搭建,还是值得学习一番的。
希望以上文档,能对你所有帮助。
本文部分节选自《深度学习之美:AI时代的数据处理与最佳实践》(张玉宏著,电子工业出版社,2018年7月出版)。更多理论推导及实战环节,请参阅该书。