您的位置:首页 > 运维架构 > Shell

04.17 Shell高级编程

2017-07-12 09:14 671 查看

第一章 Shell环境变量

1. 什么是变量

变量就是用一个固定的字符串(也可能是字符数字等的组合),替代更多更复杂的内容,这个内容里可能还会包含变量和路径,字符串等其他内容。变量的定义是存在内存中。

x=1
y=2


2. 变量类型

a)环境变量/全局变量

可以在创建他们的Shell及其派生出来的字Shell中使用。环境变量又可以分为自定义环境变量和bash内置的环境变量。

b) 局部变量/普通变量

只能在创建他们的Shell函数或Shell脚本中使用,我们创建的一般是普通变量。

3. 和变量相关的配置文件

[root@Never-downtime scripts]# ll /etc/profile /etc/bashrc ~/.bashrc  ~/.bash_profile /etc/profile.d/
-rw-r-
4000
-r--  1 root root 2730 Apr 16 14:23 /etc/bashrc
-rw-r--r--  1 root root 1860 Mar 28 22:36 /etc/profile
-rw-r--r--. 1 root root  176 May 20  2009 /root/.bash_profile
-rw-r--r--. 1 root root  176 Sep 23  2004 /root/.bashrc


4. 设置全局变量(环境变量)的方法

(1)变量名大写
(2)使用export定义
(3)全局生效放在/etc/bashrc
(4)局部生效放在~/.bashrc


5. 变量文件开机启动顺序



6. 位置变量

$0获取当前执行的shell脚本的文件名,如果执行脚本带路径那么就包括脚本路径。

condrestart|try-restart)
rh_status_q || exit 0
restart
;;
*)
echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
exit 2
esac
exit $?


$n 获取当前执行的shell脚本的第n个参数值,n=1..9,当n为0时表示脚本的文件名,如果n大于9用大括号括起来{10},参数以空格隔开。

$# 获取当前执行的shell脚本后面接的参数的总个数。

7. 进程状态变量

$? 获取执行上一个指令的返回值(0位成功,非0为失败)

返回值含义
0表示运行成功
2权限拒绝
1~125表示运行失败,脚本命令、系统命令错误或参数传递错误
126找到该命令,但无法执行
127未找到要运行的命令
>128命令被系统强制结束

第二章 变量的数值运算

运算含义
++ –增加及减少,可前置也可放结尾
+ - ! ~一元的正好与符号,非,逻辑与位的取反
* / %乘法、除法、取余
< <= > >=比较符号
== !=相等、不相等
<< >>向左位移,向右位移
&位的AND
^位的异
|位的或
&&位的AND
||位的OR
?:条件表达式
= += -= *= /= %= &= ^= <<= >>= |=赋值运算符
**幂运算
[root@CentOS7 ~]# ((a=1+2**3-4%3))
[root@CentOS7 ~]# echo $a
8
[root@CentOS7 ~]# b=$((1+2**3-4%3))
[root@CentOS7 ~]# echo $b
8
[root@CentOS7 ~]# echo $((1+2**3-4%3))
8


1. 【$(())】

同$(())
[root@Never-downtime tmp]# echo $[2+3]
5
[root@Never-downtime tmp]# echo $[2*3]
6


2. 数值判断

[root@CentOS7 ~]# echo $((4>2))
1
[root@CentOS7 ~]# echo $((4<2))
0


第三章 read读入

1. 功能说明

Read lines from a file into an array variable

read命令从标准输入中读取一行,并把输入行的每个字段的值指定给shell变量。

2. 选项参数

-p prompt 设置提示信息

-t timeout 设置输入超时时间,单位s。

[root@CentOS7 ~]# read -p "qing shu ru yige zhi:" a
qing shu ru yige zhi:3
[root@CentOS7 ~]# echo $a
3


3. 清楚赋值变量unset

[root@CentOS7 ~]# unset a
[root@CentOS7 ~]# echo $a


4. 实现一个加减乘除的计算器

[root@Never-downtime scripts]# vi read2.sh
#!/bin/bash
read -p "请输入2个值:" a b
echo "$a+$b=$(($a+$b))"
echo "$a-$b=$(($a-$b))"
echo "$a*$b=$(($a*$b))"
echo "$a/$b=$(($a/$b))"

[root@Never-downtime scripts]# sh read2.sh
请输入2个值:6 2
6+2=8
6-2=4
6*2=12
6/2=3

[root@Never-downtime scripts]# sh read2.sh
请输入2个值:2 8
2+8=10
2-8=-6
2*8=16
2/8=0


第四章 测试表达式

1. 常用文件测试操作符号

常用文件测试操作符号说明
-f 文件,英文file文件存在且为普通文件则真,即测试表达式成立。
-d文件,英文directory文件存在且为目录文件则真,即测试表达式成立。
-s文件,英文size文件存在且为文件大小不为0则真,即测试表达式成立。
-e文件,英文exist文件存在则真,即测试表达式成立,只要有文件就行,区别-f
-r文件,英文read文件存在且可读则真,即测试表达式成立。
-w文件,英文write文件存在且可写则真,即测试表达式成立。
-x文件,英文executable文件存在且可执行则真,即测试表达式成立。
-L文件,英文link文件存在且为链接文件则真,即测试表达式成立。
f1 -nt f2,英文newer than文件f1比文件f2新则真,即测试表达式成立,根据文件修改时间计算。
f1 -ot f2,英文older than文件f1比文件f2旧则真,即测试表达式成立,根据文件修改时间计算。
2. 字符串测试操作符

字符串测试操作符的作用:比较两个字符串是否相同、字符串长度是否为零,字符串是否为NULL。Bash区分零长度字符串和空字符串。

常用字符串测试操作符说明
-z “字符串”若串长度为0则真,-z理解为zero
-n “字符串”若串长度不为0则真,-n理解为no zero
“串1” = “串2”若串1等于串2则真,可以使用”==”代替”=”
“串1” != “串2”若串1不等于串2则真,但不能使用”!==”代替”!=”
特别注意,以上表格中的字符串测试操作符号务必要用”“引起来。[-z “$string”]字符串比较,比较符号两端最好有空格,参考系统脚本。

[ “$password” = “john” ]中[ “$password” = “john” ]之间必须存在空格。

引号可以不加,遇到空格必须加,但是推荐使用引号!

3. 整错错误示例

正确中括号、引号、空格[ “abc” = “abc” ] && echo “eq”
错误中括号、引号[ “abc”=”ac” ] && echo “eq”
错误中括号[ abc=bc ] && echo “eq”
4. 整数二元比较操作符

在[]中使用的比较符说明
-eqequal等于
-nenot equal大等于
-gtgreater than 大于
-gegreater equal 大于等于
-ltless than 小于
-leless equal 小于等于
5. 逻辑操作符

在[]中使用的逻辑操作符说明
-a与and,两端都为真则真
-o或or,有一个真就真
非not,相反则为真
小结:多个[]之间的逻辑操作符是&&或||,&&前面成功执行后面,||前面不成功执行后面。

综合实战案例:开发shell脚本分别实现以脚本传参以及read读入的方式比较2个整数大小。用条件表达式(禁止if)进行判断并以屏幕输出的方式提醒用户比较结果。注意:一共是开发2个脚本。当用脚本传参以及read读入的方式需要对变量是否为数字、并且传参个数不对给予提示。

#!/bin/bash
a=$1
b=$2

[ "$#" -ne 2 ] && echo "警告:这里必须输入两个字符" && exit 1
zimu1=`echo $1|sed 's#[0-9]##g'`
zimu2=`echo $2|sed 's#[0-9]##g'`

[ -n "${zimu1}" ] && echo "警告:第一个字符类型必须是数字" && exit 2
[ -n "${zimu2}" ] && echo "警告:第二个字符类型必须是数字" && exit 2

[ $a -eq $b ] && echo "$a = $b"
[ $a -gt $b ] && echo "$a > $b"
[ $a -lt $b ] && echo "$a < $b"


read读入

read -t 5 -p "提示:请输入2个字符" a b

[ -z "$a" -o -z "$b" ] && echo "必须是两个字数" && exit 1

replace1=$(echo $a |sed "s#[0-9]##g")
replace2=$(echo $b |sed "s#[0-9]##g")

[ -n "$replace1" ] && echo "警告:第一个字符类型必须是数字" && exit 2
[ -n "$replace2" ] && echo "警告:第二个字符类型必须是数字" && exit 2

[ "$a" -eq "$b" ] && echo "$a = $b" && exit
[ "$a" -gt "$b" ] && echo "$a > $b" && exit
[ "$a" -lt "$b" ] && echo "$a < $b" && exit


第五章 if条件语句

1. if单分支条件句语

if  [条件]
then
指令
if
或
if  [条件];then
指令
fi
提示:分号相当于命令换行,上面两种语法等同。

特殊写法if [ -f "$file" ];then echo 1 ;fi 相当于[ -f "$file" ] && echo 1


[root@Never-downtime scripts]# vi size_Comparison1.sh
#!/bin/bash
a=$1
b=$2

if [ "$#" -ne "2" ]
then
echo "警告:这里必须输入两个字符" && exit 1
fi

replace1=$(echo $1 |sed "s#[0-9]##g")
replace2=$(echo $2 |sed "s#[0-9]##g")

if [ -n "$replace1" ]
then
echo "警告:第一个字符类型必须是数字" && exit 2
fi

if [ -n "$replace2" ]
then
echo "警告:第二个字符类型必须是数字" && exit 2
fi

if [ "$a" -eq "$b" ]
then
echo "$a = $b"
fi

if [ "$a" -gt "$b" ]
then
echo "$a > $b"
fi

if [ "$a" -lt "$b" ]
then
echo "$a < $b"
fi


2. if双分支条件语句

if  [ 条件 ]
then
指令1
else
指令2
fi


3. 判断是否为文件

[root@Never-downtime scripts]# vi iftuo.sh
#!/bin/bash
if [ -f "read1.sh" ]
then
echo 0
else
echo 1
fi
相当于[ -f "read1.sh" ] && echo 0 || echo 1


4. if多分支语句

if [ 条件1 ]
then
指令1
elif [ 条件2 ]
then
指令2
elif [ 条件3 ]
then
指令3
elif [ 条件4 ]
then
指令4
....
else
指令n
fi


5. 判断两个数字的大小

23 if [ "$a" -eq "$b" ]
24   then
25     echo "$a=$b"
26
27 elif [ "$a" -gt "$b" ]
28   then
29     echo "$a>$b"
30
31 else [ "$a" -lt "$b" ]
32     echo "$a<$b"
33 fi


6. if语句总结

分支语法结果
单分支if then fi一个条件一个结果
双分支if then else fi一个条件两个结果
多分支if then elif elif else fi多个条件多个结果

第六章 for循环结构语法

for 变量名 in 变量取值列表
do
指令.....
done


1. 示例循环10次

[root@Never-downtime scripts]# for i in {00..10}
> do
> echo $i
> done
00
01
02
03
04
05
06
07
08
09
10
[root@Never-downtime scripts]# for i in {00..10}; do echo $i; done


2. 小结

in后面的字符个数控制循环的次数
将i后面的字符分别赋值给变量i,在do后面可以引用变量i也可以不用
以空格区分,[root@oldboyedu-35 data]# for i in {1..10};do useradd test$i;done


第七章 获取随机数的几种方法

1. 通过系统变量$RANDON

[root@CentOS7 ~]#  echo $RANDOM
9820
[root@CentOS7 ~]#  echo $RANDOM
1468
[root@CentOS7 ~]# echo $RANDOM
14955


2. 通过openssl产生

[root@CentOS7 ~]# openssl rand -base64 8|md5sum
b025e02d40e910f8a9cd36f98ff363d7  -
[root@CentOS7 ~]# openssl rand -base64 8|md5sum
6a9619eab8009f0ca5f56a82475c2077  -


3. echo $(date +%N)

[root@CentOS7 ~]# echo $(date +%N)
216956783
[root@CentOS7 ~]# echo $(date +%N)
349010758
[root@CentOS7 ~]# echo $(date +%N)
773229182


4. urandom

[root@CentOS7 ~]# head /dev/urandom |cksum
3017719303 1809
[root@CentOS7 ~]# head /dev/urandom |cksum
1901402952 1933
[root@CentOS7 ~]# head /dev/urandom |cksum
3354308804 2453


5. uuidgen码有硬件、时间、机器当前运行信息等组成,理论上在互联网中唯一

[root@CentOS7 ~]# uuidgen
93841c31-0664-462d-8a28-a406b3791bb0
[root@CentOS7 ~]# uuidgen
bfb2487f-5cbd-4daa-b847-9870920a706c
[root@CentOS7 ~]# uuidgen
cce1d3c9-041a-4cd8-a3a0-1b399fee4c51


第八章 case结构条件句语法

case “字符串标量” in
值1)
指令1
;;
值2)
指令1
;;
*)
指令
esac
#注:case语句相当于一个if的多分支结构语句


1. case语句小结

case语句就相当于多分支的if语句。case语句的优势是更规范、易读。

case语句适合变量的值少,且为固定的数字或字符串集合。(1,2,3)或(start,stop,restart)。

系统服务启动脚本传参的判断多用case语句,多参考rpcbind/nfs/crond脚本。

结合示例:打印选择菜单,按照选择一键安装不同的web服务。
shmenu.sh
1.[install lamp]
2.[install lnmp]
3.[exit]
pls input the num you want:

要求:
1、当用户输入1时,输出“startinstalling lamp提示”。然后执行/servsr/scripts/lamp.sh。脚本内容输出“lampis installed”后退出脚本, lamp一键安装脚本。
2、当用户输入2时,输出“startinstalling lnmp提示”,然后执行/server/scripts/lnmp.sh。脚本内容输出“lnmpis installed”后退出脚本, lnmp一键安装脚本。
3、当输入3时,退出当前菜单及脚本。
4、当输入任何其它字符,给出提示“Input error”后退出脚本。
5、要对执行的脚本进行相关的条件判断,例如:脚本文件是否存在,是否可执行等判断,尽量用上前面讲解的知识点。


[root@Never-downtime scripts]# vi case.sh
#!/bin/bash

cat<<EOP
本程序支持安装的服务:
1.安装LAMP服务
2.安装LNMP服务
3.exit 退出安装
EOP

read -p "请输入你的选择:" a
case $a in
1)
echo "startinstalling lamp"
lampScripts=/server/scripts/lamp.sh
[ -f $lampScripts ] && sh $lampScripts || exit 2
;;
2)
echo "startinstalling lnmp"
lnmpScripts=/server/scripts/lnmp.sh
[ -f $lnmpScripts ] && sh $lnmpScripts || exit 3
;;
3)
exit
;;
*)
echo "您的输入有误,请重新输入"
;;
esac


第九章 Linux色值 彩色字体值

echo -e "\033[30m 黑色字oldboy trainning \033[0m"
echo -e "\033[31m 红色字oldboy trainning \033[0m"
echo -e "\033[32m 绿色字oldboy trainning \033[0m"
echo -e "\033[33m 黄色字oldboy trainning \033[0m"
echo -e "\033[34m 蓝色字oldboy trainning \033[0m"
echo -e "\033[35m 紫色字oldboy trainning \033[0m"
echo -e "\033[36m 天蓝字oldboy trainning \033[0m"
echo -e "\033[37m 白色字oldboy trainning \033[0m"


第十章 Linux色值 彩底白字值

echo -e "\033[40;37m 黑底白字 welcome to old1boy\033[0m"
echo -e "\033[41;37m 红底白字 welcome to old2boy\033[0m"
echo -e "\033[42;37m 绿底白字 welcome to old3boy\033[0m"
echo -e "\033[43;37m 黄底白字 welcome to old4boy\033[0m"
echo -e "\033[44;37m 蓝底白字 welcome to old5boy\033[0m"
echo -e "\033[45;37m 紫底白字 welcome to old6boy\033[0m"
echo -e "\033[46;37m 天蓝白字 welcome to old7boy\033[0m"
echo -e "\033[47;30m 白底黑字 welcome to old8boy\033[0m"


第十一章 while条件句

while 条件
do
指令
done


[root@Never-downtime ~]# vi while.sh
#!/bin/bash

while true
do
uptime >>/tmp/uptime.log
sleep 1
done

[root@Never-downtime ~]# tailf /tmp/uptime.log
09:29:04 up  2:00,  4 users,  load average: 0.00, 0.01, 0.04
09:29:06 up  2:00,  4 users,  load average: 0.00, 0.01, 0.04
09:29:08 up  2:00,  4 users,  load average: 0.00, 0.01, 0.04
09:29:10 up  2:00,  4 users,  load average: 0.00, 0.01, 0.04


第十二章 各种语句小结

1. while循环

while循环的特长是执行守护进程以及我们希望循环不退出持续执行,用于频率小于1分钟循环处理(crond),其他的while循环几乎都可以被for循环替代。

2. case语句

case语句可以被if语句替换,一般在系统启动脚本传入少量固定规则字符串用case语句,其他普通判断多用if。


3. until循环

until执行死循环,表达式成立后结束循环。

until [ $# -eq 0 ]
do
echo $*
shift
done
1 2 3 4 5
2 3 4 5
3 4 5
4 5
5


第十三章 循环控制语句

continue 跳过当次循环
break    跳过整个循环
exit     退出脚本
return   退出函数


1. break

break脚本:

[root@Never-downtime scripts]# vi break.sh
#!/bin/bash
for a in {01..10}
do
if [ $a -eq 5 ]
then
break
else
echo $a
fi
done

echo "我猜你现在在看这几行字..."


输出结果:
[root@Never-downtime scripts]# sh break.sh
01
02
03
04
我猜你现在在看这几行字...


2. exit

exit脚本:

#!/bin/bash
for a in {01..10}
do
if [ $a -eq 5 ]
then
exit
else
echo $a
fi
done

echo "我猜你现在在看这几行字..."


输出结果:

[root@Never-downtime scripts]# sh break.sh
01
02
03
04


3. continue

continue脚本:

#!/bin/bash
for a in {01..10}
do
if [ $a -eq 5 ]
then
continue
else
echo $a
fi
done

echo "我猜你现在在看这几行字..."


输出内容:

[root@Never-downtime scripts]# sh break.sh
01
02
03
04
06
07
08
09
10
我猜你现在在看这几行字...
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息