shell脚本

shell脚本基础

1.变量

1.1 什么是变量?

变量即可以变化的量

1.2 变量名称注意事项

  • 只能包含字母、数字、下划线,并且不能以数字开头
  • 不应该跟系统中已有的环境变量重名,尽量不要全部使用大写,尽量不要用“_”下划线开头
  • 最好做到见名知义
  • 不能使用程序中的保留字(语法),例如if、for等

1.3 变量类型

  • 字符型
  • 数值型
    • 整型(整数,没有小数点)
    • 浮点型(包括小数点,但不能说小数点就是浮点型)
  • 布尔型(只有true和force,判断)

1.4 变量操作

  • 设置变量
[root@localhost ~]# a=10
  • 引用变量
[root@localhost ~]# echo $a        //在变量前加$符号
10
  • 撤销变量(一般不用)
[root@localhost ~]# unset a
[root@localhost ~]# echo $a

单引号与双引号的区别

  • "" //双引号,弱引用,可以实现变量替换
  • '' //单引号,强引用,不完成变量替换(表示本身)

[root@localhost ~]# echo $a
10
[root@localhost ~]# echo "$a"
10
[root@localhost ~]# echo '$a'
$a
[root@localhost ~]# echo "\$a"          \是转义符号
$a

1.5 bash变量类型

  • 环境变量(全用大写)
[root@localhost ~]# echo $PATH
/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/root/bin
[root@localhost ~]# echo $HISTORY
1000
  • 本地变量(局部变量)
  • 位置变量
  • 特殊变量(bash内置的,用来保存某些特殊数据的变量,也称系统变量)

1.5.1 本地变量

VAR_NAME=VALUE      //本地变量,作用域为当前shell进程。对当前shell外的其它shell进程,包括当前shell的父shell、子shell进程均无效

local VAR_NAME=VALUE    //局部变量,作用域为当前代码段,常用于函数
[root@localhost ~]# a=10    
[root@localhost ~]# echo $a    //父进程内
10
[root@localhost ~]# bash    //bash进入了一个子进程
[root@localhost ~]# echo $a     //子进程内没有这个变量

[root@localhost ~]# a=20
[root@localhost ~]# echo $a     //子进程设置了这个变量
20
[root@localhost ~]# bash        //bash进入另一个孙进程
[root@localhost ~]# echo $a

[root@localhost ~]# exit    //退出
exit
[root@localhost ~]# echo $a   //子进程
20
[root@localhost ~]# exit    //退出
exit
[root@localhost ~]# echo $a   //父进程
10

1.5.2 环境变量

export VAR_NAME=VALUE   //作用域为当前shell进程及其子进程
[root@localhost ~]# aaa=200
[root@localhost ~]# export aaa=200
[root@localhost ~]# echo $aaa
200
[root@localhost ~]# bash
[root@localhost ~]# echo $aaa
200
[root@localhost ~]# bash
[root@localhost ~]# echo $aaa
200
[root@localhost ~]# 
//export环境变量只作用于当前进程和其子进程
//不能作用于当前进程的父进程

1.5.3 位置变量

$1,$2,$3,....       //用来引用脚本的参数
    shift [num]         //位置变量使用完以后退出,后面的参数向前推进
[root@localhost ~]# vim test.sh
[root@localhost ~]# cat test.sh 
#!/bin/bash

echo $2 $1 $2 $3
[root@localhost ~]# chmod +x test.sh
[root@localhost ~]# ./test.sh 1 2 3 4
2 1 2 3

1.5.4 特殊变量

$#      //是传给脚本的参数个数
[root@localhost ~]# vim test.sh
[root@localhost ~]# cat test.sh
#!/bin/bash

echo $#
[root@localhost ~]# ./test.sh 1 2 3 4 5 6 3 2 4
9


$0      //是脚本本身的名字
[root@localhost ~]# vim test.sh
[root@localhost ~]# cat test.sh
#!/bin/bash

echo $0
[root@localhost ~]# ./test.sh
./test.sh
[root@localhost ~]# /bin/bash test.sh
test.sh


$!      //是shell最后运行的后台Process的PID

$@      //是传给脚本的所有参数的列表
[root@localhost ~]# vim test.sh
[root@localhost ~]# cat test.sh
#!/bin/bash

echo $@
[root@localhost ~]# ./test.sh 1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8


$*     //是以一个单字符串显示所有向脚本传递的参数,与位置变量不同,参数可超过9个(平常用这个)
[root@localhost ~]# vim test.sh
[root@localhost ~]# cat test.sh
#!/bin/bash

echo $*
[root@localhost ~]# ./test.sh 1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8


$$      //是脚本运行的当前进程ID号
$?      //是显示上条命令的退出状态,0表示没有错误,其他表示有错误

1.5.5 bash内建环境变量

PATH
SHELL
UID(用户ID)
HISTSIZE
HOME(家目录)
PWD(当前路径)
HISTFILE
PS1

1.5.6 只读变量(常量)

readonly VAR_NAME=VALUE     //不能修改值,不能销毁,只能等shell进程终止时随之消亡
[root@localhost ~]# readonly a=10
[root@localhost ~]# echo $a
10
[root@localhost ~]# a=20
bash: a: readonly variable
[root@localhost ~]# echo $a
10

2. 脚本基础

2.1 什么是脚本?

按实际需要,结合命令流程控制机制实现的源程序。说白点就是命令的堆砌。

2.2 程序返回值

程序执行以后有两类返回值:

  • 程序执行的结果
  • 程序状态返回代码(0-255)
    • 0:正确执行
    • 1-255:错误执行,1、2(没有找到该目录和文件)、127(没有找到该命令)系统预留,有特殊意义

2.3 脚本测试

(一定要在最小化上面执行,不能在图形化上执行。在最小化上能执行那么其他所有主机上都可执行,具备通用性)

bash如何测试脚本是否有错误?报错后如何排查?

bash -n scriptname      //检查脚本是否有语法错误
bash -x scriptname      //单步执行,检查脚本错在哪里(常用)

2.4 写脚本注意事项

  • 禁止将未成功执行过的代码直接写进脚本(开两个终端,在这个终端中一条命令可以执行成功了,再写入另一个终端的脚本里)
  • 脚本中的命令一定要用绝对路径
  • 最后要恢复null快照再把脚本执行看是否有问题

2.5 shell算术运算

+(加)  -(减)  *(乘)  /(除)   **乘方(**2——二次方,**3——三次方)

1、let C=$A+$B         //let 算术运算表达式
[root@localhost ~]# vim test.sh 
[root@localhost ~]# cat test.sh 
#!/bin/bash

a=30
b=20

let c=$a-$b
echo $c
[root@localhost ~]# ./test.sh 
10
[root@localhost ~]# vim test.sh 
[root@localhost ~]# cat test.sh 
#!/bin/bash

a=30
b=20

let c=$a-$b
echo $a - $b = $c
[root@localhost ~]# ./test.sh 
30 - 20 = 10



2、C=$[$A+$B]          //$[算术运算表达式]
[root@localhost ~]# vim test.sh 
[root@localhost ~]# cat test.sh 
#!/bin/bash

a=30
b=20

c=$[$a-$b]
echo $a - $b = $c
[root@localhost ~]# ./test.sh 
30 - 20 = 10



3、C=$(($A+$B))         //$((算术运算表达式))
[root@localhost ~]# vim test.sh 
[root@localhost ~]# cat test.sh 
#!/bin/bash

a=30
b=20

c=$(($a-$b))
echo $a - $b = $c
[root@localhost ~]# ./test.sh 
30 - 20 = 10


4、C=`expr $A + $B`    //expr 算术运算表达式,表达式中各操作数及运算符之间要有空隔,而且要使用命令引用

2.6 命令间的逻辑关系

逻辑与:&&
    第一个条件为假时,第二个条件不用再判断,最终结果已经有
    第一个条件为真时,第二个条件必须得判断
逻辑或:||
    前一个命令的结果为真时,第二个命令就不执行
    前一个命令的结果为假时,第二个命令必须执行

3. bash条件判断

3.1 条件测试类型

  • 整数测试(=,不等于!=,<,>,<=,>=)
  • 字符测试(相同或不相同)
  • 文件测试(文件是否存在,文件类型和大小等)(只有一个对象判断——单目测试)

3.2 条件测试的表达式

[ expression ]
[[ expression ]]    //在字符测试中会用到
test expression

3.3 整数测试(双目——两个对象进行对比)

-eq     //测试两个整数是否相等(=)
-ne     //测试两个整数是否不等(!=)
-gt     //测试一个数是否大于另一个数(>)
-lt     //测试一个数是否小于另一个数(<)
-ge     //大于或等于(>=)
-le     //小于或等于(<=)
[root@localhost ~]# [ 2 -ne 2 ]      //-ne 不等于
[root@localhost ~]# echo $?
1          //不成立
[root@localhost ~]# [ 2 -lt 3 ]     //-lt 小于
[root@localhost ~]# echo $?
0        //成立

//也可以用这个方式测试,基本上不用,在单目中用这种方式
[root@localhost ~]# test 2 -le 3
[root@localhost ~]# echo $?      //判断是否成立
0

3.4 字符测试(判断字符串需要用引号)

==      //等值比较,检查==两边的内容是否一致,==两边都要有空格
!=      //检查两边内容是否不一致,不一致为真,一致为假
=~      //左侧字符串是否能够被右侧的PATTERN所匹配到。此表达式应用于双中括号[[]]中
-z "string"     //测试指定字符串是否为空,空则为真,不空则为假
-n "string"     //测试指定字符串是否不空,不空则为真,空则为假
[root@localhost ~]# [ 'abc' == 'abcd' ]
[root@localhost ~]# echo $?
1
[root@localhost ~]# [ "abc" == "abc" ]
[root@localhost ~]# echo $?
0

//.表示一个字符
[root@localhost ~]# [[ "abc" =~ ... ]]    //匹配三个字符
[root@localhost ~]# echo $?
0     //成立
[root@localhost ~]# [[ "abc" =~ .. ]]      //匹配两个字符
[root@localhost ~]# echo $? 
0      //成立
[root@localhost ~]# [[ "abc" =~ .... ]]    //匹配四个字符
[root@localhost ~]# echo $?
1      //不成立

//-z,判断是否为空,空为真(在数据库里null表示空是真空)
[root@localhost ~]# [ -z '' ]   //真空
[root@localhost ~]# echo $?
0      //成立
[root@localhost ~]# [ -z ' ' ]    //假空,有一个空字符
[root@localhost ~]# echo $?
1     //不成立

3.5 文件测试

//存在性测试:
    -e      //测试文件是否存在
//存在性及类别测试:
    -b      //测试文件是否为块设备文件
    -c      //测试文件是否为字符设备文件
    -f      //测试文件是否为普通文件(常用)
    -d      //测试指定路径是否为目录(常用)
    -h      //测试文件是否为符号链接文件
    -L      //测试文件是否为符号链接文件
    -p      //测试文件是否为命名管道文件
    -S      //测试文件是否为套接字文件
//文件权限测试:
    -r      //测试当前用户对指定文件是否有读权限
    -w      //测试当前用户对指定文件是否有写权限
    -x      //测试当前用户对指定文件是否有执行权限
//文件特殊权限测试:
    -g      //测试文件是否有sgid权限
    -u      //测试文件是否有suid权限
    -k      //测试文件是否有sticky权限 rwt——有sticky权限
//文件大小测试:
    -s      //测试文件是否非空(不空为真)(不能用来判断目录,只能判断文件)
//文件是否打开测试:
    -t fd   //fd表示的文件描述符是否已经打开且与某终端相关
//双目测试:
    file1 -ef file2     //测试file1与file2是否指向同一个设备上的相同inode,说白点就是两者是不是同一个文件
    file1 -nt file2     //测试file1是否比file2新(看时间)
    file1 -ot file2     //测试file1是否比file2旧
//无分类:
    -N      //测试文件自从上一次被读取之后是否被修改过(被修改为真)
    -O      //测试文件是否存在并且被当前用户拥有
    -G      //测试文件是否存在并且默认组是否为当前用户组

3.6 组合测试条件

-a      //与关系(相当于&&)
-o      //或关系(相当于||)
!       //非关系(取反not)

//给脚本传的参数只能是两个或三个
[ $# -gt 1 -a $# -le 3 ]      //-gt大于,-le小于等于
[ $# -gt 1 ] && [ $# -le 3 ]

3.7 条件判断,控制结构(判断)

3.7.1 单分支if语句

if 判断条件; then
    statement1
    statement2
    ......
fi

3.7.2 双分支if语句

if 判断条件; then
    statement1
    statement2
    ......
else             //否则
    statement3
    statement4
    ......
fi

3.7.3 多分支if语句

if 判断条件1; then
    statement1
    statement2
    ......
elif 判断条件2; then
    statement3
    statement4
    ......
else
    statement5
    statement6
    ......
fi

4. 分支选择(匹配)

case $变量名 in            
value1)                
    statement                
    ...                
    ;;                //value-值,直接匹配到value1或者value2或者*
value2)                
    statement                
    ...                
    ;;            
*)                
    statement                
    ...                
    ;;      //;;表示结束  
esac

//case支持glob风格的通配符:
    *           //任意长度任意字符
    ?           //任意单个字符
    []          //指字范围内的任意单个字符
    abc|bcd     //abc或bcd

5. 循环语句

循环语句通常需要有一个进入条件和一个退出条件。

(没有进入和退出条件就成死循环一直循环直到资源耗尽死机)

5.1 for循环

for循环当列表不为空时进入循环,否则退出循环

//第一种方式
for 变量 in 列表; do
    循环体
done
//第二种方式
for ((expr1;expr2;expr3))
{
    循环体
}
//第三种方式
for (( expr1 ; expr2 ; expr3 ));do
    循环体
done

expr1   //用于指定初始条件,给控制变量一个初始值
expr2   //判定什么时候退出循环
expr3   //修正expr1指定的变量的值

//如何生成列表:
    {1..100}
    seq [起始数] [步进长度] 结束数
[root@localhost ~]# seq 10     //seq取数字
1
2
3
4
5
6
7
8
9
10
[root@localhost ~]# seq 2 10    //从2开始取
2
3
4
5
6
7
8
9
10
[root@localhost ~]# seq 1 2 10   //从1开始取,隔两个取一个
1
3
5
7
9
[root@localhost ~]# seq 2 2 10    //从2开始取,隔两个取一个
2
4
6
8
10

$1  //i++ 以前面为基础一直加1,i--以前面为基础一直减1

5.2 while循环

while循环适用于循环次数未知的场景(不知道要循环多少次),注意要有退出条件。
条件满足时进入循环,条件不满足了退出循环。

5.2.1 while循环正常用法

while 条件; do
    statement
    ...
done

//示例
[root@localhost ~]# chmod +x test.sh
[root@localhost ~]# cat test.sh 
#!/bin/bash
i=1

while [ $i -le 10 ];do
    echo $i
    echo ===
    let i++
done

5.2.2 while循环特殊用法

#while循环特殊用法一:死循环
while :;do
    statement
    ...
done

[root@localhost ~]# vim test.sh
[root@localhost ~]# cat test.sh 
#!/bin/bash
i=1

while :;do
    echo $i
    echo ===
    let i+=2     //i+2
    sleep 3     //休息3秒,这样看得清楚
done


[root@localhost ~]# ./test.sh 
1
===
3
===
5
===
7
===
^C
[root@localhost ~]# cat test.sh 
#!/bin/bash
i=1

while :;do
    echo $i
    echo ===
    let i+=2
    if [ $i -gt 100 ];then     //加入判断,大于100 就停
	break
    fi
done

//1-100打印
[root@localhost ~]# cat test.sh 
#!/bin/bash

i=1

while :;do
    if [ $i -gt 100 ];then
        break
    fi
    echo $i
    echo ===
    let i++
done

[root@localhost ~]# ./test.sh 
1
===
2
===
...
99
===
100
===



#这里的冒号可以改成任何非空值

while循环特殊用法二:逐行读取某文件,将值存入line变量中
while read line;do     //line行的意思
    statement
    ...
done < /path/to/somefile

示例:
写一个脚本,要求如下:

设定变量Fa的值为/etc/passwd
依次向/etc/passwd中的每个用户问好,并且说出对方的ID是什么。结果输出如下:
Hello,root,your UID is 0.
统计当前系统一个有多少个用户并输出

//执行
[root@localhost ~]# cat test.sh 
#!/bin/bash

Fa=/etc/passwd
count=0
while read line;do
    user=$(echo $line | awk -F: '{print $1}')
    uid=$(echo $line | awk -F: '{print $3}')
    echo "Hello $user, Your uid is $uid."
    let count++
done < $Fa

echo "当前系统一共有$count个用户"

[root@localhost ~]# ./test.sh 
Hello root, Your uid is 0.
Hello bin, Your uid is 1.
Hello daemon, Your uid is 2.
Hello adm, Your uid is 3.
Hello lp, Your uid is 4.
Hello sync, Your uid is 5.
Hello shutdown, Your uid is 6.
Hello halt, Your uid is 7.
Hello mail, Your uid is 8.
Hello operator, Your uid is 11.
Hello games, Your uid is 12.
Hello ftp, Your uid is 14.
Hello nobody, Your uid is 65534.
Hello dbus, Your uid is 81.
Hello systemd-coredump, Your uid is 999.
Hello systemd-resolve, Your uid is 193.
Hello tss, Your uid is 59.
Hello polkitd, Your uid is 998.
Hello unbound, Your uid is 997.
Hello sssd, Your uid is 996.
Hello sshd, Your uid is 74.
Hello apache, Your uid is 995.
当前系统一共有22个用户

5.3 until循环

条件不满足时进入循环,条件满足了退出循环。

until 条件; do
    statement
    ...
done

5.4 循环语句特殊情况

在循环语句中,有几种特别情况:

break [num]:提前退出循环。当循环语句中出现break时,将提前退出循环,不再执行循环后面的语句

continue [num]:提前结束本轮循环而进入下一轮循环。当循环语句执行到continue时,continue后面的语句将不再执行,提前进入下一轮循环

[root@localhost ~]# cat test.sh 
#!/bin/bash

i=0

while :;do
    let i++
    if [ $i -lt 10 ];then
	    continue     //如果i小于10的时候将continue,直接进入下一个循环进入i++
    elif [ $i -gt 30 ];then
        break    //如果i大于30的话将break退出循环
    fi
    echo $i
done

[root@localhost ~]# ./test.sh 
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//取偶数
[root@localhost ~]# cat test.sh 
#!/bin/bash

i=0

while :;do
    let i+=2
    if [ $i -lt 10 ];then
	    continue
    elif [ $i -gt 30 ];then
        break
    fi
    echo $i
done

[root@localhost ~]# ./test.sh 
10
12
14
16
18
20
22
24
26
28
30

6. 定义脚本退出状态码

//exit命令用于定义执行状态结果

exit #      //此处的#号是一个数字,其范围可以是0-255

如果脚本没有明确定义退出状态码,那么,最后执行的一条命令的退出码即为脚本的退出状态码

注意:脚本中一旦遇到exit命令,脚本会立即终止
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值