美文网首页
利用Linux Shell脚本实现SSR自动更换端口

利用Linux Shell脚本实现SSR自动更换端口

作者: 泅渡沙洲 | 来源:发表于2020-03-26 07:55 被阅读0次

利用Linux Shell脚本实现SSR自动更换端口——沙洲

最近不知道为什么突然查的特别严,可能是战疫期间境外反动势力异常猖獗,刚换完端口不到三天新端口又被封了。苦于手动换端口、换IP实在令人不胜厌烦,我突发奇想能不能使用传说中强大实用的bash脚本实现自动换端口呢,由于我在这方面完全是个一窍不通的小白,因此编写脚本期间很是吃了一番苦头,参考了很多很多前辈的文章,本文特此记录。

本文深受以下文章启发,可作为参考:

首先墙裂推荐==跑不了的你兄==的这篇文章,内容十分详细:
Linux下使用脚本读取参数修改配置文件 —— 跑不了的你
可惜文章内容实在比较深,小的理解起来比较困难,但是可以树立在这方面需用到的命令的一个较的全面认识。关于文章中用到但并未详细解释的opts,这篇文章有十分详细的叙述:
shell脚本中关于getopts的使用方法 —— 邻家大男孩
基础的Shell脚本格式与如何执行:
Linux就该这么学 —— 执行Shell脚本(多种方法)
学习如何用awk命令读取文件中的内容:
awk命令 —— DBA_zzher
Shell awk命令详解(格式+使用方法)
关于学习用复杂的sed命令来替换文件内容:
Linux命令行大全 —— sed命令
linux sed命令详解(推荐)
如何在脚本里实现算术:
详解Shell编程之变量数值计算(一)
如何截取部分字符串:
Linux-shell脚本字符串截取 —— linux运维菜

以及下面一些写得非常好,但是因为和实际情况暂不符所以暂未用上的文章,留作参考:
shell脚本读取ini配置文件的值 —— yuzaipiaofei
Linux Shell环境下用jq命令处理json文件 —— 东孤熊猫

查询IP或者端口是否被封

  • IP被封
    IP被封的情况比较好鉴别,直连ping一下服务器的ip看下是否有响应就行了。Ctrl+R打开运行,输入cmd,然后ping MY_IP。
  • 端口被封
    这里推荐一个网站,可以从全球不同地方的服务器ping访问指定的端口。对于位于境外的服务器来说,输入ip:端口号,如果国内ip访问显示是红色的,那么代表该端口就被封了。
    端口ping检查

从SSR配置文件中读取端口号

通常来说Linux下的配置文件为ini文件,因此可参考上述 yuzaipiaofei的文章进行编写。但是不巧我的配置文件是userconfig.json东孤熊猫的文章中描述的jq命令来读取json文件的值固然十分方便,但是十分不巧的是我的vps上的debian连apt-get都404,完全装不了jq。因此需要想办法手动从userconfig.json读取到当前的端口号是多少。


awk命令简介

这里我选择了使用awk命令。借花献佛简单记录下awkawk命令包含两部分,模式(pattern)与动作(action),其中动作又分为格式化输出和流程控制两类。
awk命令的格式:awk '条件1{动作1}条件2{动作2}条件3{动作3}...' 文件名

  1. 条件
    一般使用关系表达式作为条件,表示对于awk命令的执行条件进行限制。这些关系表达式非常多,具体参考表1。
条件类型 条件 说明
awk保留字 BEGIN 在 awk 程序一开始,尚未读取任何数据之前执行。BEGIN 后的动作只在程序开始时执行一次
awk保留字 END 在 awk 程序处理完所有数据,即将结束时执行。END 后的动作只在程序结束时执行一次
关系运算符 > 大于
关系运算符 < 小于
关系运算符 >= 大于等于
关系运算符 <= 小于等于
关系运算符 == 等于
关系运算符 != 不等于
关系运算符 A~B 判断字符串 A 中是否包含能匹配 B 表达式的子字符串
关系运算符 A!~B 判断字符串 A 中是否不包含能匹配 B 表达式的子字符串
正则表达式 /正则/ 如果在“//”中可以写入字符,则也可以支持正则表达式
  1. 动作
[root@localhost ~]# awk '{printf $2 "\t" $6 "\n"}' student.txt
#输出第二列和第六列的内容
Name Average
Liming 87.66
Sc 85.66
Gao 91.66

在这个例子中没有设定任何的条件类型,所以这个文件中的所有内容都符合条件,动作会无条件执行。动作是格式化输出 printf"$2""$6"分别代表第二个字段和第六个字段,所以这条 awk 命令会列出 student.txt 文件的第二个字段和第六个字段。
如果想让 awk 识别字符串,则必须使用"//"包含,例如:

[root@localhost ~]$ awk '/Liming/ {print}' student.txt
#打印Liming的成绩
1 Liming 82 95 86 87.66

然后基于这个原理我对ssr的配置文件userconfig.json文件进行截取。首选查看配置文件的具体格式root@vultr:~# vim /etc/shadowsocksr/userconfig.json,看见服务器端口是由server_port这个字段记录的:

{
    "server": "0.0.0.0",
    "server_ipv6": "::",
    "server_port": 8994, #ssr服务器端口
    "local_address": "127.0.0.1",
    "local_port": 1080,

    "password": "@********6", #ssr密码
    "method": "aes-256-cfb",
    "protocol": "auth_sha1_v4_compatible",
    "protocol_param": "",
    "obfs": "plain",
    "obfs_param": "",
    "speed_limit_per_con": 0,
    "speed_limit_per_user": 0,

    "additional_ports" : {},
    "timeout": 120,
    "udp_timeout": 60,
    "dns_ipv6": false,
    "connect_verbose_info": 0,
    "redirect": "",
    "fast_open": false
}

因为awk命令默认是用:进行字段分隔的,所以我们通过正则表达式的格式化输出条件,输出该行的第二个字段,命令如下:

awk '/"server_port"/{printf $2 "\n"}' /etc/shadowsocksr/user-config.json
执行结果: awk命令执行结果.png

这样子就得到了我们需要的旧端口号啦。

端口号进行自增运算

得到8994,后,我们需要用语法将逗号去掉,${var%,*}表示从右数起的第一个逗号,保留它之前的所有内容,然后我们就port=${var%,*}得到了port=8994。

然而此时有一个新的问题,我们截取出来的port现在是个字符串,而shell中是字符串数字是不能进行运算的。
在下对Shell脚本不甚了解,苦于没有像Java中Integer.parseInt(port)这种方便的语法,试验了很久查了很多资料,终于成功把它转变为了数字。其实说来非常简单,只要用$[]就行了,网上很多资料真是毁人不倦!
然后我们用$(( ))的命令表示其中的内容是进行数学运算,这样子就成功实现了端口号的自增:

newport=$[port]
newport=$(($newport + 1))

现在echo $newport输出就是数值的8994了!。

用新端口替换旧端口

既然得到了新的端口,接下来我们就用sed命令来替换旧端口,sed命令是一个面向字符流的非交互式编辑器。在seds表示替换、-i表示直接修改源文件。

说实话,sed真是太复杂晦涩了,也可能是在下没有找到好的参考资料,总之一直弄不对。搞了好久,一直在报ed: -e expression #1, char 35: unterminated `s' command的错误,迫于无奈,这里直接采用最简单的实现方式,今后再慢慢对其进行研究:

sed -i "s/$port/$newport/" /etc/shadowsocksr/user-config.json

这行命令表示用找到源文件中所有$port即8994的地方,一律替换成$newport的值8995。s/...表示采用替换命令,而-i表示将这种替换直接作用于源文件而不是在控制台打印。幸好user-config.json文件中只有一个字段是8994,否则这种实现方式后果不堪设想,整个文件所有的8994字段被修改,今后应用它必须慎之又慎!

验证脚本

综上,我们的bash文件如下:

#!/bin/bash
ssr_file=/etc/shadowsocksr/user-config.json
cp ${ssr_file} ${ssr_file}.bk
var=$(awk '/"server_port"/{printf $2 "\n"}' ${ssr_file})

echo "old port is ${var%,*}"
port=${var%,*}
newport=$[port]
newport=$(($newport + 1))

newport=$(echo $newport)

sed -i "s/$port/$newport/" ${ssr_file}
var=$(awk '/"server_port"/{printf $2 "\n"}' ${ssr_file})
echo "new port is ${var%,*}"
cat ${ssr_file}

结束编辑,运行bash。可以看见执行结果:


运行结果.png

到这里我们用shell脚本实现SSR自动换端口就结束了,如果您觉得本文对您有所帮助,请按个赞吧,谢谢 !: )

相关文章

网友评论

      本文标题:利用Linux Shell脚本实现SSR自动更换端口

      本文链接:https://www.haomeiwen.com/subject/tltvyhtx.html