考试题 1:用 source 执行脚本和用 bash 执行 Shell 脚本的区别是什么?
用source执行脚本,是在当前shell中执行的脚本,脚本中的变量值在当前shell中依然存在。用bash执行脚本都会启动新的子shell执行,执行完后退回的父shell。因此,变量值无法保留。
考试题 2:定义变量内容,不加引号、单引号、双引号、反引号有什么区别?
不加引号 内容是纯数字、简单的连续字符时,可以不加任何引号
单引号 所见所得。希望变量的内容原样输出时加单引号
双引号 输出双引号内所有内容
反引号 希望变量引用命令的结果时就用反引号或$()
考试题 3:写出特殊变量对应的意义及应用?
ID | 变量 | 含义 |
---|---|---|
1 | $0 | 获取当前执行的shell脚本名称,如果执行脚本包含的路径,那么就包括脚本路径 |
2 | $n | 获取当前执行shell脚本的第n个参数值,n=1..9 ,当n为0是表示文件名;如果n大于9 用大括号括起来 |
3 | $# | 获取当前执行shell脚本的第n个参数值,n=1..9 ,当n为0是表示文件名;如果n大于9 用大括号括起来 |
4 | $* | 获取当前执行shell脚本的第n个参数值,n=1..9 ,当n为0是表示文件名;如果n大于9 用大括号括起来 |
5 | $@ | 获取当前执行shell脚本的第n个参数值,n=1..9 ,当n为0是表示文件名;如果n大于9 用大括号括起来 |
6 | $? | 获取当前执行shell脚本的第n个参数值,n=1..9 ,当n为0是表示文件名;如果n大于9 用大括号括起来 |
7 | $$ | 获取当前执行的shell脚本的进程号(PID) |
8 | $! | 获取上一个在后台运行的进程号(PID) |
考试题 4:写出下面特殊变量扩展的意义
ID | 表达式 | 含义 |
---|---|---|
1 | ${oldboy} | 返回变量$oldboy的内容 |
2 | ${#oldboy} | 按字符返回变量${oldboy} 内容的长度 |
3 | ${oldboy:offset:length} | 在变量${oldboy}中,从位置offset 之后开始提取长度为Length 的子串 |
4 | ${oldboy#word} | 表示开头删除,匹配最短 word字串 |
5 | ${oldboy##word} | 表示开头删除,匹配最长word字串 |
6 | ${oldboy%word} | 表示从结尾删除,匹配最短word字串 |
7 | ${oldboy%%word} | 表示从结尾删除,匹配最长word字串 |
8 | ${oldboy/pattern/string} | 使用string 代替第一个pattern |
9 | ${oldboy//pattern/string} | 使用string 代替全部 pattern |
10 | ${oldboy:-word} | 如果oldboy的变量为空或未赋值,则会返回word字符串代替变量的值 |
考试题 5:通过脚本传参的方式,检查 Web 网站 URL 是否正常(要求主体使用函数)。
- 脚本实现:
方法1:
#!/bin/bash
wget -q $1 &>/dev/null
retval=$?
if [ $retval -eq 0 ]
then
echo "url is ok."
else
echo "url is no."
fi
考试题 6:开发 Nginx 服务(编译安装)启动停止脚本,并分别通过 chkconfig(CentOS6)和 systemctl(CentOS7)实现开机自启动。
- 脚本实现:
#!/bin/bash
[ -f /etc/rc.d/init.d/functions ] && source /etc/rc.d/init.d/functions
lockdir='/var/lock/subsys'
lock_file_path="$lockdir/nginx"
nginx_pid_file_path="/application/nginx/logs/nginx.pid"
log_success_msg(){
action "SUCCESS! $@" /bin/true
}
#失败提示函数
log_failure_msg(){
action "ERROR! $@" /bin/false
}
start(){
/application/nginx/sbin/nginx &>/dev/null
retval=$?
if [ $retval -eq 0 ]
then
log_success_msg "Nginx is started."
if test -w "$lockdir" #判断锁目录是否可写。
then
touch "$nginx_file_path" #创建锁文件。
return $retval
else
log_failure_msg "Nginx lockfile denied" #调用失败函数提示。
return 1
fi
else
echo "Nginx startup fail."
return 1
fi
}
stop(){
if test -s "$nginx_pid_file_path"
then
#读取pidfile
nginx_pid=`cat "$nginx_pid_file_path"`
if (kill -0 $nginx_pid 2>/dev/null)
then
kill $nginx_pid
retval=$?
if [ $retval -eq 0 ]
then
log_success_msg "Nginx Stop" #调用停止成功函数。
if test -f "$lock_file_path"
then
rm "$lock_file_path" #删除锁文件。
fi
return $retval
else
log_failure_msg "Nginx Stop."
return $retval
fi
else
log_failure_msg "Nginx server_pid's process is not running!"
rm "$nginx_pid_file_path"
fi
else
log_failure_msg "nginx server PID file is null or not exist!"
return 1
fi
}
case "$1" in
start)
start
retval=$?
;;
stop)
stop
retval=$?
;;
restart)
stop
sleep 2
start
retval=$?
;;
*)
echo $"Usage:$0 {start|stop|restart}"
exit 1
esac
exit $retval
考试题 7:猜数字游戏。首先让系统随机生成一个数字,给这个数字定一个范围(1-60),让用户输入猜的数字,对输入进行判断,如果不符合要求,就给予高或低的提示,猜对后则给出猜对用的次数。
- 脚本实现:
#!/bin/bash
YOUXI(){
clear
number=$[$RANDOM%100]
i=1
while true
read -p "猜吧,范围是0-100的整数,不可以猜别哦。 :" num
do
if [[ ! "$num" =~ ^[0-9]+$ ]]
then
echo "你输入的是啥玩意?重输"
else
if [ $num -eq $number ]
then
echo "哎嘛!真聪明!跟我比也就差那么一点吧!"
sleep 1
echo "啾儿~~duang! 啾儿~~duang!"
sleep 2
echo "啾儿~~duang! 啾儿~~duang!"
sleep 2
echo "啊?你问我干啥呢?"
sleep 2
echo "这不给你放烟花呢嘛!"
sleep 2
echo "啥?想出去?那不行,再来一把吧"
sleep 2
JIXU
elif [ $num -gt $number ]
then
echo "没猜着!好像猜大了"
let i=$i+1>/dev/null
else
echo "没猜着!好像猜小了"
let i=$i+1>/dev/null
fi
fi
done
}
JIXU(){
clear
cat<<eof
=====================
| 1.真好玩再来一把 |
| 2.选1 |
| 3.选2 |
=====================
eof
read -p "再来一次吧!" jixu
case $jixu in
1)
echo "好嘞!游戏马上开始"
echo "载入中。。。" &&sleep 2
YOUXI
;;
2)
echo "骗你的!这是个隐藏的退出开关。"
sleep 1
echo "看看你的智商是啥水平"
if [ $i -le 3 ]
then
echo -e "
=======================================
| \033[31m(三次以下).堪比诸葛亮 \033[0m |
| (八次以下).也就一般吧 |
| (八次以上).笨比 |
=======================================
"
elif [[ $i -gt 3 && $i -le 8 ]]
then
echo -e "
=======================================
| (三次以下).堪比诸葛亮 |
| \033[31m(八次以下).也就一般吧 \033[0m |
| (八次以上).笨比 |
=======================================
"
else
echo -e "
=======================================
| (三次以下).堪比诸葛亮 |
| (八次以下).也就一般吧 |
| \033[31m(八次以上).笨比 \033[0m |
=======================================
"
fi
echo "退出中。。。" &&sleep 2 && exit 0
;;
3)
echo "骗你的!这是个隐藏的退出开关。"
if [ $i -le 3 ]
then
echo -e "
=======================================
| \033[31m(三次以下).堪比诸葛亮 \033[0m |
| (八次以下).也就一般吧 |
| (八次以上).笨比 |
=======================================
"
elif [[ $i -gt 3 && $i -le 8 ]]
then
echo -e "
=======================================
| (三次以下).堪比诸葛亮 |
| \033[31m(八次以下).也就一般吧 \033[0m |
| (八次以上).笨比 |
=======================================
"
else
echo -e "
=======================================
| (三次以下).堪比诸葛亮 |
| (八次以下).也就一般吧 |
| \033[31m(八次以上).笨比 \033[0m |
=======================================
"
fi
echo "退出中。。。" && sleep 2 && exit 0
;;
*)
echo "没用的别挣扎了!hia hia hia hia"
JIXU
;;
esac
}
BUWAN(){
clear
cat<<eof
=====================
| 1.算了玩吧 |
| 2.劳资就是不玩 |
=====================
eof
read -p "再想想!我四十米长刀已经拔出来了! :" B
case $B in
1)
echo "这才对嘛!紧张刺激的猜数字游戏马上开始!"
echo "载入中。。" && sleep 2
YOUXI
;;
2)
echo "没用的必须玩,准备好!开始了!"
echo "载入中。。。" && sleep 2
YOUXI
;;
*)
echo "只能输1和2,重来!"
sleep 1
BUWAN
esac
}
HEAD(){
clear
cat <<eof
=====================
| y.猜数字 |
| n.exit |
=====================
eof
read -p "是否要进行一场紧张刺激的猜数字游戏呢(y|n) :" A
case $A in
y|Y|yes)
echo "紧张刺激的猜数字游戏马上开始!"
echo "载入中。。。" && sleep 2
YOUXI
;;
n|N|no)
BUWAN
;;
*)
echo "你咋回事??重输!"
HEAD
esac
}
clear
cat <<eof
=====================
| y.搞快点 |
| n.劳资不玩 |
=====================
eof
read -p "是否要进行一场紧张刺激的猜数字游戏呢(y|n) :" A
case $A in
y|Y|yes)
echo "紧张刺激的猜数字游戏马上开始!"
echo "载入中。。。" && sleep 2
YOUXI
;;
n|N|no)
BUWAN
;;
*)
echo "你咋回事??重输!"
sleep 2
HEAD
esac
考试题 8:计算从 1 加到 100 之和(要求用 for 和 while,至少给出两种方法)。
- 脚本实现:
方法1:
#!/bin/bash
sum=0
for i in `seq 1 100`
do
sum=$[$sum+$i]
done
echo $sum
方法2:
#!/bin/bash
j=0
for((i=0;i<=100;i++))
do
((j=j+i))
done
echo $j
方法3:
#!/bin/bash
i=0
n=1
while [ $n -lt 101 ]
do
i=$[$n+$i]
n=$[$n+1]
done
echo $i
方法4:
#!/bin/bash
i=0
n=100
until [ $n -le 0 ]
do
i=$[$n+$i]
n=$[$n-1]
done
echo $i
考试题 9: 利用 bash for 循环打印下面这句话中字母数不大于 6 的单词(某企业面试真题)。I am oldboy teacher welcome to oldboy training class
- 脚本实现:
#!/bin/bash
array=(I am oldboy teacher welcome to oldboy training class)
for word in ${array[*]}
do
if [ ${#word} -le 6 ]
then
echo $word
fi
done
考试题 10:使用 read 读入方式比较两个整数大小,要求对用户输入的内容严格判断是否为整数,是否输入了两个数字。
- 脚本实现:
方法1(严谨):
#!/bin/bash
read -p "pls input two number:" nmb1 nmb2
expr $nmb1 + 1 &>/dev/null
retval1=$?
expr $nmb2 + 1 &>/dev/null
retval2=$?
if [ -z "$nmb1" -o -z "$nmb2" -o $retval1 -ne 0 -o $retval2 -ne 0 ]
then
echo "请输入两个整数"
exit 1
fi
if [ $nmb1 -gt $nmb2 ]
then
echo "$nmb1>$nmb2"
elif [ $nmb1 -lt $nmb2 ]
then
echo "$nmb1<$nmb2"
else
echo "$nmb1=$nmb2"
fi
方法2(不严谨):
#!/bin/bash
read -p "input var1 var2:" var1 var2
if [ $var1 -gt $var2 ] ; then
echo "$var1 > $var2"
elif [ $var1 -lt $var2 ] ; then
echo "$var1 < $var2"
else
echo "$var1 = $var2"
fi
考试题11:批量生成随机字符文件名案例
使用for 循环在/oldboy目录下批量创建10个html文件,其中每个文件需要包含oldboy 固定字符串加10 个随机小写字母,名称示例如下:
[root@oldboy scripts]# ls /oldboy
oldboy_amaeeurmja.html oldboy_jmtiqwhinw.html oldboy_rnbwmjkjkh.html oldboy_yhufdiceox.html
oldboy_antodvkjcf.html oldboy_ncivkckvok.html oldboy_tyqfhfxvup.html
oldboy_epwmszmttm.html oldboy_osjmrurgsx.html oldboy_vpgslhajdn.html
- 脚本实现:
#!/bin/bash
a=/oldboy
[ -d "$a" ] || mkdir -p $a
for n in {1..10}
do
b=`openssl rand -base64 40 |sed 's#[^a-z]##g' |cut -c 1-10`
touch $a/oldboy_${b}.html
done
考试题12:批量改名特殊案例
将上题11中结果文件名中的oldboy字符串全部改成oldgirl,并且将扩展名html全部改成 大写HTML(不低于2 种方法)
- 脚本实现:
方法1:
#!/bin/bash
DirName="/oldboy"
cd $DirName||exit 1
for OldFileName in `ls`
do
NewFileName=$(echo $OldFileName|awk -F [_.] '{print "oldgirl_"$2".HTML"}')
mv $OldFileName ${NewFileName}
done
方法2:
ls *.html|awk -F '[_.]' '{print "mv",$0,"oldgirl_"$2".HTML"}'|bash
方法3:
rename oldboy oldgirl *.html && rename .html .HTML *.html
考试题13:批量创建特殊要求用户案例
批量创建10 个系统帐号oldboy01-oldboy10并设置密码(密码为随机8位数)。
不用for 循环的实现思路:http://user.qzone.qq.com/49000448/blog/1422183723
- 脚本实现:
方法1:
#!/bin/bash
. /etc/init.d/functions
for user in oldboy{01..10}
do
passwd=`echo $user|md5sum|cut -c 1-8`
if [ `id $user 2>/dev/null|wc -l` -ge 1 ]
then
action "$user is no" /bin/false
continue
else
useradd $user &>/dev/null &&{
echo -e "${user}:$passwd" >>/tmp/user.txt #存用户面信息
}
fi
done
if [ -s /tmp/user.txt ]
then
chpasswd</tmp/user.txt
fi
方法2:
#!/bin/bash
for user in {01..10}
do
pass=`echo "$RANDOM"|md5sum|cut -c 1-8`
useradd oldboy$user &>/dev/null
echo "$pass"|passwd --stdin oldboy$user &>/dev/null
echo "oldboy$user $pass" >>/tmp/pass.log
done
批量删除用户10个用户
#!/bin/bash
for user in oldboy{01..10}
do
userdel -r $user
done
考试题14:解决DOS 攻击生产案例
写一个Shell脚本解决DOS攻击生产案例。 请根据 web 日志,监控当某个 IP 短时内 PV 达到 100(读者根据实际情况设定),即调用 防火墙命令封掉对应的IP。防火墙命令为:iptables -I INPUT -s IP -j DROP(IP为要封的 地址)
- 脚本实现:
file=$1
awk '{print $1}' $1|grep -v "^$"|sort|uniq -c >/tmp/tmp.log
exec </tmp/tmp.log
while read line
do
ip=`echo $line|awk '{print $2}'`
count=`echo $line|awk '{print $1}'`
if [ $count -ge 30 ] && [ `iptables -L -n|grep $ip|wc -l` -lt 1 ]
then
iptables -I INPUT -s $ip -j DROP
echo "$ip is droped" >>/tmp/droplits_$(date +%F).log
fi
done
执行方式:
[root@web02 ~/duanyang]# sh 14.sh access_2010-12-8.log
考试题15:菜单自动化软件部署经典案例
综合实例:打印选择菜单,按照选择一键安装不同的Web服务。 示例菜单:
[root@oldboy scripts]# sh menu.sh
1.[install lamp]
2.[install lnmp]
3.[exit]
pls input the num you want:
-
要求:
1、当用户输入1 时,输出“start installing lamp.提示”然后执行/server/scripts/lamp.sh, 脚本内容输出"lamp is installed"后退出脚本,工作中就是正式lamp一键安装脚本;
2、当用户输入2时,输出“start installing lnmp.提示” 然后执行/server/scripts/lnmp.sh 输出"lnmp is installed"后退出脚本,工作中就是正式lnmp一键安装脚本;
3、当输入3 时,退出当前菜单及脚本;
4、当输入任何其它字符,给出提示“Input error”后退出脚本;
5、要对执行的脚本进行相关的条件判断,例如:脚本文件是否存在,是否可执行等判断, 尽量用上前面讲解的知识点。
- 脚本实现:
#!/bin/sh
path=/server/scripts #<==定义脚本路径。
[ ! -d "$path" ] && mkdir $path -p #<==条件表达式判断,如果目录不存在,则创建目录。
#menu
cat <<END #<==利用cat的命令打印选择菜单,这里也可以用select语句打印选择菜单。
1.[install lamp]
2.[install lnmp]
3.[exit]
pls input the num you want:
END
read num #<==接收用户选择的数字。
expr $num + 1 &>/dev/null #<==判断是否为整数。
[ $? -ne 0 ] && { #<==根据返回值进行判断。
echo "the num you input must be {1|2|3}"
exit 1
}
[ $num -eq 1 ] && {
echo "start installing lamp."
sleep 2;
[ -x "$path/lamp.sh" ] || { #<==判断脚本是否可执行,不可能执行给予提示。
echo "$path/lamp.sh does not exist or can not be exec."
exit 1
}
$path/lamp.sh #<==执行脚本安装脚本,工作中建议用source $path/lamp.sh替代,这里目的是练习-x的判断。
#source $path/lamp.sh #<==脚本中执行脚本,使用source比sh或者不加解释器等更好一些。
exit $?
}
[ $num -eq 2 ] && { #<==如果用户选择2,执行lnmp安装命令。
echo "start installing LNMP."
sleep 2;
[ -x "$path/lnmp.sh" ] || { #<==判断脚本是否可执行,不可能执行给予提示。
echo "$path/lnmp.sh does not exist or can not be exec."
exit 1
}
$path/lnmp.sh #<==执行脚本安装脚本,工作中建议用source $path/lamp.sh替代,这里目的是练习-x的判断。
#source $path/lnmp.sh #<==脚本中执行脚本,使用source比sh或者不加解释器等更好一些。
exit $?
}
[ $num -eq 3 ] && { #<==如果用户输入3,退出脚本。
echo bye.
exit 3
}
#这里有三种用户的输入不等于1或2或3的综合用法。
[[ ! $num =~ [1-3] ]] && { #<==[[]]的通配符匹配方法。
echo "the num you input must be {1|2|3}"
echo "Input ERROR"
exit 4
}
考试题16:批量检查多个网站地址是否正常
- 要求:
1、使用shell数组方法实现,检测策略尽量模拟用户访问。
2、每 10秒钟做一次所有的检测,无法访问的输出报警。
3、待检测的地址如下
http://blog.oldboyedu.com
http://www.baidu.com
http://oldboy.blog.51cto.com
http://10.0.0.7
- 脚本实现:
#!/bin/sh
[ -f /etc/init.d/functions ] && . /etc/init.d/functions
arr=(
http://blog.oldboyedu.com
http://www.baidu.com
http://oldboy.blog.51cto.com
http://10.0.0.7
)
usage(){
if [[ ! $1 =~ http://.* ]]
then
echo "Usage:$0 http://www.xx.com"
exit 1
fi
}
check_url(){
wget -q -o /dev/null --spider -T 15 --tries=2 $1 &>/dev/null
retval=$?
if [ $retval -eq 0 ]
then
action "$1 is ok." /bin/true
else
action "$1 is no." /bin/false
fi
}
piliang(){
for url in ${arr[*]}
do
usage $url
check_url $url
done
}
main(){
while true
do
piliang
echo ====================
sleep 5
done
}
main
考试题17-18:单词及字母去重排序案例
用shell处理以下内容
the squid project provides a number of resources to assist users design,implement and support squid installations. Please browse the documentation and support sections for more infomation,by oldboy training.
- 要求:
1、按单词出现频率降序排序(不低于3种方法)
2、按字母出现频率降序排序(不低于3种方法)
- 实现方法:
#(1)
方法1:
tr " ,." "\n" <oldboy.txt|sort|uniq -c|sort -rn
方法2:
tr " ,." "\n" <oldboy.txt|awk '{S[$1]++}END{for(k in S) print S[k],k}'|sort -rn
方法3:
awk -F "[, .]+" '{for(i=1;i<=NF;i++)S[$i]++}END{for(key in S) print S[key],key}' oldboy.txt|sort -rn
#(2)
方法1:
awk -F "" '{for(i=1;i<=NF;i++)array[$i]++}END{for(key in array)print array[key],key|"sort -nr"}' oldboy.txt
方法2:
grep -o "[^ ]" oldboy.txt|sort|uniq -c|sort -rn
方法3:
grep -o "[^ ]" oldboy.txt|awk '{S[$1]++}END{for(key in S)print S[key],key|"sort -rn"}'
考试题19:已知:/etc/hosts的内容为
192.168.1.11 oldboy11
192.168.1.21 oldboy21
192.168.1.31 oldboy31
请用shell脚本实现,怎么才能在输入IP后找到/etc/hosts里对应的唯一的hostname?
- 脚本实现:
#!/bin/bash
if [ $# -ne 1 ]
then
echo "Usage: $0 + IP"
exit 1
else
hostname=`awk -F "[ ]+" -vn=$1 '$1==n{print $2}' /etc/hosts`
if [ ${#hostname} -eq 0 ]
then
echo "not found $1 in /etc/hosts"
else
echo $hostname
fi
fi
执行方式:
[root@web02 ~/duanyang]# sh 19.sh 192.168.1.11
oldboy11
考试题20:老男孩交流群某人发问如下
上海@Danny(122504707)21:54:37
请教一个问题 cat oldboy.txt
192.168.1.1 /hello1/b.do?bb=4
192.168.1.2 /hello2/a.do?ha=3
192.168.1.3 /hello3/r.do?ha=4
如何显示成以下效果
192.168.1.1 b.do
192.168.1.2 a.do
192.168.1.3 r.do
- 脚本实现:
#!/bin/bash
array=(
"192.168.1.1 /hello1/b.do?bb=4"
"192.168.1.2 /hello2/a.do?ha=3"
"192.168.1.3 /hello3/r.do?ha=4"
)
for n in "${array[@]}"
do
echo $n|awk -F "[ /?]" '{print $1,$4}'
done
while read line
do
echo $line|awk -F "[ /?]" '{print $1,$4}'
done < 20.txt
链接:https://pan.baidu.com/s/13Yy-f0kF_kIB1Q_TU5aW5g
提取码:m27h
m/p/7dd2ad568a69)
- [](javascript:void(0);)