跟我用路由器学Linux编程实例
本专栏文章以梅林、openwrt等linux路由为基础硬件,和笔者一起学习使用shell语言。带你从编写简单的插件开始,学习怎么折腾路由器,顺便学会编程。软路由用的都是Linux基础系统,学会了在路由上编程,自然也就学会了在Linux上编程。本专栏以shell语言为主,在实例中也可能用到其它编程语言。
文章目的是让略有计算机操作基础的人能看明白代码的主要逻辑,进而可以自己动手对路由的各种插件进行适当地理解和修改,或者自己写一些不太复杂的代码实现某些简单的功能。本系列文章定位于对折腾路由和编程有兴趣,又不想花大量时间去系统学习的懒人。当然也会有很多软路由的实用干货以供参考,也算是寓教于乐~ 最终让读者对编程和网络运维有一定了解,并运用与生产生活中。
本专栏不会有大量的命令参数让人看得眼花缭乱,大多命令只讲最常用和简单的参数。
用折腾路由的兴趣,顺便入门shell编程。
第一章 简单编程实现花生壳的ddns功能
文章目录
- 跟我用路由器学Linux编程实例
-
- [第一章 简单编程实现花生壳的ddns功能](#第一章 简单编程实现花生壳的ddns功能)
- 前言
- 一、ddns
- 二、最简单的ddns
- 三、理解一下ddns工作原理
- 四、写成正经的脚本
- 小结
前言
路由刷完固件正常工作后,第一件事就是想远程控制它吧?所以咱就直接从写ddns脚本开始,不用怕,一个简单的ddns脚本没几句代码的。最简单的甚至只要一句代码就行了。
一、ddns
dns(域名解析)简单来说就是把你的ip地址告诉服务器,再给那一串ip地址起一个好听的名字,如:baidu.com,以后你不在家就可以用这个好听的名字在互联网上找到你的路由器。
因为现在家用宽带的ip地址都是不固定的,所以就会在ip变化的时候要告诉服务器你的ip地址,这就叫ddns了。第一个d是动态的意思的,后面的dns就是域名解析的意思。
二、最简单的ddns
以常见的花生壳的ddns为例子,来个最简单的写法,真的只要一句代码哦:
shell
curl -s "http://用户名:密码@ddns.oray.com/ph/update?hostname=域名"
很多子域名(也叫二级域名,花生壳称之壳域名,相应的baidu.com这是顶级域名,www.baidu.com也是二级域名)ddns都有这种写法,去相应的官网看一看就知道了,比如freedns、dynv6等等,最多把用户名密码换成token。
是不是很简单?只要你把用户名、密码、域名用你自己的填进去。就可以立刻更新你的域名ip。
我们来看这一句代码:
先不管curl -s
,这看上去是不是和一个网址很像,除去:用户名:密码@ 这部分,它就是一个正常的网址。当然了,有 用户名:密码@ 它也是一个正常网址,不常见而已。不用说这是把用户名密码一次性搞定的写法,不用去单独登陆了。
你不禁要冒出三个?号,ip呢?作者你不是说ddns就是告诉服务器自己的ip的吗?你告诉服务器的ip被作者你吃了吗?其实很多ddns服务器支持这种写法,这是服务器自动得到你访问的ip。也就是说服务器是知道你从哪个ip访问的,那么它就自动给你设置了。省得你折腾!
这种办法肯定是不怎么高明的,某些出国留学的软件一开,你的ip就连你自己都很难搞明白,更别说机器了。出错那是很大机率的事!
先不管好坏,总之是实现了。那么再来看看前几个字符:
shell
curl -s
curl是一个linux命令,大多路由固件内置的有。你可以把它理解成浏览器,就是没有界面给你看而已,除了不能渲染页面,浏览器能干的事它都基本上能干。它有很多参数,咱不管那些奇奇怪怪的参数,只看这里所用到的-s
:
-s
在这里是可以省的,你可以试试,理论上没有-s
的话,运行时会出现进度条啊,一些消息什么的。这个-s
也可以写成--silent
这就比较好理解了,安静的意思嘛~
三、理解一下ddns工作原理
再理解一下上述那一句ddns代码,逻辑就是,我们用命令形式的浏览器curl
给服务器发了一个请求,服务器先验证我们的登陆信息,如果正确,就根据我们发出请求的ip地址,查询一下我们的域名ip是不是和请求发出地址一致,如果是一致的就告诉我们nochg
(no change:没有改变的意思),如果不一致就替我们改了,再回一个消息good
。
还有一种情况,如果出错了怎么办?前面说过 这句代码除去curl -s
就是一个浏览器地址,那么如果我们用浏览器输入这个地址会怎么样?服务器会回你一个badauth
这就是告诉你登陆出错。
那么有没有一种用浏览器来更新ddns的写法呢?也是有的,大多数ddns应该会设计成如下写法:
shell
http://ddns.oray.com/ph/update?hostname=域名&username=用户名&pass=密码
这句代码把用户名和密码写到域名后面了,并且用&
连接起来,在大多编程语言中,&
都表示和的意思。
实际测试免费花生壳不能这样写,应该也是可以的,但好像只给付费用户用,花生壳服务器返回的是!donator
。一般!
在各编程语言里都是否定的意思,这个返回我猜测是:"你不是付费用户"
好了,咱接着说命令。那么如果一个路由器不带curl
命令怎么办?别慌,咱还有个wget
可以用:上句代码也可以改写:
shell
wget "http://用户名:密码@ddns.oray.com/ph/update?hostname=域名"
这种写法就返回一大堆信息,我们来看看:
shell
admin@RT-AC3100-88B0:/tmp/home/root# wget "http://$username:$pass@ddns.oray.com/ph/update?hostname=$hostname"
--2023-12-31 15:17:36-- http://用户:*密码*@ddns.oray.com/ph/update?hostname=域名
Resolving ddns.oray.com... 114.215.199.192, 114.215.189.130
Connecting to ddns.oray.com|114.215.199.192|:80... connected.
HTTP request sent, awaiting response... 401 Unauthorized
Authentication selected: Basic base-64-authorization realm="DDNS"
Reusing existing connection to ddns.oray.com:80.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/html]
Saving to: 'update?hostname=域名'
update?hostname=域名 [ <=> ] 20 --.-KB/s in 0s
2023-12-31 15:17:37 (689 KB/s) - 'update hostname=域名' saved [20]
要想独立完成一个ddns客户端,那么这些基础网络知识是必须的,所以这里简单解释一下返回代码:
Resolving ddns.oray.com...
这一句是解析ddns.oray.com域名的ip地址Connecting to ddns.oray.com
这是连接到服务器,正在连接401 Unauthorized
是没有验证登陆的意思 在网络错误中,400系列错误都是用户的问题,500是服务器问题Authentication selected
这里就是验证方式了,base-64是一种编码规则。Reusing existing connection
过了验证后,继续连接200 OK
就是表示连接成功了,200系列都是正常的返回代码。- 再之后就是进度条和返回成功消息了
理解这个过程对我们写ddns代码是很重要的。不理解就只能照抄了,明白了这个过程我们才能有目的去调试代码,而不是靠瞎猜。虽然有经验的码农经常猜中~
好了,这里是用 wget
写了一句代码来实现前面 curl
的功能,那么wget
有没有安静模式呢,我们可以用帮助看一下
shell
wget -h
找一找,就会发现以下一行,这和curl
的-s
几乎一样嘛,就是换了一个英语单词而已。
shell
-q, --quiet quiet (no output)
因为两者的某些功能是差不多的,但 curl
强于 http 和 https 请求方面,所以本文主要使用 curl
。而 wget
支持 ftp 且在下载文件方面非常好用,所以大家看到的用命令下载文件,基本上写成 wget
。
四、写成正经的脚本
作者你一篇文章都快写完了,还让我在命令行里打字来更新ddns,是不是太不负责了?
好吧,下面我们就把这一句代码给搞成能工作的脚本,先上代码:
shell
#!/bin/sh
curl -s "http://用户名:密码@ddns.oray.com/ph/update?hostname=域名"
对的!还就是这一句代码,只是在前面加了这一句 #!/bin/sh
,这一句的意思是告诉系统:我这代码是要用sh解释器来执行的。解释器有很多种,路由基本上都是sh
,linux系统就五花八门了,常见的是bash
、sh
、ash
、csh
、tcsh
等等, Mac OSX现在基本上是zsh
,实际区别并不大,基本上都是命令参数有些区别。对路由来说这是套路写法,只要是路由的shell代码,就少不了这一句。
把它保存成文件,可以叫phddns或phddns.sh,对于linux来说有没有后缀(.sh)是没有区别的,就看你自己喜欢了。linux只管读文件,看文件有没有执行权限,不管你起的什么后缀。
既然都在学习编程了,总不能还用winscp这种软件来传输文件,那也太low了,对于win10以上的系统来说,powershell是自带ssh工具的。所以你只要打开powershell工具,这里默认你的路由已开启ssh功能,输入:
shell
# 命令行传输文件:
scp ./phddns user@192.168.50.1:/jffs/scripts/
user是路由用户名,192.168.50.1是路由的ip,./phddns是要上传的文件路径,/jffs/scripts/是上传后文件的路径,不指定上传后的文件名,默认会使用原文件名,回车后按要求输入路由密码。
这里不详细解释路径的概念,这个太基础了。./
是表示本目录下,windows也是一样的。不过windows的斜杠可能是反的\
。
上传文件以后,我们可以去用ssh去路由器看看,给予执行权限
shell
# user是路由用户名,192.168.50.1是路由的ip
ssh user@192.168.50.1
前提是你在系统设置里打开ssh功能。梅林在:系统管理-->系统设置-->Enable SSH
如果是第一次连接还会问你是否同意连接,打个yes就行。然后会要求你输入密码,输入正确后就和路由建立连接了。嗯就是这个命令行界面改了个提示符而已哦,看上去很高大上嘛,一看就是程序员应该用的~
如笔者这里提示符是这样变化的:
shell
mac@macdeAir
# 输入 ssh admin@192.168.2.1 并登陆成功后
admin@RT-AC3100-88B0:/tmp/home/root
表示由本机:macdeAir用户:mac ,切换到了路由机器:RT-AC3100-88B0,用户:admin, 后面在此提示符下的操作就是对路由起作用了
注:scp
命令可以上传文件自然也可以下载,把两个路径对调就行了,且 scp
和 ssh
是同样的要打开ssh功能,同样用默认的22端口,这两个命令是双生的,s是流的意思,后面cp是拷贝,sh就是shell了。
shell
# 这里是以梅林固件的路径为例,openwrt直接放到init.d下开机会自动执行
# pandvan这种的到/opt/目录下找个地方放,linux文件存放位置是有讲究的
chmod +x /jffs/scripts/phddns
这里chmod
是改变文件权限的命令,ch表示change(改变),mod表示model(模式),合起来就是改变模式,+x
表示增加执行权限,linux把文件权限分成三种,w、r、x,分别表示write(写)、read(读)、execute(执行),文件夹也一样的,执行权限对于文件夹来说就是可以打开。当然linux还有用户和组的概念,在路由器不太能用到,这里略过,所以对某一个文件用chmod
用上+/- w、r、x
就可以得到你想要的结果。Linux还有另一套用数字表示权限的方法也很常见:
shell
chmod 755 /jffs/scripts/phddns
这种表示法:w是4,r是2,x是1,加起来正好是7。
- 第一个7是文件的所有者的权限,表示具有全部读写执行的权限,
- 第二个5是与文件所有者在同一个组的用户的权限,有读和执行
- 第三个5是普通用户的权限
上面的+x
写法是给所有用户增加了执行权限,当然也可以写成u+x
表示只给普通用户加上执行权限。路由上基本用不上,不详细解释。
对于Linux来说,一个文件没有执行权限是不能当作程序来运行的,在这里我们的代码是要运行的,所以必须加上x权限。没有x权限就是一个普通文本文件,这和windows中用后缀来区分文件类型是不同的。
小结
本章详细讲解了一个最简单的ddns脚本是怎么炼成的,并且讲了如何用scp
命令上传文件、用 ssh
命令连接路由器、以及 chmod
的简单用法,这些都是非常基础的知识,也非常容易学会,无需理会 curl
和 wget
那复杂无比的参数,用到的时候再去查嘛~ 我觉得作者有时候都不一定能记住这么多参数~
这一章太长了,下一章再来学习如何让我们写的脚本自动工作,以及如何改进它~