Linux运维之Shell编程实例
题目1:监控MySQL错误码及主从复制同步异常;
监控MySQL主从同步是否异常,如果异常,则发送短信或者邮件给管理员。提示:如果没主从同步环境,可以用下面文本放到文件里读取来模拟:
阶段1:开发一个守护进程脚本每30秒实现检测一次;
阶段2:如果同步出现如下错误号(1158,1159,1008,1007,1062),则跳过错误;
阶段3:请使用数组技术实现上述脚本(获取主从判断及错误号部分)。
阶段1:
*/2 * * * * user /PATH/TO/SCRIPT
阶段2:监控MySQL-----过滤错误码;
#!/bin/bash
CONTACT='root@node77'
ERR_LOG='/var/log/mariadb/mariadb.log'
yum install mailx -y
email_to_admin() {
mailsubject="MySQL Error."
mailbody="`date +%F-%H:%M:%S`: MySQL Error,please check and repair."
echo $mailbody | mail -s "$mailsubject" $CONTACT
}
while true;do
for ERROR_CODE in `grep 'Error_code: [[:digit:]]\+' $ERR_LOG | grep -o '[[:digit:]]\+'` ;do
case $ERROR_CODE in
1007)
continue
;;
1008)
continue
;;
1158)
continue
;;
1159)
continue
;;
1162)
continue
;;
esac
email_to_admin
done
sleep 30
done
阶段3:监控MySQL-----主从同步;
#!/bin/bash
DB_USER='root'
DB_PASSWORD='cured'
DB_PORT='3306'
MASTER='192.168.0.76'
SLAVE='192.168.0.77'
CMD_CONN_MASTER='mysql -u$DB_USER -p$DB_PASSWORD -P$DB_PORT -h$MASTER'
CMD_CONN_SLAVE='mysql -u$DB_USER -p$DB_PASSWORD' -P$DB_PORT -h$SLAVE'
CONTACT='root@node77'
declare -a master_status
master_status[0]="CMD_CONN_MASTER -e 'show master status\G' | egrep File | cut -d: -f2"
master_status[1]="CMD_CONN_MASTER -e 'show master status\G' | egrep Position | cut -d: -f2"
declare -a slave_status
slave_status[0]="CMD_CONN_SLAVE -e 'show slave status\G' | egrep Master_Log_File | cut -d: -f2"
slave_status[1]="CMD_CONN_SLAVE -e 'show slave status\G' | egrep Read_Master_Log_Pos | cut -d: -f2"
slave_status[2]="CMD_CONN_SLAVE -e 'show slave status\G' | egrep Last_Errno | cut -d: -f2"
email_to_admin() {
mailsubject="Syncing failed."
mailbody="`date '+%F %H:%M:%S'`: Syncing of master-slave is failed,please check and repair."
echo $mailbody | mail -s "$mailsubject" $CONTACT
}
while true ; do
if [ ${master_status[0]} == ${slave_status[0]} -a ${master_status[1]} == ${slave_status[1]} -a ${slave_status[2]} == 0 ]; then
echo "Syncing of master-slave is OK."
else
echo "Syncing of master-slave is failed."
email_to_admin
fi
sleep 30
done
题目2:批量创建、重命名文件;
(1)使用for循环在/heros目录下通过随机小写10个字母加固定字符串_yangkang批量创建10个html文件,名称例如为:
(2)将上述各文件名中的yangkang改为yangguo,并将html改成大写。
#!/bin/bash
#批量创建随机名称的文件
HTML_DIR=/heros
[ ! -d $PATH ] && mkdir $HTML_DIR
#yum isntall coreutils -y
#[ ! -d $PATH ] && install -m 700 -d $HTML_DIR
#使用install创建目录时,需安装coreutils。
cd $HTML_DIR && for i in `seq 10` ; do touch `openssl rand -base64 64 | tr -dc a-z | head -c 10`_yangkang.html; done
#!/bin/bash
#批量重命名文件
HTML_DIR=/heros
FILES=`ls $HTML_DIR`
GUO=guo.HTML
YANGGUO=_yangguo.HTML
cd $HTML_DIR && for j in $FILES; do
CHARS=`echo $j | cut -c 1-15`
mv $CHARS* $CHARS$GUO
done
cd $HTML_DIR && for j in $FILES; do
CHARS=`echo $j | awk -F '_' '{print$1}'`
mv $CHARS* $CHARS$YANGGUO
done
类似题目:批量创建用户;
批量创建10个系统帐号user01-user10,并设置密码为随机8位字符串。
#!/bin/bash
#批量创建用户,密码随机
for i in {01..10}; do
PASSWORD=`tr -dc [:alpha:] < /dev/urandom | head -c 8`
#PASSWORD=`openssl rand -base64 16 | tr -dc [[:alpha:]] | head -c 8`
useradd user$i
echo $PASSWORD | passwd --stdin user$i
echo user$i-----$PASSWORD >> /tmp/user-pwd.txt
done
for j in {01..10}; do userdel -r user$j; done
题目3:判断在线主机;
写一个脚本,实现判断10.0.0.0/24网络里,当前在线用户的IP有哪些。
#!/bin/bash
#
declare -i i=1
declare -i online
declare -i offline
net="10.0.0."
while [ i -le 254 ]; do
ping $net$i -c2 -w2 &> /dev/null
if [ $? -eq 0 ];then
echo "$net$i is on-line."
let online++
else
echo "$net$i is off-line."
let offline++
fi
let i++
done
echo "NO. of on-line hosts: $online ."
echo "NO. of off-line hosts: $offline ."
题目4:监控并发连接;
写一个脚本解决DOS攻击生产案例。
提示:根据web日志或者或者网络连接数,监控当某个IP并发连接数或者短时内PV达到100,即调用防火墙命令封掉对应的IP,监控频率每隔3分钟。防火墙命令为:iptables -I INPUT -s 10.0.1.10 -j DROP。
#!/bin/bash
IPlist=`netstat -ntu | awk 'NR>2' | awk '{print $5}' | cut -d: -f1 | uniq -c | sort | awk '{if($1>99)print $2}'`
#测试时,使用的并发连接为2,实际生产可将NR>2改为>100;
for ip in $IPlist; do
iptables -I INPUT -s $ip -j DROP
echo "$IPlist is dropped."
sleep 180
done
题目5:服务启动脚本;
开发mysql多实例启动脚本:
已知mysql多实例启动命令为:mysqld_safe--defaults-file=/data/3306/my.cnf &
停止命令为:mysqladmin -u$MYSQL_USER -p$MYSQL_PASSWORD -S /data/3306/mysql.sock shutdown
请完成mysql多实例启动启动脚本的编写。
要求:用函数,case语句、if语句等实现。
#!/bin/bash
. /etc/init.d/functions
declare -a PORT
PORT=(3306 3307 3308 3309 3310)
MYSQL_SOCK=/data/$PORT/mysql.sock
for i in (3306..3310); do echo $i; done
start() {
if [ ! e "MYSQL_SOCK" ]; then
nohub mysqld_safe--defaults-file=/data/${PORT[$i]}/my.cnf > /dev/null 2>&1 &
ss -tun | grep :${PORT[$i]}
if [ $? -eq 0 ]; then
action "Mysql of ${PORT[$i]} is listening." /bin/true
else
action "Mysql of ${PORT[$i]} isn't listening" /bin/false
fi
else
action "Mysql of ${PORT[$i]} is listening already." /bin/false
}
stop() {
if [ e "MYSQL_SOCK" ]; then
nohub mysqladmin -u$MYSQL_USER -p$MYSQL_PASSWORD -S /data/$PORT/mysql.sock shutdown > /dev/null 2>&1 &
ss -tun | grep :$PORT{PORT[$i]}
if [ $? -ne 0 ]; then
action "Mysql of $PORT has been stopped." /bin/true
else
action "Mysql of $PORT is still listening." /bin/false
fi
else
action "Mysql of $PORT has been stopped already." /bin/false
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
*)
echo "Usage:$0 {3306|3307|3308|3309|3310}{start|stop|restart}"
;;
esac
类似题目:rsyncd服务启动脚本;
撰写脱离xinetd服务,独立进程运行模式下rsync的服务启动脚本;
例如:/etc/init.d/rsyncd{start|stop|restart}
要求:使用函数、可被chkconfig管理;
#!/bin/bash
# chkconfig: 2345 75 25
# describtion: This service starts|stops|restarts rsync server daemon.
. /etc/rc.d/init.d/functions
prog=$(basename $0)
lockfile=/var/lock/subsys/$prog
start() {
if [ -e $lockfile ]; then
action "Rsyncd is running already." /bin/false
else
touch $lockfile
action "Starting rsyncd finished." /bin/true
fi
}
stop() {
if [ -e $lockfile ]; then
rm -f $lockfile
action "Stopping rsyncd finished." /bin/true
else
action "Rsyncd is stopped already." /bin/false
fi
}
status() {
if [ -e $lockfile ]; then
echo "Rsyncd is running."
else
echo "Rsyncd is stopped."
fi
}
usage() {
echo "Usage:$prog {start|stop|status|restart}"
}
if [ $# -ne 1 ]; then
usage
exit
fi
case $1 in
start)
start
;;
stop)
stop
;;
status)
status
;;
restart)
stop
start
;;
*)
usage
;;
esac
题目6:打包备份;
如何实现对MySQL数据库进行分库加分表备份,请用脚本实现。
#!/bin/bash
yum install expect -y
DATE=`date +%Y-%m-%d`
OLD_DATE=`date +%Y-%m-%d -d '-30 days'`
BAK_DIR=/backup/mydata
DB_USER=root
DB_PASSWORD=cured
DB_name=DB_NAME
table_name=TABLE_NAME
[ -d ${BAK_DIR} ] || mkdir -p ${BAK_DIR}
[ -d ${BAK_DIR}/${DATE} ] || mkdir ${BAK_DIR}/${DATE}
[ ! -d ${BAK_DIR}/${OLD_DATE} ] || rm -rf ${BAK_DIR}/${OLD_DATE}
for DB_NAME in mysql $DB_NAME $TABLE_NAME
do
/usr/bin/mysqldump -u$DB_USER -p$DB_PASSWORD --databases ${DB_NAME} > ${BAK_DIR}/${DATE}/${DATE}-${DB_NAME}-backup.sql
/bin/sleep 3
done
cd ${BAK_DIR}
tar -cjf $DATE.db_bak.tar.bz2 $DATE
/bin/sleep 3
password='cured'
#System user's password for root@DB_BAK_SERVER
expect -c "
spawn scp $DATE.db_bak.tar.bz2 root@DB_BAK_SERVER:/backup/mydata
expect {
\"yes/no\" {set timeout 30; send \"yes\r\"; exp_continue;}
\"password\" {set timeout 30; send \"$password\r\";}
}
expect eof"
#####本脚本实现MySQL服务器打包压缩备份,并自动交互上传至备份服务器,分库分表备份暂未实现。#####
题目7:字符串打印;
使用for循环打印下面这句话中字母数不大于6的单词。
I am an interviewer, welcome to our company for interviewing .
#!/bin/bash
WORDS='I am an interviewer welcome to our company for interviewing'
for i in $WORDS; do
NUM= `echo $i | wc -L`
if [ $NUM -le 6 ]; then
echo $i
fi
done
for i in $WORDS; do
if [ ${#i} -le 6 ]; then
echo $i
fi
done
类似题目:字符串处理;
中启动力shell面试题:
1、按单词出现频率降序排序!
2、按字母出现频率降序排序!
the squid project provides a number of resources toassist users design,implement and support squid installations. Please browsethe documentation and support sections for more infomation
#!/bin/bash
WORDS='the squid project provides a number of resources toassist users design implement and support squid installations Please browsethe documentation and support sections for more infomation'
for i in $WORDS; do echo $i; done | sort | uniq -c | sort -rn
#!/bin/bash
WORDS='the squid project provides a number of resources toassist users design implement and support squid installations Please browsethe documentation and support sections for more infomation'
for i in $WORDS; do
for j in `seq 1 ${#i}`; do
ALPHA=`echo $i | cut -c$j`
echo $ALPHA
done
done | sort | uniq -c | sort -rn
题目8:判断数字大小;
开发shell脚本,分别实现以脚本传参以及read读入的方式比较2个整数大小。以屏幕输出的方式提醒用户比较结果。注意:一共是开发2个脚本。当用脚本传参以及read读入的方式需要对变量是否为数字、并且传参个数做判断。
#!/bin/bash
##########以脚本传参,非read读入方式(执行脚本时,在命令后面跟两个参数)##########
[ ! $# -ne 2 ] && {
echo "You should input 2 integer nums after run $0 next time,bye."
exit 1
}
expr $1 + 1 &> /dev/null
RETVAL_A=$?
expr $2 + 2 &> /dev/null
RETVAL_B=$?
[ $RETVAL_A -ne 0 -o $RETVAL_B -ne 0 ] && {
echo "At least one of numbers you input isn't integer num."
exit 2
}
if [ $1 -lt $2 ] ; then
echo "$1 < $2"
elif [ $1 -eq $2 ] ; then
echo "$1 = $2"
else
echo "$1 > $2"
fi
#!/bin/bash
##########read读入方式##########
read -t 10 -p "Please input one integer nums: " a
if [ -z $a ];then
echo "2B,Bye." && exit 1
fi
read -t 10 -p "Please input the other integer nums: " b
if [ -z $b ];then
echo "2B,Bye." && exit 1
fi
expr $a + 1 &> /dev/null
RETVAL_A=$?
expr $b + 2 &> /dev/null
RETVAL_B=$?
[ $RETVAL_A -ne 0 -o $RETVAL_B -ne 0 ] && {
echo "At least one of numbers you input isn't integer num."
exit 2
}
if [ $a -lt $b ] ; then
echo "$a < $b"
elif [ $a -eq $b ] ; then
echo "$a = $b"
else
echo "$a > $b"
fi
题目9:打印菜单;
打印选择菜单,一键安装web服务;
[root@node25 ~ ]# sh menu.sh
1.[install lamp]
2.[install lnmp]
3.[exit]
Please select an pition:
要求:
1、当用户输入1时,输出“start to install lamp.”然后执行/server/scripts/lamp.sh,脚本内容输出"lamp is installed"后退出脚本;
2、当用户输入2时,输出“start to install lnmp.”然后执行/server/scripts/lnmp.sh输出"lnmp is installed"后退出脚本;
3、当输入3时,退出当前菜单及脚本;
4、当输入任何其它字符,给出提示“Input error”后退出脚本;
5、要对执行的脚本进行相关条件判断,例如:脚本是否存在,是否可执行等。
#!/bin/bash
cat << EOF
1.[install lamp]
2.[install lnmp]
3.[exit]
============================
EOF
read -p "Please select an pition: " option
while [ "$option" != '1' -a "$option" != '2' -a "$option" != '3' ]; do
read -p "Wrong option, select again: " option
done
if [ "$option" == '1' ]; then
echo "Start to install lamp."
echo "Lamp is installed."
exit 1
elif [ "$option" == '2' ]; then
echo "Start to install lnmp."
echo "Lnmp is installed."
exit 2
else
echo "Exit"
exit 3
fi
#####最后的if多分支条件语句也可改为以下的case条件语句。#####
case $option in
1)
echo "Start to install lamp."
echo "Lamp is installed."
exit 1
;;
2)
echo "Start to install lnmp."
echo "Lnmp is installed."
exit 2
;;
3)
echo "Exit"
exit 3
;;
*)
echo "Usage:{1|2|3|}"
exit 4
;;
case
题目10:监控web和DB服务;
要求:1、分别监控web和DB服务是否正常,各不低于3种监控策略;2、间隔1分钟,持续监控。
监控web法一:80端口;
ss -tanl | grep :80 | uniq | wc -l
netstat -tanl | grep :80 | uniq | wc -l
监控web法二:http状态码,正常访问时为200;
yum install curl -y
curl -I -s -o /dev/null -w %{http_code} $WEB_SVR_URL
-I, --head Show document info only
-m, --max-time SECONDS
-o /dev/null, --output FILE to /dev/null
-s, --silent Silent mode
-w %{http_code},-w, --write-out FORMAT What to output after completion
yum install wget -y
wget -S -T 10 --spider $WEB_SVR_URL 2>&1 | grep "200" | awk '{print $2}'
-S, --server-response print server response.
--spider don't download anything.
-T, --timeout=SECONDS
监控web法三:web进程,这里以httpd为例;
ps -ef | grep httpd | grep -v grep | uniq | wc -l
#!/bin/bash
PORT_NUMS=`ss -tanl | grep :80 | uniq | wc -l`
#PORT_NUMS=`netstat -tanl | grep :80 | uniq | wc -l`
CONTACT='root@node77'
email_to_admin() {
mailsubject="Web Down."
mailbody="`date '+%F %H:%M:%S'`: Web service is unavailable,please check and repair."
echo $mailbody | mail -s "$mailsubject" $CONTACT
}
if [ $PORT_NUMS -eq 0 ]; then
echo "Web service is unavailable."
mail_to_admin
else
echo "Web service works correctly."
fi
#!/bin/bash
yum install curl wget -y
WEB_SVR_URL="http://192.168.0.76/index.html"
STATUS_CODE=`curl -I -s -o /dev/null -w %{http_code} $WEB_SVR_URL`
#STATUS_CODE=`wget -S -T 10 --spider $WEB_SVR_URL 2>&1 | grep "200" | awk '{print $2}'`
CONTACT='root@node77'
email_to_admin() {
mailsubject="Web Down."
mailbody="`date '+%F %H:%M:%S'`: Web service is unavailable,please check and repair."
echo $mailbody | mail -s "$mailsubject" $CONTACT
}
if [ $STATUS_CODE == "200" ]; then
echo "Web service works correctly."
else
echo "Web service is unavailable."
mail_to_admin
fi
#!/bin/bash
PID_NUMS=`ps -ef | grep httpd | grep -v grep | uniq | wc -l`
CONTACT='root@node77'
email_to_admin() {
mailsubject="Web Down."
mailbody="`date '+%F %H:%M:%S'`: Web service is unavailable,please check and repair."
echo $mailbody | mail -s "$mailsubject" $CONTACT
}
if [ $PID_NUMS -eq 0 ]; then
echo "Web service is unavailable."
mail_to_admin
else
echo "Web service works correctly."
fi
监控DB法一:监听端口(以MySQL或MariaDB为例);
DB_PORT=`ss -tanl | grep :3306 | awk '{print $4}' | cut -d: -f2`
if [ $DB_PORT == "3306" ]; then
echo "Database service works correctly."
......
监控DB法二:sock文件(以MySQL或MariaDB为例);
DB_HOME="/var/lib/mysql/"
DB_SOCK="mysql.sock"
SOCK_FILE=`ls -l $DB_HOME$DB_SOCK`
if [ -e $SOCK_FILE ]; then
echo "Database service works correctly."
......
监控DB法三:DB进程(以MySQL或MariaDB为例);
DB_PID_NUMS=`ps -ef | grep mysql | grep -v grep | uniq | wc -l`
DB_PID_NUMS=`ps -ef | grep mariadb | grep -v grep | uniq | wc -l`
if [ $DB_PID_NUMS -gt 0 ]; then
echo "Database service works correctly."
......
题目11:监控memcache服务;
监控memcached服务是否正常,模拟用户(web客户端)检测;
使用nc命令加上set/get来模拟检测,以及监控响应时间及命中率。
#!/bin/bash
mem_srv=`ss -tunl | grep :11211 | wc -l`
log_path=/monitor/memcached
#email_of_admin=username@domain
if [ ! -d $log_path ]; then
mkdir -p $log_path
fi
if [ $mem_srv -gt 0 ]; then
printf "set test_key 0 3600 5\r\nhello\r\n" | nc 127.0.0.1 11211 &> /dev/null
retn_code_1=`echo $?`
printf "get test_key\r\n" | nc 127.0.0.1 11211 &> /dev/null
retn_code_2=`echo $?`
printf "delete test_key\r\n" | nc 127.0.0.1 11211 &> /dev/null
retn_code_3=`echo $?`
if [ $retn_code_1 -eq 0 -a $retn_code_2 -eq 0 -a $retn_code_3 -eq 0 ]; then
echo "Memcached service is OK."
num_of_get_hits=`printf "stats\r\n" | nc 127.0.0.1 11211 | grep "get_hits" | awk '{print $3}'`
num_of_cmd_get=`printf "stats\r\n" | nc 127.0.0.1 11211 | grep "cmd_get" | awk '{print $3}'`
get_hit_rate=`awk 'BEGIN{printf "%.2f%\n",('$num_of_get_hits'/'$num_of_cmd_get')*100}'`
echo "The get_hit_rate is : $get_hit_rate ."
fi
else
echo "Memcached service is down at `date +%F-%H:%M:%S`." | tee ${log_path}/error.log
# mail -s "Memcached service is down at `date +%F-%H:%M:%S`." $email_of_admin
fi
题目12:监控文件安全;
监控web文件是否被篡改,如果被篡改,则告警并且发邮件;每3分钟检查一次。
思路:Web上线后,使用md5sum命令对整个web目录中的所有文件生成相应地md5码,保存在/md5db/web/original.txt中。以后的md5码保存在/md5db/web/current.txt中,
被篡改的文件信息保存在/md5db/web/different.txt中。
#!/bin/bash
WEB_DIR="/var/www/html"
DATE=`date +%F`
TIME=`date +%H:%M:%S`
[ ! -d /md5db/web ] && mkdir -p /md5db/web
md5sum $WEB_DIR/* > /md5db/web/current.txt
diff /md5db/web/original.txt /md5db/web/current.txt > /md5db/web/different.txt
if [ ! $? -eq 0 ]; then
echo -e "\033[41;37m Warning!web files have been altered at $DATE $TIME.\033[0m"
cat /md5db/web/different.txt
# mail_to_amin
else
echo "Relax,web files are not be altered."
fi
crontab -e
*/20 * * * * root bash /bashs/md5db.sh
题目13:抓阄;
有N个学生,选3个参加实践;
要求:
1、执行脚本时,想去的同学输入姓名后,随机产生1-99之间的数字,数字最大的3人参加实践,已抓到的数字,下次不能再出现;
2、第一个名字输入后,屏幕输出信息,并将名字和数字记录到文件中,程序不能退出继续等待别的学生输入。
#!/bin/bash
NAME_LIST="/tmp/name_list.txt"
>$NAME_LIST
STU_NUMS=9
read_name(){
read -p "Please enter your name: " name
if [ -z $name ]; then
echo "Nothing input."
read_name
else
if [ `egrep -w "$name" $NAME_LIST | wc -l` -gt 0 ]; then
echo "This name is already in-use."
read_name
fi
if [ `egrep -w "$(echo $[$RANDOM%99+1])" $NAME_LIST | wc -l` -gt 0 ]; then
echo "This number is already in-use."
read_name
fi
if [ `egrep -w "$name" $NAME_LIST | wc -l` -eq 0 ] && [ `egrep -w "$(echo $[$RANDOM%99+1])" $NAME_LIST | wc -l` -eq 0 ]; then
echo "`echo $[$RANDOM%99+1]` $name" >> $NAME_LIST
fi
fi
}
while [ `cat $NAME_LIST | sort -rn -k1 | wc -l` -le $STU_NUMS ]; do
read_name
done
echo "The loting is ended, the results are as fallows: "
cat $NAME_LIST | sort -rn -k1 | head -3
#循环从0开始,这里表示学生数目的变量值为:学生总人数-1;
#随机产生1-99之间的数字,在使用RANDOM系统内置变量时需要用:数字最大值+1,如[$RANDOM%99+1](也就是[$RANDOM%100])。
题目14:检查网站地址是否正常;
https://www.aliyun.com
http://download.cirros-cloud.net
http://nginx.org
http://61.135.169.125
要求使用数组。
#!/bin/bash
declare -a urls
urls=(
"https://www.aliyun.com"
"http://download.cirros-cloud.net"
"http://nginx.org"
"http://61.135.169.125"
)
while true; do
for ((i=0;i<${#urls[*]};i++)); do
wget --spider --timeout=6 --tries=3 ${urls[$i]} &> /dev/null
if [ $? -eq 0 ]; then
echo "${urls[$i]} is OK."
else
echo "${urls[$i]} is down."
fi
sleep 3
done
done
题目15:暴力破解加密字符串;
已知下面的字符串是通过RANDOM随机数变量md5sum|cut -c 1-8截取后的结果,请破解这些字符串对应的md5sum前的RANDOM对应数字?
21029299
00205d1c
a3da1677
1f6d12dd
#!/bin/bash
rand_str=(
21029299
00205d1c
a3da1677
1f6d12dd
)
for ((i=0;i<32768;i++)); do
for ((j=0;j<${#rand_str[*]};j++)); do
if [ "`echo $i | md5sum | cut -c1-8`" == "${rand_str[$j]}" ]; then
echo $i ${rand_str[$j]}
fi
done
done
结果:
1346 00205d1c
7041 1f6d12dd
25345 a3da1677
25667 21029299