shell脚本能做什么

作用:简化操作步骤,提高效率,减少人为干预,减少系统故障

1.自动化的完成基础配置

2.自动化安装程序

3.自动化调整配置文件

4.自动化部署业务

5.自动化定期备份恢复程序

6.自动化信息的采集(zabbix+shell)

7.自动化日志收集(ELK)

8、自动化扩容、缩容(zabbix+shell)

shell 技能

变量 自定义变量 系统环境变量 预先定义变量 位置参数变量 内置变量

       条件判断 if else
       循环语句 for while
       流程控制 case
       函数 function
       数组
       正则表达式
       案例

变量

定义变量

variable=value

variable='value'

variable="value"

如果变量的内容是数字,那么可以不加引号;如果真的需要原样输出就加单引号;其他没有特别要求的字符串等最好都加上双引号,定义变量时加双引号是最常见的使用场景。

使用变量

使用一个定义过的变量,只要在变量名前面加美元符号$即可,如:

author="严长生"

echo $author

echo ${author}

将命令的结果赋值给变量

Shell 也支持将命令的执行结果赋值给变量,常见的有以下两种方式:

variable=`command`

variable=$(command)

删除变量

使用 unset 命令可以删除变量。语法:

unset variable_name

特殊变量列表

变量含义
$0当前脚本的文件名
$n传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2。
$#传递给脚本或函数的参数个数。
$*传递给脚本或函数的所有参数。
$@传递给脚本或函数的所有参数。被双引号(" ")包含时,与 $* 稍有不同,下面将会讲到。
$?上个命令的退出状态,或函数的返回值。
$$当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID。
#!/bin/bash

echo "File Name: $0"

echo "First Parameter : $1"

echo "First Parameter : $2"

echo "Quoted Values: $@"

echo "Quoted Values: $*"

echo "Total Number of Parameters : $#"
sh 1.sh skyhu huqing wuxi

File Name: 1.sh

First Parameter : skyhu

First Parameter : huqing

Quoted Values: skyhu huqing wuxi

Quoted Values: skyhu huqing wuxi

Total Number of Parameters : 3

变量赋值方式

1、显示赋值 (变量名=变量值)today=$(date +%F)

2、read 从键盘读入变量值

read 变量名  #变量名赋值给内置变量 REPLY  ehco $REPLY

read -p "提示信息:" 变量名

read -t 5 -p "提示信息" 变量名

read -n2 -p 变量名 能输入两个变量退出

赋值运算

1、整数运算expr expr $num1 + $num2 注意当中有空格    例:sum=`expr 2 + 2`

2、整数运算 $(()) + - * / %        例:echo $((a+b))

3、整数运算 $[] + - * / %          例:echo $[a+b]

4、整数运算let let + - * / %       例:let sum=2+3 echo $sum

5、小数运算 bc    例:sum=$(echo "$sum+$n"|bc)

算术运算符列表

运算符说明举例 a=10 b=20
+加法expr $a + $b 结果为 30。
-减法expr $a - $b 结果为 10。
*乘法expr $a \* $b 结果为  200。
/除法expr $b / $a 结果为 2。
%取余expr $b % $a 结果为 0。
=赋值a=$b 将把变量 b 的值赋给 a。
==相等。用于比较两个数字,相同则返回 true。[ $a == $b ] 返回 false。
!=不相等。用于比较两个数字,不相同则返回 true。[ $a != $b ] 返回 true。

关系运算符

关系运算符只支持数字,不支持字符串,除非字符串的值是数字。

关系运算符列表

运算符说明举例 a=10 b=20
-eq检测两个数是否相等,相等返回 true。[ $a -eq $b ] 返回 true。
-ne检测两个数是否相等,不相等返回 true。[ $a -ne $b ] 返回 true。
-gt检测左边的数是否大于右边的,如果是,则返回 true。[ $a -gt $b ] 返回 false。
-lt检测左边的数是否小于右边的,如果是,则返回 true。[ $a -lt $b ] 返回 true。
-ge检测左边的数是否大等于右边的,如果是,则返回 true。[ $a -ge $b ] 返回 false。
-le检测左边的数是否小于等于右边的,如果是,则返回 true。[ $a -le $b ] 返回 true。

布尔运算符列表

运算符说明举例 a=10  b=20
!非运算,表达式为 true 则返回 false,否则返回 true。[ ! false ] 返回 true。
-o或运算,有一个表达式为 true 则返回 true。[ $a -lt 20 -o $b -gt 100 ] 返回 true。
-a与运算,两个表达式都为 true 才返回 true。[ $a -lt 20 -a $b -gt 100 ] 返回 false。

字符串运算符列表

运算符说明举例 a=abc  b=def
=检测两个字符串是否相等,相等返回 true。[ $a = $b ] 返回 false。
!=检测两个字符串是否相等,不相等返回 true。[ $a != $b ] 返回 true。
-z检测字符串长度是否为0,为0返回 true。[ -z $a ] 返回 false。
-n检测字符串长度是否为0,不为0返回 true。[ -z $a ] 返回 true。
str检测字符串是否为空,不为空返回 true。[ $a ] 返回 true。

文件测试运算符

文件测试运算符用于检测 Unix 文件的各种属性。

文件测试运算符列表

操作符说明举例
-b file检测文件是否是块设备文件,如果是,则返回 true。[ -b $file ] 返回 false。
-c file检测文件是否是字符设备文件,如果是,则返回 true。[ -c $file ] 返回 false。
-d file检测文件是否是目录,如果是,则返回 true。[ -d $file ] 返回 false。
-f file检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。[ -f $file ] 返回 true。
-g file检测文件是否设置了 SGID 位,如果是,则返回 true。[ -g $file ] 返回 false。
-k file检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。[ -k $file ] 返回 false。
-p file检测文件是否是具名管道,如果是,则返回 true。[ -p $file ] 返回 false。
-u file检测文件是否设置了 SUID 位,如果是,则返回 true。[ -u $file ] 返回 false。
-r file检测文件是否可读,如果是,则返回 true。[ -r $file ] 返回 true。
-w file检测文件是否可写,如果是,则返回 true。[ -w $file ] 返回 true。
-x file检测文件是否可执行,如果是,则返回 true。[ -x $file ] 返回 true。
-s file检测文件是否为空(文件大小是否大于0),不为空返回 true。[ -s $file ] 返回 true。
-e file检测文件(包括目录)是否存在,如果是,则返回 true。[ -e $file ] 返回 true。

Shell字符串

获取字符串长度

string="abcd"

echo ${#string} #输出 4

提取子字符串

string="alibaba is a great company"

echo ${string:1:4} #输出liba  第一字母后面四个字母

数组

定义数组

array_name=(value0 value1 value2 value3)

单独定义各个数组分量

array_name[0]=value0

array_name[1]=value1

array_name[2]=value2

读取数组

读取数组元素值的一般格式是:

${array_name[index]}

例如:

valuen=${array_name[2]}

使用@ 或 * 可以获取数组中的所有元素,例如:

${array_name[*]}

${array_name[@]}

获取数组的长度

获取数组长度的方法与获取字符串长度的方法相同,例如:

取得数组元素的个数

length=${#array_name[@]}

或者

length=${#array_name[*]}

取得数组单个元素的长度

lengthn=${#array_name[n]}

if语句

if else语句

if 语句通过关系运算符判断表达式的真假来决定执行哪个分支。Shell 有三种 if ... else 语句:

  • if ... fi 语句;
  • if ... else ... fi 语句;
  • if ... elif ... else ... fi 语句。

if ... else 语句的语法:

if [ expression ]

then

Statement(s) to be executed if expression is true

fi

注意:expression 和方括号([ ])之间必须有空格,否则会有语法错误。

if ... else 语句也可以写成一行,以命令的方式来运行,像这样:

if test $[2*3] -eq $[1+5]; then echo 'The two numbers are equal!'; fi;

if ... else ... fi 语句

#!/bin/sh

a=10

b=20

if [ $a == $b ]

then

   echo "a is equal to b"

else

   echo "a is not equal to b"

fi

if ... elif ... fi 语句

哪一个 expression 的值为 true,就执行哪个 expression 后面的语句;如果都为 false,那么不执行任何语句。

#!/bin/sh

a=10

b=20

if [ $a == $b ]

then

echo "a is equal to b"

elif [ $a -gt $b ]

then

echo "a is greater than b"

elif [ $a -lt $b ]

then

echo "a is less than b"

else

echo "None of the condition met"

fi

运行结果:

a is less than b

Shell test命令

Shell中的 test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。

数值测试

num1=100

num2=100

if test $[num1] -eq $[num2]

then

    echo 'The two numbers are equal!'

else

    echo 'The two numbers are not equal!'

fi

字符串测试

num1=100

num2=100

if test num1=num2

then

    echo 'The two strings are equal!'

else

    echo 'The two strings are not equal!'

fi

文件测试

if test -e ./bash

then

    echo 'The file already exists!'

else

    echo 'The file does not exists!'

fi

另外,Shell还提供了与( ! )、或( -o )、非( -a )三个逻辑操作符用于将测试条件连接起来,其优先级为:"!"最高,"-a"次之,"-o"最低。例如:

if test -e ./notFile -o ./bash

then

    echo 'One file exists at least!'

else

    echo 'Both dose not exists!'

fi

case esac语句

case 语句匹配一个值或一个模式,如果匹配成功,执行相匹配的命令。case语句格式如下:

case 值 in

模式1)

command1

command2

command3

;;

模式2)

command1

command2

command3

;;

*)

command1

command2

command3

;;

esac

例:

echo 'Input a number between 1 to 4'

echo 'Your number is:\c'

read aNum

case $aNum in

    1)  echo 'You select 1'

    ;;

    2)  echo 'You select 2'

    ;;

    3)  echo 'You select 3'

    ;;

    4)  echo 'You select 4'

    ;;

    *)  echo 'You do not select a number between 1 to 4'

    ;;

esac

for循环

for循环一般格式为:

for 变量 in 列表

do

command1

command2

...

commandN

done

列表是一组值(数字、字符串等)组成的序列,每个值通过空格分隔。每循环一次,就将列表中的下一个值赋给变量。

in 列表是可选的,如果不用它,for 循环使用命令行的位置参数。

关于列表的生成方法,如下:

1、直接给出列表

2、整数列表:

(a){start...end}                {1 2 3 4 5}

(b)seq start end           seq 1 10

3、返回列表的命令

    $(COMMAND)

4、使用glob通配符如:

      *.sh

5、变量引用

$i,$*

例如, 输入正整数n,计算1+...+n的和:

#!/bin/bash

#定义变量

sum=0

read -p "请输入一个正整数:" num

#判断num是否是正整数

if [[ $num =~ ^[[:digit:]]+$ ]];then

#   若是,当i在1-$num时,输出sum值

    for i in `seq 1 $num`;do

        let sum+=$i

    done

        echo "sum=$sum"

#若不是,提示输出正整数

else

    echo "请输入一个正整数!"

fi

删除变量

unset i sum num

while循环

while循环用于不断执行一系列命令,也用于从输入文件中读取数据;命令通常为测试条件。其格式为:

while command

do

Statement(s) to be executed if command is true

done

命令执行完毕,控制返回循环顶部,从头开始直至测试条件为假。

以下是一个基本的while循环,测试条件是:如果COUNTER小于5,那么返回 true。COUNTER从0开始,每次循环处理时,COUNTER加1。运行上述脚本,返回数字1到5,然后终止。

COUNTER=0

while [ $COUNTER -lt 5 ]

do

    COUNTER='expr $COUNTER+1'

    echo $COUNTER

done

从输入文件中读取数据

#/bin/bash

####通过文件批量创建用户密码#######

while read user

  do

  u=$(echo $user|awk '{print $1}')

  p=$(echo $user|awk '{print $2}')

id $u  &>/dev/null

if [ $? -ne 0 ]; then

useradd $u &&

echo "$p"|passwd --stdin $u &>/dev/null

echo "$u is OK"

else

echo "useradd $u is already exists"

fi

done <user.tt

until循环

until 循环执行一系列命令直至条件为 true 时停止。until 循环与 while 循环在处理方式上刚好相反。一般while循环优于until循环,但在某些时候,也只是极少数情况下,until 循环更加有用。

until 循环格式为:

until command

do

Statement(s) to be executed until command is true

done

command 一般为条件表达式,如果返回值为 false,则继续执行循环体内的语句,否则跳出循环。

#!/bin/bash

a=0

until [ ! $a -lt 10 ]

do

   echo $a

   a=`expr $a + 1`

done

break和continue命令

在循环过程中,有时候需要在未达到循环结束条件时强制跳出循环,像大多数编程语言一样,Shell也使用 break 和 continue 来跳出循环。

break命令

break命令允许跳出所有循环(终止执行后面的所有循环)。

下面的例子中,脚本进入死循环直至用户输入数字大于5。要跳出这个循环,返回到shell提示符下,就要使用break命令。

#!/bin/bash

while :

do

    echo -n "Input a number between 1 to 5: "

    read aNum

    case $aNum in

        1|2|3|4|5) echo "Your number is $aNum!"

        ;;

        *) echo "You do not select a number between 1 to 5, game is over!"

            break

        ;;

    esac

done

在嵌套循环中,break 命令后面还可以跟一个整数,表示跳出第几层循环。例如

break n

表示跳出第 n 层循环。

continue命令

continue命令与break命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环。

#!/bin/bash

while :

do

    echo -n "Input a number between 1 to 5: "

    read aNum

    case $aNum in

        1|2|3|4|5) echo "Your number is $aNum!"

        ;;

        *) echo "You do not select a number between 1 to 5!"

            continue

            echo "Game is over!"

        ;;

    esac

done

Shell函数

函数可以让我们将一个复杂功能划分成若干模块,让程序结构更加清晰,代码重复利用率更高。像其他编程语言一样,Shell 也支持函数。Shell 函数必须先定义后使用。

Shell 函数的定义格式如下:

function_name () {

list of commands

[ return value ]

}

函数返回值,可以显式增加return语句;如果不加,会将最后一条命令运行结果作为返回值。

Shell 函数返回值只能是整数,一般用来表示函数执行成功与否,0表示成功,其他值表示失败。如果 return 其他数据,比如一个字符串,往往会得到错误提示:"numeric argument required"。

如果一定要让函数返回字符串,那么可以先定义一个变量,用来接收函数的计算结果,脚本在需要的时候访问这个变量来获得函数返回值。

调用函数只需要给出函数名,不需要加括号。

#/bin/bash

file=/etc/passwd

i=0

count (){

while read line

do

  let i++

done <$file

echo "$file is count $i"

}

echo "调用函数统计文本有多少行"

count

函数返回值

用于排查故障 

return 0

return 1

#/bin/bash

file=/etc/aaaaa

abc(){

if [ -f $file ];then

return 0

else

      return 1

fi

}

abc

test=$?

if [ $test -eq 0 ];then

  echo "$file 文件存在"

fi

if [ $test -eq 1 ];then

echo "$file 文件不存在"

fi

像删除变量一样,删除函数也可以使用 unset 命令,不过要加上 .f 选项,如下所示:

$unset .f function_name

函数参数

在Shell中,调用函数时可以向其传递参数。在函数体内部,通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数...

带参数的函数示例:

#!/bin/bash

funWithParam(){

    echo "The value of the first parameter is $1 !"

    echo "The value of the second parameter is $2 !"

    echo "The value of the tenth parameter is $10 !"

    echo "The value of the tenth parameter is ${10} !"

    echo "The value of the eleventh parameter is ${11} !"

    echo "The amount of the parameters is $# !"  # 参数个数

    echo "The string of the parameters is $* !"  # 传递给函数的所有参数

}

funWithParam 1 2 3 4 5 6 7 8 9 34 73

运行脚本:

The value of the first parameter is 1 !

The value of the second parameter is 2 !

The value of the tenth parameter is 10 !

The value of the tenth parameter is 34 !

The value of the eleventh parameter is 73 !

The amount of the parameters is 11 !

The string of the parameters is 1 2 3 4 5 6 7 8 9 34 73 !

注意,$10 不能获取第十个参数,代表第一个参数后面紧接着0,   获取第十个参数需要${10}。当n>=10时,需要使用${n}来获取参数。

$command >> file 2>&1   # stdout 和 stderr 合并后重定向到 file

$command 2 > file  #stderr 重定向到 file

全部可用的重定向命令列表

命令说明
command > file将输出重定向到 file。
command < file将输入重定向到 file。
command >> file将输出以追加的方式重定向到 file。
n > file将文件描述符为 n 的文件重定向到 file。
n >> file将文件描述符为 n 的文件以追加的方式重定向到 file。
n >& m将输出文件 m 和 n 合并。
n <& m将输入文件 m 和 n 合并。
<< tag将开始标记 tag 和结束标记 tag 之间的内容作为输入。

Here Document 目前没有统一的翻译,这里暂译为"嵌入文档"。Here Document 是 Shell 中的一种特殊的重定向方式,它的基本的形式如下:

command << delimiter

document

delimiter

它的作用是将两个 delimiter 之间的内容(document) 作为输入传递给 command。

例:

cat << EOF

This is a simple lookup program

for good (and bad) restaurants

in Cape Town.

EOF

$ command > /dev/null  #不希望在屏幕上显示输出结果

$ command > /dev/null 2>&1  #如果希望屏蔽 stdout 和 stderr,可以这样写

Shell 也可以包含外部脚本,将外部脚本的内容合并到当前脚本。

Shell 中包含脚本可以使用:

  1. . filename

  1. source filename

例如,创建两个脚本,一个是被调用脚本 subscript.sh,内容如下:

url="http://see.xidian.edu.cn/cpp/view/2738.html"

一个是主文件 main.sh,内容如下:

#!/bin/bash

. ./subscript.sh

echo $url

执行脚本:

$chomd +x main.sh

./main.sh

http://see.xidian.edu.cn/cpp/view/2738.html

标签: shell

添加新评论