当前位置:网站首页>shell 图形化跳板机
shell 图形化跳板机
2022-07-29 18:59:00 【51CTO】
whiptail
在CentOS6系统中,我们可以使用setup指令来修改网卡的IP等信息,交互起来十分方便 在CentOS7系统中,setup命令已经没有了,但是还有nmtui命令,可以让我们修改IP和主机名。
那么whiptail命令的作用,就是出现一个可以交互的图形化界面,并且样式有很多。
在之前的课程中,我们已经使用流程控制语句,满足了一个跳板机的需求,但是我们还想是想更多的功能,当然脚本也都能实现,但是我们想要更炫酷的,脱离死气沉沉的命令行。
那么我们就一起来看一下,whiptail可以实现哪些需求吧...
消息框

布尔值选择框

yes:0
no:1
## 布尔值选择框案例一:
whiptail --title "你确定要这么做吗?" --yesno "请做出你的选择YES or NO !" 10 60
if [ $? -eq 0 ];then
echo '选择的yes'
else
echo '选择的是no'
fi
## 布尔值选择框案例二:
whiptail --title "你确定要这么做吗?" --yes-button "运维" --no-button "开发" --yesno "请选择你在公司的岗位" 10 60
if [ $? -eq 0 ];then
echo '你的岗位是运维'
else
echo '你的岗位是开发'
fi
--titlle:标题
--yes-button:yes的按钮可以改名
--no-button:no的按钮可以改名
--yesno:布尔值框,后面可以加框内的内容
- 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.
交互式输入框
实践
whiptail
--title
"曾老湿跳板机-10.0.0.61"
--inputbox
"请输入一个文件名路径:"
10
60 /etc/passwd
3>&1
1>&2
2>&3
## 交互式输入框
source_file
=
`whiptail --title
"曾老湿跳板机-10.0.0.61"
--inputbox
"请输入源文件位置:"
10 60 3>&1 1>&2 2>&3`
if [
$?
-eq
0 ];then
dest_file
=
`whiptail --title
"曾老湿跳板机-10.0.0.61"
--inputbox
"请输入对端存放位置:"
10 60 /etc/passwd 3>&1 1>&2 2>&3`
if [
$?
-eq
0 ];then
scp
$source_file
172.16.1.7:
$dest_file &>/dev/null
else
echo
'请输入一个目标路径'
fi
else
echo
'请输入一个源文件路径'
fi
## 交互式输入框
source_file
=
`whiptail --title
"曾老湿跳板机-10.0.0.61"
--inputbox
"请输入源文件位置:"
10 60 3>&1 1>&2 2>&3`
whiptail
--title
"
$HOSTNAME
Disk Info"
--msgbox
"
$source_file
"
30
60
## 选项
--inputbox:交互式输入框
10
60 /etc/passwd
10:高度
60:宽度
/etc/passwd:默认值
## 返回值
选择OK:0
选择Cancel:1
命令本身带输入内容,输入内容可以保存在变量中
- 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.
密码输入框
PASSWD
=
`whiptail --title
"曾老湿跳板机-10.0.0.61"
--passwordbox
"请输入一个密码名路径:"
10 60 3>&1 1>&2 2>&3`
# 实战
## 密码输入框
PASSWD
=
`whiptail --title
"曾老湿跳板机-10.0.0.61"
--passwordbox
"请输入一个密码名路径:"
10 60 3>&1 1>&2 2>&3`
if [
$?
-eq
0 ];then
if [
${#PASSWD}
-ne
0 ];then
echo
"密码是:
$PASSWD
"
else
echo
"密码为空"
fi
else
echo
'选择了取消'
fi
# 返回值
选择OK:0
选择Cancel:1
命令本身带输入内容,输入内容可以保存在变量中
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
菜单栏
## 菜单栏
OPTION
=
$(whiptail --title
"曾老湿跳板机-10.0.0.61"
--menu
"根据菜单选吧老弟"
30 60 10 \
"1"
"lb01"
\
"2"
"lb02"
\
"3"
"web01"
\
"4"
"web02"
\
"5"
"web03"
3>&1 1>&2 2>&3)
--menu:菜单栏
30:高度
60:宽度
10:菜单显示几行内容
## 返回值
选择OK:0
选择Cancel:1
选择的值,会将序号保存在OPTION变量中
## 实战
## 菜单栏
OPTION
=
$(whiptail --title
"曾老湿跳板机-10.0.0.61"
--menu
"根据菜单选吧老弟"
30 60 10 \
"1"
"lb01"
\
"2"
"lb02"
\
"3"
"web01"
\
"4"
"web02"
\
"5"
"web03"
3>&1 1>&2 2>&3)
if [
$?
-eq
0 ];then
case
$OPTION
in
1)
echo
"连接 lb01"
;;
3)
ssh
172.16.1.7
;;
esac
else
echo
"选择了退出"
fi
- 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.
单选框
## 语法
DISTROS
=
$(whiptail --title
"曾老湿跳板机-10.0.0.61"
--radiolist
"请在下面内容选择一项,上下左右移动,空格选中"
20 60 10 \
"send"
"发送文件"
OFF \
"useradd"
"创建用户"
OFF \
"ssh"
"远程连接"
ON \
"mem"
"查看内存"
OFF 3>&1 1>&2 2>&3)
## 选项
--radiolist:单选框
OFF:默认没有被选中
ON:默认被选中
多选没有意义,后面的选项会覆盖前面的选项
## 返回值
选择OK:0
选择Cancel:1
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
多选框
# 语法:
DISTROS
=
$(whiptail --title
"曾老湿跳板机-10.0.0.61"
--checklist
"请在下面内容选择一项,上下左右移动,空格选中"
20 60 10 \
"send"
"发送文件"
ON \
"useradd"
"创建用户"
OFF \
"ssh"
"远程连接"
OFF \
"mem"
"查看内存"
OFF 3>&1 1>&2 2>&3)
## 多选框实战
send(){
echo 执行send函数
}
mem(){
echo 执行mem函数
}
DISTROS
=
$(whiptail --title
"曾老湿跳板机-10.0.0.61"
--checklist
"请在下面内容选择一项,上下左右移动,空格选中"
20 60 10 \
"send"
"发送文件"
ON \
"useradd"
"创建用户"
OFF \
"ssh"
"远程连接"
OFF \
"mem"
"查看内存"
OFF 3>&1 1>&2 2>&3)
echo
$?
echo
$DISTROS
for n
in
$DISTROS;do
${n//\"/
''
}
done
## 返回值:
选择OK:0
选择Cancel:1
- 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.
进度条
作业
#!/bin/bash
## 消息框
whiptail
--title
"
$HOSTNAME
跳板机"
--msgbox \
" 欢迎来到界面很low的跳板机"
15
60
connect(){
host
=
$1
ping
-c
1
-W
1
$host &>/dev/null
if [
$?
-eq
0 ];then
if [ !
-f ~/.ssh/id_rsa ];then
ssh-keygen
-t rsa
-P
''
-f ~/.ssh/id_rsa &>/dev/null
fi
check_key
=
`sshpass -p 1 ssh -o
'StrictHostKeyChecking no'
$host
'grep "m01" \
~/.ssh/authorized_keys 2>/dev/null |wc -l'
`
if [
$check_key
-eq
0 ];then
sshpass
-p
1 ssh-copy-id
-o
'StrictHostKeyChecking no'
-i ~/.ssh/id_rsa.pub \
$host &>/dev/null
fi
ssh
$host
fi
}
jdt(){
{
for ((i
=
0 ; i <
=
100 ; i
+
=
1));
do
usleep
3000
echo
$i
done
} | whiptail
--gauge
"等一下子,正在执行"
6
60
0
}
send1(){
scp
$source_file
172.16.1.5:
$dest_file &>/dev/null
jdt
}
send2(){
scp
$source_file
172.16.1.6:
$dest_file &>/dev/null
jdt
}
send3(){
scp
$source_file
172.16.1.7:
$dest_file &>/dev/null
jdt
}
send4(){
scp
$source_file
172.16.1.8:
$dest_file &>/dev/null
jdt
}
send5(){
scp
$source_file
172.16.1.9:
$dest_file &>/dev/null
jdt
}
df1(){
whiptail
--title
"lb01 Disk Info"
--msgbox
"`ssh 172.16.1.5 'df -h'`"
20
60
}
df2(){
whiptail
--title
"lb02 Disk Info"
--msgbox
"`ssh 172.16.1.6 'df -h'`"
20
60
}
df3(){
whiptail
--title
"web01 Disk Info"
--msgbox
"`ssh 172.16.1.7 'df -h'`"
20
60
}
df4(){
whiptail
--title
"web02 Disk Info"
--msgbox
"`ssh 172.16.1.8 'df -h'`"
20
60
}
df5(){
whiptail
--title
"web03 Disk Info"
--msgbox
"`ssh 172.16.1.9 'df -h'`"
20
60
}
fm1(){
whiptail
--title
"
$HOSTNAME
Disk Info"
--msgbox
"`ssh 172.16.1.5 'free -m'`"
20
90
}
fm2(){
whiptail
--title
"
$HOSTNAME
Disk Info"
--msgbox
"`ssh 172.16.1.6 'free -m'`"
20
90
}
fm3(){
whiptail
--title
"
$HOSTNAME
Disk Info"
--msgbox
"`ssh 172.16.1.7 'free -m'`"
20
90
}
fm4(){
whiptail
--title
"
$HOSTNAME
Disk Info"
--msgbox
"`ssh 172.16.1.8 'free -m'`"
20
90
}
fm5(){
whiptail
--title
"
$HOSTNAME
Disk Info"
--msgbox
"`ssh 172.16.1.9 'free -m'`"
20
90
}
gn1(){
ps
=
`ssh 172.16.1.5
'ps -ef|grep [n]ginx|wc -l'
`
if [
$ps
-eq
0 ];then
whiptail
--title
"lb01"
--msgbox
"nginx未存活"
20
60
else
whiptail
--title
"lb01"
--msgbox
"nginx存活 \
进程数=
$?
"
20
60
fi
}
gn2(){
ps
=
`ssh 172.16.1.6
'ps -ef|grep [n]ginx|wc -l'
`
if [
$ps
-eq
0 ];then
whiptail
--title
"lb02"
--msgbox
"nginx未存活"
20
60
else
whiptail
--title
"lb02"
--msgbox
"nginx存活 \
进程数=
$?
"
20
60
fi
}
gn3(){
ps
=
`ssh 172.16.1.7
'ps -ef|grep [n]ginx|wc -l'
`
if [
$ps
-eq
0 ];then
whiptail
--title
"web01"
--msgbox
"nginx未存活"
20
60
else
whiptail
--title
"web01"
--msgbox
"nginx存活 \
进程数=
$?
"
20
60
fi
}
gn4(){
ps
=
`ssh 172.16.1.8
'ps -ef|grep [n]ginx|wc -l'
`
if [
$ps
-eq
0 ];then
whiptail
--title
"web02"
--msgbox
"nginx未存活"
20
60
else
whiptail
--title
"web02"
--msgbox
"nginx存活 \
进程数=
$?
"
20
60
fi
}
gn5(){
ps
=
`ssh 172.16.1.9
'ps -ef|grep [n]ginx|wc -l'
`
if [
$ps
-eq
0 ];then
whiptail
--title
"web03"
--msgbox
"nginx未存活"
20
60
else
whiptail
--title
"web03"
--msgbox
"nginx存活 \
进程数=
$?
"
20
60
fi
}
ml1(){
whiptail
--title
"lb01"
--msgbox
"`
$ml
`"
20
60
}
ml2(){
whiptail
--title
"lb02"
--msgbox
"`
$ml
`"
20
60
}
ml3(){
whiptail
--title
"web01"
--msgbox
"`
$ml
`"
20
60
}
ml4(){
whiptail
--title
"web02"
--msgbox
"`
$ml
`"
20
60
}
ml5(){
whiptail
--title
"web03"
--msgbox
"`
$ml
`"
20
60
}
caidan(){
fuwu
=
$(whiptail --title
"跳板机-10.0.0.61"
--menu
"请根据菜单选机器"
25 60 11 \
"1"
"lb01"
\
"2"
"lb02"
\
"3"
"web01"
\
"4"
"web02"
\
"5"
"web03"
3>&1 1>&2 2>&3)
}
sure(){
whiptail
--title
"你确定要这么做吗?"
--yesno
"请做出你的选择YES or NO !"
10
60
}
mingl(){
mling
=
$(whiptail --title
"跳板机-10.0.0.61"
--checklist
"请在下面服务器中选择一台或多台,空格选中"
20 60 11 \
"ml1"
"lb01"
ON \
"ml2"
"lb02"
ON \
"ml3"
"web01"
OFF \
"ml4"
"web02"
OFF \
"ml5"
"web03"
OFF 3>&1 1>&2 2>&3)
}
grepn(){
gn
=
$(whiptail --title
"跳板机-10.0.0.61"
--checklist
"请在下面服务器中选择一台或多台,空格选中"
20 60 11 \
"gn1"
"lb01"
ON \
"gn2"
"lb02"
ON \
"gn3"
"web01"
OFF \
"gn4"
"web02"
OFF \
"gn5"
"web03"
OFF 3>&1 1>&2 2>&3)
}
freem(){
fm
=
$(whiptail --title
"跳板机-10.0.0.61"
--checklist
"请在下面服务器中选择一台或多台,空格选中"
20 60 11 \
"fm1"
"lb01"
ON \
"fm2"
"lb02"
ON \
"fm3"
"web01"
OFF \
"fm4"
"web02"
OFF \
"fm5"
"web03"
OFF 3>&1 1>&2 2>&3)
}
df_h(){
dff
=
$(whiptail --title
"跳板机-10.0.0.61"
--checklist
"请在下面服务器中选择一台或多台,空格选中"
20 60 11 \
"df1"
"lb01"
ON \
"df2"
"lb02"
ON \
"df3"
"web01"
OFF \
"df4"
"web02"
OFF \
"df5"
"web03"
OFF 3>&1 1>&2 2>&3)
}
duoxuan(){
DISTROS
=
$(whiptail --title
"跳板机-10.0.0.61"
--checklist
"请在下面服务器中选择一台或多台,空格选中"
20 60 11 \
"send1"
"lb01"
ON \
"send2"
"lb02"
ON \
"send3"
"web01"
OFF \
"send4"
"web02"
OFF \
"send5"
"web03"
OFF 3>&1 1>&2 2>&3)
}
while
true ;do
OPTION
=
$(whiptail --title
"跳板机-10.0.0.61"
--menu
"请从菜单中选择你想要的"
20 60 10 \
"1"
"ssh远程连接"
\
"2"
"推送文件"
\
"3"
"查看磁盘空间"
\
"4"
"查看内存空间"
\
"5"
"查看服务状态"
\
"6"
"批量执行命令"
\
"7"
"小游戏放松一下吧"
\
"8"
"退出"
3>&1 1>&2 2>&3)
if [
$OPTION
-eq
1 ];then
caidan
case
$fuwu
in
1)
connect
172.16.1.5
;;
2)
connect
172.16.1.6
;;
3)
connect
172.16.1.7
;;
4)
connect
172.16.1.8
;;
5)
connect
172.16.1.9
;;
esac
elif [
$OPTION
-eq
2 ];then
source_file
=
`whiptail --title
"跳板机-10.0.0.61"
--inputbox
" \
请输入源文件位置:"
10 60 /tmp/1.txt 3>&1 1>&2 2>&3`
if [
$?
-eq
0 ];then
dest_file
=
`whiptail --title
"跳板机-10.0.0.61"
--inputbox
"请输入对端存放位置:\
"
10 60 /tmp/ 3>&1 1>&2 2>&3`
if [
$?
-eq
0 ];then
duoxuan
for n
in
$DISTROS;do
${n//\"/
''
}
done
else
echo
'请输入一个目标路径'
fi
else
echo
'请输入一个源文件路径'
fi
elif [
$OPTION
-eq
3 ];then
if [
$?
-eq
0 ];then
df_h
for n
in
$dff;do
${n//\"/
''
}
done
fi
elif [
$OPTION
-eq
4 ];then
if [
$?
-eq
0 ];then
freem
for n
in
$fm;do
${n//\"/
''
}
done
fi
elif [
$OPTION
-eq
5 ];then
if [
$?
-eq
0 ];then
grepn
for n
in
$gn;do
${n//\"/
''
}
done
fi
elif [
$OPTION
-eq
6 ];then
ml
=
`whiptail --title
"跳板机-10.0.0.61"
--inputbox
" \
请输入执行的命令:"
10 60 3>&1 1>&2 2>&3`
if [
$?
-eq
0 ];then
mingl
for n
in
$mling;do
${n//\"/
''
}
done
fi
elif [
$OPTION
-eq
7 ];then
sh /root/6.sh
elif [
$OPTION
-eq
8 ];then
PASSWD
=
`whiptail --title
"跳板机-10.0.0.61"
--passwordbox
"请输入一个密码名路径:"
10 60 3>&1 1>&2 2>&3`
if [
$?
-eq
0 ];then
if [
${#PASSWD}
-ne
0 ];then
if [
$PASSWD
-eq
123 ];then
exit
fi
else
whiptail
--title
"
$HOSTNAME
"
--msgbox
"密码为空"
20
60
fi
else
whiptail
--title
"
$HOSTNAME
Disk Info"
--msgbox
"你选择了取消"
20
60
fi
fi
- 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.
- 161.
- 162.
- 163.
- 164.
- 165.
- 166.
- 167.
- 168.
- 169.
- 170.
- 171.
- 172.
- 173.
- 174.
- 175.
- 176.
- 177.
- 178.
- 179.
- 180.
- 181.
- 182.
- 183.
- 184.
- 185.
- 186.
- 187.
- 188.
- 189.
- 190.
- 191.
- 192.
- 193.
- 194.
- 195.
- 196.
- 197.
- 198.
- 199.
- 200.
- 201.
- 202.
- 203.
- 204.
- 205.
- 206.
- 207.
- 208.
- 209.
- 210.
- 211.
- 212.
- 213.
- 214.
- 215.
- 216.
- 217.
- 218.
- 219.
- 220.
- 221.
- 222.
- 223.
- 224.
- 225.
- 226.
- 227.
- 228.
- 229.
- 230.
- 231.
- 232.
- 233.
- 234.
- 235.
- 236.
- 237.
- 238.
- 239.
- 240.
- 241.
- 242.
- 243.
- 244.
- 245.
- 246.
- 247.
- 248.
- 249.
- 250.
- 251.
- 252.
- 253.
- 254.
- 255.
- 256.
- 257.
- 258.
- 259.
- 260.
- 261.
- 262.
- 263.
- 264.
- 265.
- 266.
- 267.
- 268.
- 269.
- 270.
- 271.
- 272.
- 273.
- 274.
- 275.
- 276.
- 277.
- 278.
- 279.
- 280.
- 281.
- 282.
- 283.
- 284.
- 285.
- 286.
- 287.
- 288.
- 289.
边栏推荐
- 碎片化时间真的适合学习吗?
- Low code of the trilogy
- R语言时间序列数据提取:使用xts包的first函数提取时间序列中最前面10天的数据(first 10 day)
- MarkBERT
- 会议OA项目之待开会议&&所有会议功能
- Small programs use npm packages
- "Additional price" can not exchange for safety, the death of Lexus LM, whose fault is it?
- R语言时间序列数据提取:使用head函数或者tail函数获取时间序列数据中最早或者最新的样本数据
- 中天钢铁在 GPS、 AIS 调度中使用 TDengine
- 关于Image scaleType的属性详解,以及每一个属性的区别
猜你喜欢

手机银行体验性测试:如何获取用户真实感受

记录一个相当坑爹的WSL局域网访问问题

C # CLI (common language infrastructure)

测试基础:Nosql数据库之Redis

Really touch the fish and lead the teacher: The programmer brother works 10 minutes a day with an annual salary of 570,000. I broke the defense...

Win11任务栏太宽了怎么变窄?Win11任务栏宽度调整方法

面试突击:为什么 TCP 需要 3 次握手?

不堆概念、换个角度聊多线程并发编程

centos8安装redis

迅为i.MX8MM开发板Coatrx-M4内核开发给IAR安装8MM补丁
随机推荐
如何使用TDengine Sink Connector?
Go 语言如何读取 excel 测试数据,简单易学
【中标麒麟系统Your trial is EXPIRED and no VALID licens 关闭弹窗】
第01章 Linux下MySQL的安装与使用【1.MySQL架构篇】【MySQL高级】
Neo4j开源NoSQL数据库
Gesture password unlock WeChat applet project source code
智能合约安全——重入漏洞
【PyCharm 常用快捷键】
函数的声明与作用域
Typescript mix method to class with decorator
Security whole configuration does not take effect after the Gateway?
PromptBERT: Improving BERT Sentence Embeddings with Prompts
[数学]必备基本知识
效率技巧│十分钟学会 xmind 思维导图的使用
“加价”都换不来安全保障,雷克萨斯LM之殇,到底是谁的错?
HbuilderX打包app,Hbuilder怎么打包app,H5打包成app,H5怎么打包成app「建议收藏」
Chengdu | Changed to software testing, from zero income to over 10,000 monthly salary, a new turning point in life...
牛客网刷题记录 || 指针
swagger @ApiModel @ApiModelProperty注解属性说明「建议收藏」
H265码流RTP封装方式详解