树莓派接上键鼠和显示器就是一台普通的Linux的主机了,这样没什么好玩的。我的想法是只接网线和电源,将它作为一台永久运行的个人服务器,随时随地可以远程登录它,在上面跑耗时的爬虫代码等任务。
除了一台装好Linux系统(Raspbian)的树莓派,一根路由器给的网线,合适的放置环境,我们还需要做软件方面的配置。主要是如何从外网ssh登录到树莓派,昨天晚上写了个脚本解决了这个问题,这里分享一下。
电信分给用户的IP是动态的,我使用的一般是2天变化一次,重启路由器的话立即改变。ssh需要的就是ip和用户名,所以只要解决了ip的问题,就可以做到随时登录了。
1.路由器静态分配内网IP
路由器在内网分配的ip也是动态的,以我的为例,是tplink的路由器,内网的ip两个小时换一次,电脑重启立即改变。
解决方案比较简单。
- 打开路由器的管理页面(通常是192.168.1.1,不同型号也可能不同)。
- 在DHCP服务中将地址池设置为192.168.1.100-200,这样动态分配的ip会在这个范围。
- 设置静态分配。添加一个静态分配的规则,添加树莓派的MAC地址和静态分配的IP(要在局域网的网段,通常是192.168.1.XXX,而且不要在Step2设置的地址池范围内),我使用的是192.168.1.20.
如果不知道自己的MAC地址,可以在打开DHCP服务的时候查看一下。或者在树莓派中用ifconfig
命令查看HWaddr
。
到此为止,任何时候只要你连接了这个路由器,就可以使用192.169.1.22登陆到树莓派系统了(通常情况下,路由器的设置都需要重启生效)。
2.外网IP和端口映射到内网
如果想要从外网登陆的话,还需要做一步映射。因为路由器分出了很多ip,如果外网访问某一端口的话,到底是访问了哪一个ip呢?
在路由器的「转发规则」页面添加一个对22端口(这个就是ssh端口)的转发,到192.168.1.20(你在上一节设置的IP)上。
设置成功,你可以在 http://www.ip138.com/ 查看一下自己当前的ip是多少,然后尝试使用这个ip ssh登陆,正常情况下,是可以登陆的。
3.解决外网IP变化的方法
外网的IP一旦改变,原来的你记住的ip就失效了,解决这个问题,我用的方案是:树莓派每一个小时检查自己的公网ip,如果改变,就向我的邮箱发送一封邮件报告自己的最新ip。
原理是使用Linux的crontab添加定时任务,任务就是一个脚本,这个脚本来做check ip和发送邮件的功能。
操作步骤:
- 在树莓派上登录Root账户(sudo -s),因为这个程序要放在/root/rootcrons下而且添加为root的例行程序。
- 执行
git clone https://github.com/laixintao/Report-IP-hourly.git /root/rootcrons/
下载脚本代码(如果放在别的目录下,要注意调整后面的步骤相应的路径)。 vi reportip.py
设置邮件信息,修改代码的e-mail config
部分:- smtpserver:你的SMTP服务器
- username:你登陆SMTP的用户名
- password:密码
- sender:发送人,注意要和SMTP登录的账户对应,通常都是一个一个邮箱账户。
- receiver:收信人列表
- subject:邮件主题
具体的修改信息,在代码中有详细的注释。
- 执行
crontab /root/rootcrons/rootcron
,将rootcroon的任务添加到crontab列表中。 - 重启crontab,使配置立即生效。
/etc/init.d/cron restart
这时整个定时检查ip并发送邮件的功能已经实现了,下一节是解释代码和更高级的配置,如果没有兴趣可以跳过,去读一下「特别注意」(我惨痛的教训)。
如何得到树莓派的内网ip?
开一个socket,然后用python直接获得此socket的名字。代码像这样:
123456 def get_lan_ip():s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)s.connect(("1.1.1.1",80))ipaddr=s.getsockname()[0]s.close()return ipaddr
3.5添加开机启动
通过使用了一段时候之后,我发现,如果ip变化了,而树莓派启动的时间不是在整点的话,你只能等到下一个整点才能收到邮件了。所以这里我们再加一步,将脚本添加至开机启动里面。
这一步很简单,只要 vim /etc/rc.local ,然后添加下面一句话就可以了。
1 2 |
# report ip to e-mail /usr/bin/python /root/rootcrons/reportip.py |
4.代码原理
最新版本的代码请看这里:https://github.com/laixintao/Report-IP-hourly
脚本会先检查网络是否连通,连通才会有后续的步骤。方法是访问百度是否正常返回结果(百度的主要功能是检查自己在不在线,不是搜索引擎)。
如果联通,则尝试获得公网ip,使用一个lastip.txt来保存ip地址,每次检查的结果和这个ip对比,如果相同,则不发送邮件。
那么如何获得公网ip呢?我的方法是去访问一个测试ip的网站,得到的html中用正则表达式去找ip。脚本中提供了三个网址,如果失败或者访问超时(默认20s),则尝试下一个。如果不能满足需要大家可以添加更多。
有朋友指出,我这里的地址已经失效了,并提供了下面两个可以获取ip的地址。
- http://www.ip138.com/ip2city.asp
- http://ipv4.icanhazip.com/
- https://httpbin.org/ip (这也比较稳定哦)
运行结果像下面这样:
详细的代码和注释请见github吧。
关于crontab
crontab filename
是将任务添加到定时计划中,如果有需要可以更改rootcron的配置来控制脚本的执行频率。rootcron中的代码像下面这样:
1 |
0 */1 * * * /usr/bin/python /root/rootcrons/reportip.py |
- 第1列分钟1~59
- 第2列小时1~23(0表示子夜)
- 第3列日1~31
- 第4列月1~12
- 第5列星期0~6(0表示星期天)
- 第6列要运行的命令
例如,数字表示第x分钟或者小时来执行,*表示每分钟/小时等执行。详细介绍见文末参考。
5.特别注意
- 树莓派放置环境,注意温度不能太高。
- 如果1 2小节设置完毕之后测试失败,试一下重启路由器,路由器的设置一般都是在重启之后生效的。不同的路由器相应地菜单和设置方法可能是不一样的,有一些甚至没有提供转发功能。
- 不要使用常用邮箱给树莓派做发送用,这样不安全,最好申请一个邮箱专门给树莓派发送报告用。
- 添加到crontab之前最好手动执行一下(
python reportip.py
)来看一下代码是否能够正常执行,可以的话再添加到crontab。 - 如果代码有授权失败异常(503),先不要怀疑是自己的配置出错了,去邮件提供商,看一下设置里面的「客户端SMTP」是否允许了(别问我怎么知道的,申请了三个邮箱才反应过来啊!)。
- 收信箱请设置一个规则,例如标题带[RPI]的放到[RPI]的放到一个RPI文件夹,不提示。这样自己就不会被打扰,邮件也不会被扔到垃圾箱了。
- 特别重要!crontab执行脚本的时候运行环境是和我们直接在shell执行不一样的!!!所以crontab文件中的命令全部写绝对路径,例如
/usr/bin/python /root/rootcrons/reportip.py
这样。脚本中所有用到的配置都要写绝对路径,例如file文件存放的目录(两个小时才找到这个bug啊衰!手动执行正常,crontab就是不正常!)。
6.推荐使用
- TP-link路由器:提供了映射服务,我的路由器支持花生壳动态解析,挺好用的。
- Secure Shell for Chrome:配色好看,而且使用这个,无论你用Windows,mac,linux还是什么系统,只要有Chrome,就可以随时登陆ssh。
- JuiceSSH for android:GooglePlay所有的ssh app我都用过,这个是最好的,相信我。
- what for ios?:我没有iPhone,iPhone用户自求多福吧 :)。
7.其他获得解决动态变化的IP的方案
这些方法我也考虑过,有兴趣的朋友可以实现以下:
- 发送邮件的方式改为用网页公开。写一个html网页,然后用ftp上传到自己的服务器,这样每次想要看最新的ip的话只要打开这个网页看一下就行了。缺点:总觉得树莓派不安全,放这里ftp密码有点不放心。
- 有一种叫做动态解析的东西。缺点:花钱。
8.树莓派做服务器的缺点
树莓派做到7×24运行,不知道靠不靠谱,我是个稳重的人,所以给树莓派贴了两片散热铜片还装了个风扇。只是…………这破烂玩意太吵了,这么点个风扇比机箱还吵。
安卓使用app无法ssh登陆,估计是22端口被屏蔽了,因为我用vpn访问是正常的。
9.参考资料
最后,如果你遇到了本文没有解决的问题,可以留言或电邮,会在6个小时之内得到回复。
点击图片可看大图。
Serverauditor for IOS;铜片够了;22端口是被屏蔽的。noip是有免费动态域名解析,但就是会时不时往你注册邮箱发个广告让你买服务。
牛,要是免费解析,就用个新邮箱注册好了,广告导师可以接受。
我去把风扇拆掉
写的棒
楼主的分享不错! https://account.daocloud.io/signup?invite_code=qscyw8lmeyhddm674ca3 这里有个免费送树莓派2的活动 特别适合楼主这样有博客的(送书送树莓派,但是要邀请用户)
很感谢你的教程!但是由于年代久远,reportip.py中获取IP地址的网站该更新啦,这两个都是可以用的“http://www.ip138.com/ip2city.asp”“http://ipv4.icanhazip.com/”
谢谢,已经更新到原文。
楼主,请教一下这是怎么回事
root@raspberrypi:~/rootcrons# python reportip.py
Network is Ready!
IP information from http://ipv4.icanhazip.com/
IP changed.
Traceback (most recent call last):
File “reportip.py”, line 108, in
sendEmail(ipaddr)
File “reportip.py”, line 39, in sendEmail
smtp.login(username, password)
File “/usr/lib/python2.7/smtplib.py”, line 622, in login
raise SMTPAuthenticationError(code, resp)
smtplib.SMTPAuthenticationError: (535, ‘5.7.8 authentication failed’)
你好,从traceback来看,ip获取正常,但是发送邮件的时候失败了,你应该检查一下你发送邮件的部分,比如邮箱的用户名密码,端口是否都设置正确了。
如果使用的是163的邮箱,要注意163邮箱的密码不是你的登录密码,而是另一个特定的用于客户端登录的密码。
在sendEmail的函数里,msgRoot.attach后面加上
smtp = smtplib.SMTP()
smtp.connect(smtpserver,587) #587是gmail的smtp的端口。
smtp.ehlo()
smtp.starttls()
smtp.ehlo()
你好,我用的你的github里的代码,很好用,但是有一个问题
我的ip自始至终没有变化,但是这段代码却一直在向我发邮件
我把crontab里面的时间代码改成每5分钟检查一次的,却几乎每五分钟就发一次邮件了。
reportip.py里面我把第一个没法用的网址
http://1111.ip138.com/ic.asp
改成了:
http://members.3322.org/dyndns/getip
邮箱设置我可以确定没问题。
hi,我尝试了几次代码,发现ip不变的时候是不会发送邮件的,所以我怀疑你的ip一直在变化。不知道发送到你的邮件的ip是否都是一样的?
你可以在树莓派上clone下来这个代码,然后重复执行几次试一下(
python reportip.py
),如果发现每次执行ip都变了,说明代码部分没问题,要么是你使用的监测ip的网址不准,要么的确是你的ip变化频率很高。就是因为发送过来的邮件都显示一样的ip,所以我需要反馈这个问题啊。
发过来的邮件都是给出这个地址114.232.21.44
然后我检查了lastip.txt,里面是两个ip地址,一个就是上面一个,另一个是我所在的内网地址10.0.0.6
直接python运行提示是
network is ready
ip information from http://members.3322.org/dydns/getip
ip changed
successfully sent the e-mail
很奇怪ip明明没变哪来的ip changed.
我用的是江苏电信,路由器是网件的,和这些有没有关系?因为有时候我打开邮件发来的ip会变成路由器的界面?
应该没有关系,邮件内容应该是纯文本,不应该有别的内容啊。
你可以手动执行脚本看下输出吗? (执行python reportip.py)
哦对不起,我没看到这条评论。我跑了几次不会这样,我把源代码改成你这个ip试一下吧
手动执行,提示这个
network is ready
ip information from http://members.3322.org/dydns/getip
ip changed
successfully sent the e-mail
这说明ip变了啊,你再运行几次,每一次都会变吗?
另外他说
successfully sent the e-mail
,你应该会收到邮件的,你看下邮件内容里面的ip变了吗?反复运行多少次,都提示ip changed,邮件已经几十封了,每封邮件的地址都一毛一样
我不会用命令行拷贝,scp命令不会用的。
lastip.txt文件存在的,没问题,里面有两个ip,一个公网的一个内网的,也没问题
会不会是文件编码的问题。你比较一下两次命令生成的文件是不是不一样。内容一样但是提示不一样的话很可能是文件写入的过程有问题
ip终于变了,还是反复发邮件
文件编码怎么看?不明白
放弃在树莓派上用这个了,内网还有路由器什么的麻烦死了,如果是在vps上用的话感觉会很方便。
还是感谢你的代码
嗯,没有ip没啥好的办法,可以试试内容穿透之类的。如果是vps的话就不用这个了…… vps的ip是固定的。
兄弟,我试了你的这个网址,也是 Ip not change啊,我录了一段实验过程你可以看看:https://asciinema.org/a/onknbfPeoIvUs7SEk9zbpH1N5,可能需要翻墙看。我怀疑是你的环境问题了…… 你检查一下lastip.txt文件的位置,是不是找不到这个文件来比较啊?
2017年11月19日亲测有效。电信宽带
查询IP地址的要换成文章中所说的两个地址
后来发现 https://httpbin.org/ip 也比较稳定
outlook 邮箱好像没办法配置呀?
pop
服务器名称: outlook.office365.com
端口: 995
加密方法: TLS
smtp
服务器名称: smtp.office365.com
端口: 587
加密方法: STARTTLS
应该可以的,你看加密方式Python客户端配置对了没有?
先本地用Python发一封邮件试试能不能成功。
楼主大大,这个脚本很棒,我成功使他寄信了,但是…不知是否能让其支援Python3?
我现在写的代码基本都是Python3,现在Python2真难写,我有空去兼容下吧,估计要改一下urllib和编码的问题。
啊,不用做兼容的,可以直接改写成Python3,因为Raspbian Stretch 是内置 Python3的,所以估计可以放弃掉Python2的代码
感谢楼主特地回覆,您的这个IP回报程序帮助我能够远端管理分散式资料库,希望您可以成功改写成Python3~
我觉得可能还有一些老的用户只能用 Python2 的,除了树莓派还有一些其他平台的用户(我也很震惊)。不过我稍微改了一下,在这个分支支持 Python3:https://github.com/laixintao/Report-IP-hourly/tree/python3 ,你看下能不能运行吧。
我測試後,得到這個錯誤訊息:
‘ascii’ codec can’t decode byte 0xe6 in position 23: ordinal not in range(128)
‘ascii’ codec can’t decode byte 0xa6 in position 340: ordinal not in range(128)
難道執行過程中出現了中文?
成功,我在腳本的開頭加上
import sys
reload(sys)
sys.setdefaultencoding(‘utf-8’)
抱歉,原本的運行是完全沒有問題的,是我自己忘記切換成python3模式,上面的那個錯誤是python2下出錯的
抱歉,原本的运行是完全没有问题的,是我自己忘记切换成python3模式,上面的那个错误是python2下出错的
問題都解決了~謝謝樓主
不過,我想請教一下,如果要在電腦上測試,要如何解決
“server_hostname cannot be an empty string or start with a leading dot.”的問題呢?
具体是哪一行的错误呢?看起来你用了一个错误的URL地址?
嗯….樓主,您使用電腦版的Python執行一下您的這個腳本,我想就會出現了。
请问获取ip后怎么连接啊,用xshell登陆时显示连接失败
请参考文中的端口转发,确定你可以在公网访问ssh的端口。
已将22端口映射至内网设备的ip,使用文中ip查询网页所得ip无法ssh端口
用ping netstat之类的工具一步一步查一下吧,应该是网络的问题。先把公网的访问搞通了再说。
请问为什么每次都是获取到内网ip,发邮件是内网ip,不是公网的
Network is Ready!
IP information from http://www.whereismyip.com/
Fail to get the Network ip.
Get the LAN ip.
192.168.2.3 192.168.2.3
IP changed. New ip: 192.168.2.3 192.168.2.3
看日志 IP 是从 http://www.whereismyip.com/ 这个网站拿到的,而这个网站已经挂了……
我明天改下代码吧。
我删掉这个网址还是只能获取内网ip,
ip.cn这个网址可以显示ip,能用吗
pi@raspberrypi:~ $ curl ip.cn
当前 IP:113.88.13 来自:广东省深圳市 电信
博主你好!我成功的测试了,但是我想在发送邮箱的时候,不想发送内网的ip,代码需要修改那一块?可以修改发送邮箱的的正文内容吗?想添加几个字进去!
可以的,邮件的内容就是这个字符串 https://github.com/laixintao/Report-IP-hourly/blob/master/reportip.py#L96
嗯,可以了,有什么办法可以让发送的邮件内容进行换行,因为发送的邮件内容公网ip和内网ip的字符间距挨得太密集了,看起来怪怪的,想分别换行显示公网和内网ip,但是我查了资料,网上说发送邮件的内容含有html格式的话,需要加\n\r,我加了,不起作用,想问问你什么有解决的办法吗?
这个… 慢慢测试吧,是在不行加几个空格或者字符吧。比如 内网ip: xxx 公网ip:xxx表示出来。