前言
这已经是 这个系列 的第十篇了,我们将前文要用到的从Github下载的各个软件包,实现更容易的更新和安装。
脚本
我默认你已经按照 前文(二) 安装好各种必要的软件包了。新建 /usr/local/bin/update-pkgs.sh
内容如下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
|
#!/usr/bin/env bash
pkgs=(
adguardhome
cidr_merger
clash
mosdns
nali
subconverter
trzsz
unblocknem
)
declare -A adguardhome
adguardhome[cmd]='adguardhome'
adguardhome[reponame]='AdguardTeam/AdGuardHome'
adguardhome[dlname]='AdGuardHome_linux_amd64.tar.gz'
adguardhome[decomp]='tar --no-same-owner -xf "$dlname" --strip-components 2 --directory=.'
adguardhome[install]='install -ps AdGuardHome /usr/local/bin/${cmd}'
adguardhome[install_post]='systemctl restart ${cmd}.service'
adguardhome[local_ver]='${cmd} --version 2>/dev/null | grep -oP "(\d+\.){2}\d+"'
declare -A cidr_merger
cidr_merger[cmd]='cidr-merger'
cidr_merger[reponame]='zhanhb/${cmd}'
cidr_merger[dlname]='${cmd}-linux-amd64'
cidr_merger[install]='install -ps "${dlname}" /usr/local/bin/${cmd}'
cidr_merger[local_ver]='${cmd} -v |& grep -oP "(\d+\.){2}\d+"'
declare -A clash
clash[cmd]='clash'
clash[reponame]='MetaCubeX/mihomo'
clash[dlname]='mihomo-linux-amd64-v${remote_ver}.gz' # 这一行默认下载的是 AMD64 v3 架构的包,如若不支持,可以下载名称中带 cgo 或者 compatible 的,说明:https://github.com/MetaCubeX/Clash.Meta/wiki/FAQ
clash[decomp]='gzip -d $dlname'
clash[install]='install -ps mihomo-linux-amd64-v${remote_ver} /usr/local/bin/${cmd}'
clash[install_post]='systemctl restart ${cmd}.service'
clash[local_ver]='${cmd} -v 2>/dev/null | grep -oP "(\d+\.){2}\d+" | head -1'
declare -A mosdns
mosdns[cmd]='mosdns'
mosdns[reponame]='IrineSistiana/$cmd'
mosdns[dlname]='${cmd}-linux-amd64.zip'
mosdns[decomp]='unzip -oqq $dlname -d .'
mosdns[install]='install -ps ${cmd} /usr/local/bin/${cmd}'
mosdns[install_post]='systemctl restart ${cmd}.service'
mosdns[local_ver]='${cmd} version 2>/dev/null | grep -oP "(\d+\.){2}\d+"'
declare -A nali
nali[cmd]='nali'
nali[reponame]='zu1k/${cmd}'
nali[dlname]='${cmd}-linux-amd64-v${remote_ver}.gz'
nali[decomp]='gzip -d $dlname'
nali[install]='install -ps ${cmd}-linux-amd64-v${remote_ver} /usr/local/bin/${cmd}'
nali[local_ver]='${cmd} -v 2>/dev/null | grep -oP "(\d+\.){2}\d+"'
declare -A subconverter
subconverter[cmd]='subconverter'
subconverter[reponame]='tindy2013/${cmd}'
subconverter[dlname]='${cmd}_linux64.tar.gz'
subconverter[decomp]='tar --no-same-owner -xf "$dlname" --strip-components 1 --directory=.'
subconverter[install]='install -ps ${cmd} /usr/local/bin/${cmd}; rm -rf $cmd $dlname /var/lib/$cmd/*; cp -afr base config generate.ini gistconf.ini pref.* profiles rules snippets /var/lib/$cmd/'
subconverter[install_post]='systemctl restart ${cmd}.service'
subconverter[local_ver]='curl -sS http://127.0.0.1:25500/version 2>/dev/null | grep -oP "(\d+\.){2}\d+"'
declare -A trzsz
trzsz[cmd]='trzsz'
trzsz[reponame]='${cmd}/${cmd}-go'
trzsz[dlname]='${cmd}_${remote_ver}_linux_x86_64.tar.gz'
trzsz[decomp]='tar --no-same-owner -xf "$dlname" --strip-components 1 --directory=.'
trzsz[install]='install -ps trz /usr/local/bin/trz; install -ps tsz /usr/local/bin/tsz; install -ps $cmd /usr/local/bin/$cmd'
trzsz[local_ver]='${cmd} -v 2>/dev/null | grep -oP "(\d+\.){2}\d+"'
declare -A unblocknem
unblocknem[cmd]='unblocknem'
unblocknem[reponame]='UnblockNeteaseMusic/server'
unblocknem[dlname]='unblockneteasemusic-linux-x64'
unblocknem[install]='install -p $dlname /usr/local/bin/$cmd'
unblocknem[install_post]='systemctl restart ${cmd}.service'
unblocknem[local_ver]='${cmd} -v 2>/dev/null | grep -oP "(\d+\.){2}\d+"'
## 安装软件
update_pkgs() {
for pkg in ${pkgs[@]}; do
eval cmd=\${$pkg[cmd]}
eval reponame_ori=\${$pkg[reponame]}
eval reponame=$reponame_ori
eval dlname_ori=\${$pkg[dlname]}
eval dlurl_ori=\${$pkg[dlurl]}
eval decomp=\${$pkg[decomp]}
eval install=\${$pkg[install]}
eval install_post=\${$pkg[install_post]}
eval local_ver_ori=\${$pkg[local_ver]}
echo "======== 更新 $pkg ========"
workdir="/tmp/software/$pkg"
[[ ! -d "$workdir" ]] && mkdir -p "$workdir"
rm -rf "$workdir"/* &>/dev/null
cd "$workdir"
remote_ver=$(curl -sS https://api.github.com/repos/${reponame}/releases/latest 2>/dev/null | jq -r .tag_name | sed 's|v||' | grep -v "null")
local_ver=$(eval $local_ver_ori)
if [[ -n $remote_ver && $remote_ver != $local_ver ]]; then
eval dlname=$dlname_ori
eval dlurl=$dlurl_ori
if [[ -z $dlurl ]]; then
dlurl="https://github.com/${reponame}/releases/download/v${remote_ver}/${dlname}"
fi
if [[ -n $local_ver ]]; then
echo ">> 即将从 $local_ver 升级至 $remote_ver ..."
else
echo ">> 未检测到本地版本,即将安装 $remote_ver 版本..."
fi
echo ">> 开始下载:$dlurl ..."
echo ">> 临时保存至:$workdir/${dlname} ..."
echo -n ">> 下载进度:"
if wget -q --progress=bar:dot --show-progress -O "${dlname}" "$dlurl"; then
if [[ -n $decomp ]]; then
echo ">> 临时解压至:$workdir ..."
eval $decomp
fi
echo ">> 执行安装命令:$install ..."
if eval $install; then
if [[ -n $install_post ]]; then
echo ">> 执行安装后钩子:$install_post ..."
if ! eval $install_post; then
echo ">> 安装后钩子执行失败,请检查命令是否正确..."
fi
fi
else
echo ">> 安装失败,请检查命令是否正确..."
fi
else
echo ">> 下载失败:$dlurl"
fi
elif [[ -n $remote_ver && $remote_ver == $local_ver ]]; then
echo ">> 本地版本已经是最新版本 $remote_ver ,无需更新..."
else
echo ">> 未获取到最新版本,无法更新,请检查网络原因..."
fi
if [[ -n $(ls $workdir) ]]; then
echo ">> 删除临时文件:$workdir/* ..."
rm -rf "$workdir"/* &>/dev/null
fi
echo
done
}
## 中止时删除临时文件
finish() {
rm -rf /tmp/software &>/dev/null
}
## 执行主函数
main() {
trap finish EXIT
if [[ -n "$@" ]]; then
pkgs=( $@ )
fi
update_pkgs
}
main "$@"
|
为它增加可执行权限:
1
|
chmod +x /usr/local/bin/update-pkgs.sh
|
使用
1
2
|
update-pkgs.sh # 更新或安装 pkgs 数组中的全部软件包
update-pkgs.sh clash nali # 指定更新或安装所输入的软件包
|
建议还是不要将其加入定时任务来自动更新。
如果老是获取不到 Github 上的最新版本号,可以尝试将获取版本号那一行改成下面这样,其中的 $GITHUB_TOKEN
为你自己申请的 Github Token(官方说明)。
1
|
remote_ver=$(curl -H "Authorization: Bearer $GITHUB_TOKEN" -sS https://api.github.com/repos/${reponame}/releases/latest 2>/dev/null | jq -r .tag_name | sed 's|v||' | grep -v "null")
|
说明
- 全部的软件包需要定义在数组
pkgs
中,并以每个软件包定义一组数组。数组中的键名(不能使用 -
)依次含义为:
cmd
:如果后面的变量要用到,就需要定义,软件包的命令名。
reponame
:Github上的仓库名。
remote_ver
:这个键无需你来定义,而是由脚本根据 reponame
去获取的Github上的最新稳定版本号。
dlname
:要下载的软件包在Github上Release的名称,可引用前面的键。
dlurl
:如果不定义这个键,就采用 https://github.com/${reponame}/releases/download/v${remote_ver}/${dlname}
,如果定义了就用所定义的。可引用前面的键。
decomp
:如果下载的文件是压缩包,如何解压它,可以引用前面的变量,如不需要解压可不定义。可引用前面的键。
install
:如何安装软件包。可引用前面的键。
intall_post
:安装后如果需要重启什么服务,可以定义它如何重启。可不定义。可引用前面的键。
local_ver
:如何获取本地软件包的版本号。可引用前面的键。
-
数组中和键的值如果需要使用变量引用,如果最外层用单引号,在 $
前面无需转义,如果最外层用双引号,在 $
前面请添加 \
转义。
-
如果后面的引用了前面的,那么前面的必须定义。
-
其他Github上的软件包,你可以用同样的方式定义在脚本中,以实现自动安装或更新。
其他
比如我还用到另外一组软件包,就是这样子的,你可能注意到不同软件包定义的键不太一样。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
pkgs=(
act
aliyunpan
baidupcs
cidr_merger
ctop
gitea
influx_cli
nali
realtek_r8125_dkms
tokei
timemachine
trzsz
)
declare -A act
act[cmd]='act'
act[reponame]='nektos/${cmd}'
act[dlname]='${cmd}_Linux_x86_64.tar.gz'
act[decomp]='tar --no-same-owner -xf "$dlname" --directory=.'
act[install]='install -ps ${cmd} /usr/local/bin/${cmd}'
act[local_ver]='${cmd} --version 2>/dev/null | grep -oP "(\d+\.){2}\d+"'
declare -A aliyunpan
aliyunpan[cmd]='aliyunpan'
aliyunpan[reponame]='tickstep/${cmd}'
aliyunpan[dlname]='${cmd}-v${remote_ver}-linux-amd64.zip'
aliyunpan[decomp]='unzip -oqq ${dlname} -d .'
aliyunpan[install]='install -ps "${cmd}-v${remote_ver}-linux-amd64/${cmd}" /usr/local/bin/${cmd}'
aliyunpan[local_ver]='${cmd} -v 2>/dev/null | grep -oP "(\d+\.){2}\d+"'
declare -A baidupcs
baidupcs[cmd]='baidupcs'
baidupcs[reponame]='qjfoidnh/BaiduPCS-Go'
baidupcs[dlname]='BaiduPCS-Go-v${remote_ver}-linux-amd64.zip'
baidupcs[decomp]='unzip -oqq ${dlname} -d .'
baidupcs[install]='install -ps "${cmd}-v${remote_ver}-linux-amd64/BaiduPCS-Go" /usr/local/bin/${cmd}'
baidupcs[local_ver]='${cmd} -v 2>/dev/null | grep -oP "(\d+\.){2}\d+"'
declare -A cidr_merger
cidr_merger[cmd]='cidr-merger'
cidr_merger[reponame]='zhanhb/${cmd}'
cidr_merger[dlname]='${cmd}-linux-amd64'
cidr_merger[install]='install -ps "${dlname}" /usr/local/bin/${cmd}'
cidr_merger[local_ver]='${cmd} -v 2>&1 | grep -oP "(\d+\.){2}\d+"'
declare -A ctop
ctop[cmd]='ctop'
ctop[reponame]='bcicen/${cmd}'
ctop[dlname]='${cmd}-${remote_ver}-linux-amd64'
ctop[install]='install -ps "${dlname}" /usr/local/bin/${cmd}'
ctop[local_ver]='${cmd} -v 2>/dev/null | grep -oP "(\d+\.){2}\d+" | head -1'
declare -A evsieve
evsieve[cmd]='evsieve'
evsieve[reponame]='KarsMulder/${cmd}'
evsieve[dlname]='${cmd}'
evsieve[dlurl]='https://raw.githubusercontent.com/devome/files/master/${cmd}/${cmd}'
evsieve[install]='install -ps "${dlname}" /usr/local/bin/${cmd}'
evsieve[install_post]='systemctl restart ${cmd}.service'
evsieve[local_ver]='${cmd} --version 2>/dev/null | grep -oP "(\d+\.){2}\d+"'
declare -A gitea
gitea[cmd]='gitea'
gitea[reponame]='go-${cmd}/${cmd}'
gitea[dlname]='${cmd}-${remote_ver}-linux-amd64'
gitea[install]='install -ps ${cmd}-${remote_ver}-linux-amd64 /usr/local/bin/${cmd}'
gitea[install_post]='systemctl restart ${cmd}.service'
gitea[local_ver]='${cmd} -v 2>/dev/null | grep -oP "(\d+\.){2}\d+" | head -1'
declare -A influx_cli
influx_cli[reponame]='influxdata/influx-cli'
influx_cli[dlname]='influxdb2-client-${remote_ver}-amd64.deb'
influx_cli[dlurl]='https://dl.influxdata.com/influxdb/releases/${dlname}'
influx_cli[install]='dpkg -i "${dlname}"'
influx_cli[local_ver]='LC_ALL=C apt list --installed 2>/dev/null | grep -P "influxdb2-cli/.+installed,local" | grep -oP "(\d+\.){2}\d+"'
declare -A nali
nali[cmd]='nali'
nali[reponame]='zu1k/${cmd}'
nali[dlname]='${cmd}-linux-amd64-v${remote_ver}.gz'
nali[decomp]='gzip -d $dlname'
nali[install]='install -ps ${cmd}-linux-amd64-v${remote_ver} /usr/local/bin/${cmd}'
nali[local_ver]='${cmd} -v | grep -oP "(\d+\.){2}\d+"'
declare -A realtek_r8125_dkms
realtek_r8125_dkms[reponame]='devome/realtek-r8125-dkms'
realtek_r8125_dkms[dlname]='realtek-r8125-dkms_${remote_ver}_amd64.deb'
realtek_r8125_dkms[install]='dpkg -i "${dlname}"'
realtek_r8125_dkms[local_ver]="LC_ALL=C apt list --installed 2>/dev/null | grep -P 'realtek-r8125-dkms/.+installed,local' | awk '{print \$2}'"
declare -A tokei
tokei[cmd]='tokei'
tokei[reponame]='XAMPPRocky/${cmd}'
tokei[dlname]='${cmd}-x86_64-unknown-linux-gnu.tar.gz'
tokei[decomp]='tar --no-same-owner -xf "$dlname" --directory=.'
tokei[install]='install -ps ${cmd} /usr/local/bin/${cmd}'
tokei[local_ver]="\${cmd} -V 2>/dev/null | awk '{print \$2}'"
declare -A timemachine
timemachine[cmd]='timemachine'
timemachine[reponame]='cytopia/linux-${cmd}'
timemachine[dlname]='v${remote_ver}.tar.gz'
timemachine[dlurl]='https://github.com/${reponame}/archive/refs/tags/${dlname}'
timemachine[decomp]='tar --no-same-owner -xf "$dlname" --strip-components 1 --directory=.'
timemachine[install]='make install'
timemachine[local_ver]='${cmd} -V 2>/dev/null | grep -oP "(\d+\.){2}\d+"'
declare -A trzsz
trzsz[cmd]='trzsz'
trzsz[reponame]='${cmd}/${cmd}-go'
trzsz[dlname]='${cmd}_${remote_ver}_linux_x86_64.tar.gz'
trzsz[decomp]='tar --no-same-owner -xf "$dlname" --strip-components 1 --directory=.'
trzsz[install]='install -ps trz /usr/local/bin/trz; install tsz -ps /usr/local/bin/tsz; install -ps $cmd /usr/local/bin/$cmd'
trzsz[local_ver]='${cmd} -v 2>/dev/null | grep -oP "(\d+\.){2}\d+"'
|
系列