bash脚本总结

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bash脚本总结相关的知识,希望对你有一定的参考价值。

bash及shell脚本编程基础


bash特性之多命令执行:使用分号分隔,命令之间无关系;

]# cmd

方式一:]# cmd1 `cmd2`:命令引用实现多命令;

方式二:]# cmd1|cmd2|cmd3|...:管道实现多命令;

方式三:]# cmd1;cmd2;cmd3;...:分号实现多命令;


逻辑组合:操作的是命令的运行状态结果即退出码;

]# cmd1 && cmd2 && ...

]# cmd1 || cmd2 ||...

]# !cmd1


退出码:

0:表示为true,真,success,成功;

1-255:表示为failure,假,错误;


逻辑运算:主要操作的是命令的运行状态结果即退出码;

可认为有一种判断的机制在里面;判断取决于是与运算还是或运算还取决于第一个操作的结果;


运算数:true(1),false(0)

COMMAND运行状态结果:

0:TRUE,成功;

1-255:FALSE,错误;


与:见false(0)为false(0);相当于乘法;

true && true = true

true && false = false

第一个操作数为true,其结果取决于第二个操作数;

false && true = false

false && false = false

第一个操作数为false,其结果至此可判定为false;

例如:

]# ls /var && cat /etc/fstab

]# lls /var && cat /etc/fstab


或:见true(1)为true(1);相当于加法;

true || true = true

true || false = true

第一个操作数为true,其结果至此可判定为ture;

false || true = true

false || false = false

第一个操作数为false,其结果取决于第二个操作数;

例如:

]# id hive || useradd hive:如果用户不存在,则添加用户;

]# id hive


非:取反

! true = false

! fase = true

例如:

]# ! id hive && useradd hive:如果用户不存在,则添加用户;


优先级:非 (高)<--与 <--或(低)


运行脚本:

(1)赋予执行权限,并直接运行此程序文件;

chmod +x /PATH/TO/SCRIPT_FILE

/PATH/TO/SCRIPT_FILE


也可直接把脚本文件放在PATH环境变量中;例如把脚本文件放在/bin目录下;


(2)直接运行解释器,以脚本文件为参数;

bash /PATH/TO/SCRIPT_FILE

-x:调试执行;

-n:判断语法错误;


bash特性之变量:


引号有三种类型:‘‘,"",``

引号:字符串引用符号;

‘‘单引号:强引用;其内部的变量不会替换;

""双引号:弱引用;其内部的变量会被替换;

``反引号:命令引用符号;


例如:

]# echo ‘$PATH‘

显示结果:$PATH

]# echo "$PATH"

显示结果:/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin

]# echo `ls /root`

显示结果:anaconda-ks.cfg install.log install.log.syslog


变量引用:${NAME},要使用花括号


变量:是内存空间,有名称,名称即为变量名,对应的内存空间中的数据即为变量的值;


变量赋值:NAME=VALUE

=:赋值符号;

把VALUE存储到NAME指向的内存空间中;


编程语言:

强类型:严格区分变量(内存空间)中的数据类型;

弱类型:不区分变量中存储的数据类型,统一为字符型;

bash:统统默认为字符型数据,变量无需事先声明;


变量为什么有类型?

存储空间、存储格式、参与的运算、...



变量命名:只能使用字母、数字和下划线;且不能以数字开头;

变量名:见明知义,不能使用程序保留字(如if,then,case,fi,esac,for,while,until,break,continue等等);

变量引用:${NAME},$NAME

变量替换:把变量引用符号出现的位置替换为其指向的内存空间中的数据;


bash的变量种类:

根据作用域划分:作用域:生效范围,可引用到的范围;

变量目的:

(1)变量用于存数据,可重复多次使用这个数据;

(2)可多次修改变量里面的数据,以达到演进、迭代目的;


本地变量

环境变量

局部变量(函数中)


位置参数变量:

特殊变量:$?,, [email protected], $#

retval=$?

保存的是命令执行的状态结果;


exit结束shell进程;


pstree命令:显示进程树;

tree命令:显示目录树;


本地变量:作用域为当前shell进程;不包括其子进程;

定义本地变量:

本地变量赋值:NAME=VALUE

本地变量引用方式:$NAME,${NAME}

""

查看变量:set

撤销变量:unset NAME

注意:此处非为变量引用,因此不能使用$;

所有的本地变量在shell进程终止时,会被自动撤销;

例如:

]# pstree:查看shell进程树;

]# name="obama":定义本地变量;仅当前shell进程有效;

]# echo $name

切换到另外的进程查看name变量:

]# echo $name:内容为空;本地变量在同级进程或子进程都无效;


]# set:查看本地变量;

]# unset name:撤销本地name变量;此处非为变量引用,因此不能使用$;

]# animal="goat"

]# echo "There are some $(animal)s."

环境变量:作用域为当前shell进程及其子进程;但不包括同级进程;

环境变量声明和赋值:

declare -x NAME[=VALUE]

-r:定义为只读变量;

export NAME[=VALUE]

可以把本地变量声明环境变量;

环境变量引用方式:

${NAME},$NAME


注意:bash内嵌了很多环境变量,名称为全大写字母;例如:HOME,UID,PWD,SHELL,PATH,HISTSIZE等等;

主要用于工作的特殊环境;


查看环境变量命令:

export,declare -x

env,printenv


撤销环境变量:

unset NAME

例如:

]# declare -x animal:声明环境变量;

]# /bin/bash:环境变量在当前shell进程及其子进程有效;

]# echo ${animal}:花括号可省略;

]# export:查看环境变量;

]# declare -x:查看环境变量;

]# env:查看环境变量;显示格式不同;

]# printenv:查看环境变量;显示格式不同;

]# unset namimal:撤销环境变量;

例如:

]# ls /etc

]# retval=$?:把环境变量的值存储在变量中,方便使用;

]# lll /etc

]# echo $?:查看环境变量状态返回值;

]# echo $retval:查看之前的环境变量状态返回值,这就是变量的意义;


只读变量:就是常量,无法修改,无法撤销;生命周期同当前shell;

定义只读变量:不支持重新赋值,也不支持撤销;

(1)declare -r NAME

(2)readonly NAME


例如:

]# username="Lu Youjiao"

]# declare -r username:定义只读变量;

]# username="Ou Yangfeng":显示不能更改只读变量;

]# unset username:无法撤销只读变量;



bash脚本编程之算术运算

+,-,*,/,%(莫,判断单双数),**

shell变量是一种很弱的变量,默认情况下,一个变量保存一个串,shell不关心这个串是什么含义,所以弱要进行数学运算,必须使用一些命令例如let,declare,expr,双括号等;


算术运算

+,-,*,/,%(取模,判断单双数),**

shell变量是一种很弱的变量,默认情况下,一个变量保存一个串,shell不关心这个串是什么含义,所以弱要进行数学运算,必须使用一些命令例如let,declare,expr,双括号等;


算术运算格式语法:

(1)let VAR=$num1 op $num2(算术运算表达式)

(2)VAR=$[算术运算表达式]

(3)VAR=$((算术运算表达式))

(4)VAR=$(expr argu1 argu2 argu3)


注意:有些时候乘法符号需要转义;


练习:脚本完成,添加3个用户,求三用户的ID之和;


id user1 &> /dev/null || useradd user1

id user2 &> /dev/null || useradd user2

user1_id=$(id -u user1)

user2_id=$(id -u user2)

id_sum=$[$user1_id+$user2_id]

echo "the id sum: $id_sum"


增强型变量赋值:

+=,-=,*=,/=,%=

自身等于自身+数值,使用let命令;


例如:

    ]# declare -i i=1    

    ]# i=$[$i+1]                           

    ]# echo $i

此时就可用增强型赋值:

    ]# let i+=1


变量做某种算术运算后回存至此变量中;

    let i=$i+#

    let i+=#

    #:代表数字


自增:

    VAR=$[$VAR+1]

    let VAR+=1

    let VAR++

自减:

    VAR=$[$VAR-1]

    let VAR-=1

    let VAR--


练习:

1、脚本实现,计算/etc/passwd文件中第15个用户和第18个用户的ID号之和;

分解:做a,b2个id号的运算,id_sum=$[$id1+$id2]


 a=$(head -15 /etc/passwd | tail -1 | cut -d: -f3)

 b=$(head -18 /etc/passwd | tail -1 | cut -d: -f3)

 

 sum=$[$a+$b]


 echo "the a is:$a"

 echo "the b is :$b"

 echo "teh sum is :$sum"


2、计算/etc/rc.d/init.d/functions和/ect/inittab文件中的空白行数之和;

a=$(egrep "^[[:space:]]*$" /etc/rc.d/init.d/functions|wc -l)

b=$(egrep "^[[:space:]]*$" /etc/rc.d/init.d/network|wc -l)

sum=$[$a+$b]


echo "a is :$a"

echo "b is $b"

echo "sum is :$sum"


bash脚本编程之条件测试:

判断某需求是否满足,需要由测试机制来实现;


如何编写测试表达式以实现所需的测试:

例如:判断某文件是否有空白行、判断某用户是否存在

(1)执行命令,并利用命令状态返回值来判断;

0:成功

1-255:失败

$?:存储上一条命令执行状态返回值;


例如:

判断用户centos是否登录系统:

    who|grep "^centos\>"

    echo $?:显示上一个命令状态返回值;

取得命令状态返回值,0表示登录,1-255表示没登录;


(2)测试表达式

test EXPRESSION

[ EXPRESSION ]

[[ EXPRESSION ]]


字符比较时,用双中括号

注意:EXPRESSION两端必须要有空白字符,否则语法错误;


bash脚本编程之测试类型:

数值测试

字符串测试

文件测试


数值测试:数值之间的比较


-eq:是否等于;例如:[ $num1 -eq $num2 ],test 2 -eq 3或[ 2 -eq 3 ]

-ne:是否不等于;

-gt:是否大于;

-ge:是否大于等于;

-lt:是否小于;

-le:是否小于等于;

例如:

]# test 2 -gt 3

]# [ $A -eq $B ]

练习:

centos用户id是否比ubuntu用户的ID大?

a=$(id -u centos)

b=$(id -u ubunto)

[ $a -gt $b ] && echo "centos is bigger" || echo "ubuntu is bigger"


字符串测试比较

==:是否等于,等于为真;

!=:是否不等,不等于为真;

>:是否大于,大于为真;

<:是否小于,小于为真;

=~:左侧字符串是否能被右侧的PATTERN所匹配(左边是否包含右边),包含为真;


例如:

]# name=uubuntuu

]# [[ "$naem" =~ buntu ]]

]# echo $?


练习:

判断主机名是否包含magedu,如果不包含,则修改为magedu;

  ]# a=$(hostname)

  ]# [[ "$name" =~ magedu ]] || hostname magedu


字符串是否为空:  

-z "STRING":判断指定的字符串是否为空;

空则为真,不空则为假

-n "STRING":判断指定的字符串是否不空;

不空则为真,空则为假;

注意:

(1)字符串比较要加引号,表示引用;即不做变量替换可用单引号,做变量替换要用双引号;

(2)字符串比较时,要使用[[ ]]双中括号;            


练习:

主机名如果为空,或者为localhost.locadomain或者包含localhost或者包含linux则统统将其设为www.magedu.com

]# [ -z "$name" -o "$name"=="localhost.locadomain" -o "$name"=~"localhost" -o "$name"=~"linux" ] && hostname www.magedu.com

注意:使用-o逻辑时,字符测试比较符不能有空格且字符要用引号,不能用双中括号。


文件测试:

存在性测试

-a FILE

-e FILE:文件的存在性测试,如果存在,则为真;

例如:

]# [ -e /etc/passwd ]


文件的存在性及文件类型测试:既能测试存在性又能测试类别

-b FILE:文件是否存在并且为块设备文件;

-c FILE:文件是否存在并且为字符设备文件;

-d FILE:文件是否存在并且为目录文件;

-f FILE:文件是否存在并且为普通文件;

-h FILE或-L FILE:文件是否存在并且为符号链接文件;

-p FILE:文件是否存在并且为命名管道文件;

-S FILE:文件是否存在并且为套接字文件;

例如:

]# [ -c /dev/null ]


文件权限测试:

-r FILE:文件是否存在并且对当前用户可读;

-w FILE:文件是否存在并且对当前用户可写;

-x FILE:文件是否存在并且对当前用户可执行;

例如:

[ -w /etc/passwd ] && echo ok


特殊权限测试:

-u FILE:文件是否存在并且拥有SUID权限;

-g FILE:文件是否存在并且拥有SGID权限;

-k FILE:文件是否存在并且拥有sticky权限;

例如:

[ -u /usr/bin/passwd ]


文件是否有内容:

-s FILE:是否有内容,有则为真:

例如:

[ -s /etc/fstab ]


文件时间戳是否变化:

-N FILE:文件自从上一次读操作之后,是否被改过;


文件从属关系测试:

-O FILE:当前用户是否为文件的属主;

-G FILE:当前用户是否为文件的属组;


双目测试:

FILE1 -ef FILE2:文件1与文件2是否指向同一个文件系统上相同inode的硬链接;

FILE1 -nt FILE2:文件1是否新于文件2;

FILE1 -ot FILE2:文件1是否旧于文件2;


组合测试条件:

逻辑运算:

第一种方式:

COMMAND1 && COMMAND2:与运算;

COMMAND1 || COMMAND2:或运算;

! COMMAND(取反)


例如:

[ -O FILE ] && [ -r FILE ]


第二种方式:

expresssion1 -a expression2

expresssion1 -o expression2

! expresssion或-not expresssion


例如:

[ -O FILE -a -x FILE ]:当前引用是否为file文件的属主,且是否有执行权限;


练习:将当前主机名称保存至hostName变量中;

主机名如果为空,或者为localhost.localdomain,则将其设置为www.magedu.com;

hostName=$(hostname)

[ -z "$hostName" -o "$hostName"=="localhost.localdomain" -o "$hostName"=="localhost" ] && hostname www.magedu.com



脚本的状态返回值:

默认是脚本中执行的最后一条命令的状态返回值;

自定义状态退出状态码;

exit [n]:n为自己指定的状态码;

    注意:shell进程遇到exit时,即会终止,因此,整个脚本执行即为结束;


所以,exit不能随意添加使用,要使用条件测试判断后,确定是否添加exit退出;

埋点调试;使用$?能判断是在哪个位置退出的,定位问题常用;


练习:

脚本实现,一行命令实现,magedu用户是否存在,不存在,则添加,如果存在,以状态码为5的方式退出;

id mageedu &> /dev/null || useradd mageedu && exit 5

或:id mageedu &> /dev/null && exit 5 || useradd mageedu


bash脚本编程之向脚本传递参数

位置参数变量

命令行:*.sh argu参数1 argu参数2 argu参数3...

脚本里引用方式:$1 $2 $3...


myscript.sh agru1 argu2...

引用方式:

    $1:保存argu参数1;

    $2:保存argu参数2;

    ...

    ${10},${11}...


轮替:

    shift [n]:位置参数轮替,n为数字默认为1;表示为一次轮替前几个参数;

$1,$2...就叫位置参数变量,每次运行脚本时,通过传递参数变化来改变这些参数变量的值;


例如:

my_shell.sh ubuntu centos linux

引用方式:

脚本中使用$1,$2,$3

useradd $1

useradd $2

useradd $3

解释:$1=ubuntu,$2=centos,$3=linux


shift #:表示删掉指定参数;把后面的参数往前补充;


练习:

脚本实现,通过命令传递两个文本路径给脚本,计算其空白行数(^$)之和;

a=$(egrep "^$" $1|wc -l)

b=$(egrep "^$" $2|wc -l)

sum=$[$a+$b]

echo "a is :$a"

echo "b is $b"

echo "sum is :$sum"


shift #:会自动踢出命令参数;


特殊变量:

$0:保存脚本文件路径本身;

$#:保存脚本参数的个数;

$*:保存所有参数;把每个参数当做一个个独立参数显示;

[email protected]:保存所有参数;把每个参数合在一起,当做一个字符串参数显示;


$0:表示命令行给定脚本文件路径;


例如:命令行]# bash /tmp/parameter_blanksum.sh

脚本内容:echo $0

显示结果为:/tmp/parameter_blanksum.sh

如果命令行是:bash parameter_blanksum.sh

脚本内容不变,显示结果为:parameter_blanksum.sh


$#:表示脚本参数的个数;


例如:

]# bash parameter_blanksum.sh /etc/init.d/functions /etc/init.d/network

脚本内容:echo $#

显示结果为:2


$*:表示参数为多个字符串;

[email protected]:表示参数为一个字符串;


例如:命令行]# bash parameter_blanksum.sh /etc/init.d/functions /etc/init.d/network

脚本内容:echo $*

     echo [email protected]

显示结果为:/etc/init.d/functions /etc/init.d/network

/etc/init.d/functions /etc/init.d/network

但是$*表示为2个分开的路径,而[email protected]表示为一整行为一个字符串。


练习:

1、判断/etc/passwd是否为文件,如果为文件,则输出/etc/passwd is files,该路径通过命令传递的方式传入,当传入的命令个数大于1,则报错;

[ $# -gt 1 ] && echo "something wrong " && exit 100

[ -f $1 ] && echo "/etc/passwd is files"

2、在root目录下,写脚本,可以一次性添加3名用户,通过传递参数的方式,进行用户添加,当传递的参数不符合3个的时候,报错;

当三名用户添加完成后,需要将脚本进行权限加固(锁机制,不能再执行),将脚本权限改成属主可读可写可执行;


! [ $# -eq 3 ] && echo "please give me three username" && exit 1

useradd $1 && a=1

useradd $2 && b=1

useradd $3 && c=1

sum=$[$a+$b+$c]

[ $sum -eq 3 ] && echo "$1 $2 $3" ||exit 2

chmod 700 $0

echo $1 is added

echo $2 is added

echo $3 is added

echo "this scripts mode is 700"

或:

[ $# -gt 3 ] || [ $# -lt 3 ] && echo "something wrong,give three user" && exit 1


id $1 &> /dev/null && echo "$1 exist" || useradd $1

id $2 &> /dev/null && echo "$2 exist" || useradd $2

id $3 &> /dev/null && echo "$3 exist" || useradd $3


echo "three users $1,$2,$3 are added success"


chmod 700 $0

echo "this script mode is 700"


过程式编程语言的代码执行顺序:

顺序执行:逐条运行;

选择执行:

代码存在一个分支:条件满足时才会执行;

两个或以上的分支:只会执行其中一个满足条件的分支;

循环执行:

某代码片段(循环体)要执行0、1或多个来回(循环);


顺序执行

条件选择:

(1)&&,||

(2)if语句(单分支,双分支,多分支)

(3)case语句

循环执行:for,while,until


bash脚本编程之if语句选择分支

条件判断:

shell执行是顺序执行的


选择分支

单分支的if语句

    if 测试条件;then(如果条件为真,则执行下面语句)

        代码分支

    fi

    if 测试条件

    then

        代码分支

    fi


双分支的if语句

if 测试条件;then

条件为真时执行的分支

else

条件为假时执行的分支

fi


多分支的if语句

if 测试条件;then

条件为真时候执行的分支

elif 测试条件;then

elif 测试条件;then

elif 测试条件;then

else

条件为假时候执行的分支

fi


例如:

通过参数传递给一个用户名给脚本,此用户如果不存在则创建用户;


if ! grep "^$1\>" /etc/passwd &> /dev/null;then

useradd $1

echo $1|passwd --stdin $1 &> /dev/null

echo "add a user $1 finished"

else

echo "$1 is exist"

fi


示例:通过参数传递一个用户名给脚本,此用户不存在时,则添加;(判断表达方法:一种是命令,另一种是表达式放在中括号中或用test表示,判断用户是否存在用id或grep)

~]# vim useradd.sh

if ! grep "^$1\>" /etc/passwd &> /dev/null;then

    useradd $1

    echo $1 | passwd --stdin $1 &> /dev/null

    echo "add user $1 finished"

fi

~]# ./useradd.sh hbase

执行结果为:add user hbase finished


加入了判断参数是否存在的判断if语句:

~]# vim useradd.sh

if [ $# -lt 1 ];then

    echo "at least one username"

    exit 2

fi


if ! grep "^$1\>" /etc/passwd &> /dev/null;then

    useradd $1

    echo $1 | passwd --stdin $1 &> /dev/null

    echo "add user $1 finished"

fi

~]# ./useradd.sh hbase


变为双分支判断if语句:

~]# vim useradd.sh

if [ $# -lt 1 ];then

    echo "at least one username"

    exit 2

fi


if grep "^$1\>" /etc/passwd &> /dev/null;then

    echo "user $1 exists"

else

    useradd $1

    echo $1 | passwd --stdin $1 &> /dev/null

    echo "add user $1 finished"

fi

~]# ./useradd.sh hbase


练习:

1、通过命令参数,给定两个数字,输出其中较大的数值;

if [ $1 -gt $2 ] ;then

echo $1 is bigger

else

echo $2 is bigger

fi

或:

if [ ! $# -eq 2 ];then

 echo "give two number"

 exit 2;

fi


if [ $1 -gt $2 ];then

 echo "the bigg is $1"

elif [ $1 -lt $2 ];then

 echo "the bigg is $2"

else

 echo "$1=$2"

fi


2、通过命令参数,给定两个文本文件名,如果某文件不存在,则结束脚本,如果都存在返回每个文件的行数,并echo其中行数较多的文件名;

[ $# -ne 2 ] && echo "give two file" && exit 1


if ! [ -e $1 ];then

echo "$1 is not find"

exit 2

elif ! [ -e $2 ];then

echo "$2 is not find"

 exit 3

fi


f1=$(cat $1|wc -l)

f2=$(cat $2|wc -l)


echo "$1 line is $f1"

echo "$2 line is $f2"


if [ $f1 -gt $f2 ];then

  ehco "$f1 is more"

elif [ $f1 -eq $f2 ];then

 echo "f1 and f2 the same"

else

 echo "$f2 is more"

fi

或:

if ! [ $# -eq 2 ];then

 echo "give 2 files"

 exit 20;

elif ! [ -e $1 ];then

 echo "$1 is not exist"

elif ! [ -e $2 ];then

 echo " $2 is not exist"

 exit 30;

else

f1=$(cat $1|wc -l)

f2=$(cat $2|wc -l)

echo "f1=$f1"

echo "f2=$f2"

fi


if [ $f1 -gt $f2 ];then

 echo "file1 line is more :$f1"

 echo "$(basename $1) line is more"

elif [ $f1 -lt $f2 ];then

 echo "file2 line is more :$f2"

 echo "$(basename $2) line is more"

else

 echo "f1-$f1 and f2-$f2 is same"


fi


3、通过命令行参数给定一个用户名,判断ID号是偶数还是奇数;


多分支if语句


选择执行:

(1)&&,||

(2)if语句

(3)case语句


if语句:三种格式

单分支的if语句

if CONDITION;then

if-ture-分支

fi


双分支的if语句

if CONDITION;then

if-true-分支

else

if-false-分支

fi


多分支的if语句

if CONDITION1;then

条件1为真分支

elif CONDITION2;then

条件2为真分支

elif CONDITION3;then

条件3为真分支

...

elif CONDITIONn;then

条件nweizhen分支

else

所有条件均不满足时的分支

fi


注意:即便多个条件可能同时满足,分支只会执行其中一个,首先测试为真的条件分支执行后,就退出;


示例:通过脚本参数,传递文件路径给脚本,判断此文件的类型;

if [ $# -lt 1 ];then

echo "at lease one path"

exit 1

fi


if ! [ -e $1 ];then

echo "no such file"

eixt 2

fi


if [ -f $1 ];then

echo "common file"

elif [ -d $1 ];then

echo "directory file"

elif [ -L $1 ];then

echo "symbolic link file"

elif [ -b $1 ];then

echo "block special file"

elif [ -p $1 ];then

echo "pipe file"

elif [ -S $1 ];then

echo "socket file"

elif [ -c $1 ];then

echo "character special file"


case语句其实就是简化版的多分支if语句,但未所有if语句都能转化为case语句;


注意:if语句可以嵌套使用;


练习:

1、写脚本实现如下功能:

(1)传递参数给脚本,此参数为用户名;

(2)根据其id来判断用户类型;

0:管理员

1-999:系统用户

1000+:登录用户

(3)如不存在,可添加此用户;


[ $# -lt 1 ] && echo "at least one username" && exit 1


! id $1 &> /dev/null && echo "no such user" && exit 2


userid=$(id -u $1)

if [ $userid -eq 0 ];then

echo "root"

elif [ $userid -ge 1000 ];then

echo "login user"

else

echo "system user"

fi



2、写脚本实现如下功能:

(1)列出如下菜单给用户

disk)show disks info(fdisk -l /dev/sda)

mem)show memory info(free -m)

cpu)show cpu info(使用cat /proc/cpuinfo或lscpu)

*)quit

(2)提示用户给出自己的选择,然后显示对应其选择的相应系统信息;


cat << EOF

disk) show disk info

mem) show memory info

cpu) show cpu info

*) QUIT

EOF


read -p "please choice : " option


if [[ "$option" == "disk" ]];then

fdisk -l /dev/[sh]d[a-z]

elif [[ "$option" == "mem" ]];then

free -m

elif [[ "$option" == "cpu" ]];then

lscpu

else

echo "your choice fault option"

fi


bash脚本编程之for循环

循环执行:将一段代码重复执行0、1或多次;

进入循环条件:只有条件满足时才进入循环;

退出循环条件:每个循环都应该有退出条件,有机会退出循环;


bash脚本有三种循环方式:

for循环

while循环

until循环


for循环有2种格式:

(1)遍历列表

(2)控制变量


变量赋值有三种方式:

(1)VAR=VALUE,直接赋值;

(2)通过read,实现变量赋值;

(3)for循环中,用列表赋值给变量;

遍历列表:

for VARAIBLE in LIST;do

循环体

done


进入条件:只有列表有元素,即可进入循环;

退出条件:列表中的元素遍历完成;


LIST的生成方式:

(1)直接给出;

(2)整数列表;

(a){start..end}自动展开;

(b)seq #:从1列出到#的数字;

seq start end:从开始数字列出到结束数字;

seq start step end:从开始数字,根据步长,列出结束数字;

seq命令:显示一系列数字

seq [start [increment]] last


(3)能返回一个列表的命令;

例如:ls命令

(4)glob通配符机制;

例如:/etc/p*

(5)变量引用

例如:[email protected],$*

...


例如:

seq 10:列出1 2 3 4 5 6 7 8 9 10

seq 5 10:列出5 6 7 8 9 10

seq 1 2 10:列出1 3 5 7 9

seq 2 2 10:列出2 4 6 8 10


例如:循环添加三个用户aaa,bbb,ccc;

for username in aaa bbb ccc;do 

if id $username &>/dev/null;then

echo "$username exists"

esle

useradd $username && echo "add user $username finished"

fi

done


例如:在tmp目录下创建10个文件f1-10;

for filename in {1..10};do

 touch /tmp/f$filename

done

注意:在如何时候,要考虑判断条件;如上例,应该先判断文件是否存在;


例如:求100内所有正整数之和;

declare -i sum=0

for i in {1..100};do

sum=$[$sum+$i]

done

echo $sum


例如:计算100内的奇数和;

declare -i sum=0

for i in $(seq 1 2 100);do

 sum=$[$sum+$i]

done

echo $sum


例如:计算100内的偶数和;

declare -i sum=0

for i in $(seq 2 2 100);do

 sum=$[$sum+$i]

done

echo $sum


示例:判断/var/log目录下的每个文件的类型;

file /var/log/*即可判断,但要求用循环实现;

for filename in /var/log/*;do

 

if [ -f $filename ];then

 echo "this is common file"

elif [ -d $filename ];then

 echo "this is directory file"

elif [ -L $filename ];then

 echo "this is softlink"

elif [ -b $filename ];then

  echo "this is block file"

elif [ -c $filename ];then

 echo "this is character file"

elif [ -S $filename ];then

 echo "this is socket file"

elif [ -p $filename ];then

 echo "thisi is pipe file"

else

   echo "unknow file type"

fi


done

练习:

1、分别求100内偶数之和,奇数之和;

计算100内的奇数和;

declare -i sum=0

for i in $(seq 1 2 100);do

  sum=$[$sum+$i]

 done

 echo $sum


计算100内的偶数和;

declare -i sum=0

for i in $(seq 2 2 100);do

  sum=$[$sum+$i]

 done

 echo $sum


2、计算当前系统上所有用户的id之和;

declare -i sum=0

for i in $(cut -d: -f3 /etc/passwd);do

echo "\$sum=$sum,\$i=$i"

sum=$[$sum+$i]

done

echo $sum



3、通过脚本参数传递一个目录给脚本,然后计算此目录下所有文本文件的行数之和;并说明此类文件的总数;

! [ $# -eq 1 ] && exit 1

! [ -d $1 ] && echo "please give a comment file" && exit 2


declare -i filesum=0

declare -i sum=0

declare -i A=0

for i in $(ls $1);do

if [ -f $i ];then

    a=$(wc -l $i|cut -d" " -f1)

    A+=1

    sum=$[$sum+$a]

echo "file line sum=$a,files sum $A,all file line sum is $sum"

else 

echo "this file not text type"  

fi  

done


for循环格式:

for VARAIBLE in LIST;do

循环体

done


LIST列表生成方式有多种:直接给出,{#..#},或glob(/tpm/test/*)等任何能够返回列表的命令都可以;


for循环的特殊用法:

for ((控制变量初始化;条件判断表达式;控制变量的修正语句)); do

循环体

done

注意:条件判断可直接使用<,>;


控制变量初始化:仅在循环代码开始运行时执行一次;

控制变量修正语句:会在每轮循环结束会先进行控制变量修正运算,而后再做条件判断;


示例:求100内整正数之和


declare -i sum=0


for ((i=1;i<=100;i++));do

        let sum+=$i

done

echo "sum: $sum"


练习:打印99乘法表


for ((j=1;j<=9;j++));do

        for ((i=1;i<=j;i++));do

                echo -e -n "${i}X${j}=$[${i}*${j}]\t"

        done

        echo

done


bash脚本编程之while循环和until循环


while循环:

while CONDITION;do

循环体

循环扩展变量修正表达式(条件修正表达式)

done


进入条件:CONDITION参数为“真”;

退出条件:CONDITION参数为“假”;


until循环:

until CONDITION;do

循环体

循环扩展变量修正表达式(条件修正表达式)

done


进入条件:CONDITION参数为“假”;

退出条件:CONDITION参数为“真”;

until就相当于在while条件前取反(!)的效果;



例如:求100内正整数和;

比for优势在于,如果数值比较多,for的列表会占用内存,while则使用的是变量,占用内存空间很小;

for循环:

for i in {1..100};do

sum=$[$sum+$i]

done

echo $sum


while循环:

declare -i sum=0

declare -i i=1

while [ $i -le 10 ];do

   sum=$[$sum+$i]

   let i++ 

done

echo $sum


until循环:

declare -i sum=0

declare -i i=1

until [ $i -gt 100 ];do

   let sum+=$i

   let i++ 

done

echo $sum


练习:分别使用for、while、until各自实现;

1、求100内所有偶数之和、奇数之和;

2、创建10个用户,分别为user101-user110;密码同用户名;

3、打印九九乘法表;

4、打印逆序九九乘法表;


1x1=1

1x2=2,2x2=4

1x3=3,2x3=6,3x3=9

循环嵌套:

外循环控制乘数,内循环控制被乘数;

for j in {1..9};do

for i in $(seq 1 $j);do

echo  -n -e "${i}x${j}=$[${i}*${j}]\t"

done

echo

done


进入条件:

for:列表元素非空;

while:条件测试结果为真;

until:条件测试结果为假;

退出条件:

for:列表元素遍历完成;

while:条件测试结果为假;

until:条件测试结果为真;


循环控制语句:

continue:提前结束本轮循环,而直接进入下一轮循环判断;

while CONDITION1; do

CMD1

...

if CONDITIONS2; then

continue

fi

CMDn

...

done


示例:求100内偶数和;


declare -i evensum=0

declare -i i=0


while [ $i -le 100 ];do

       let i++

       if [ $[$i%2] -eq 1 ];then

               continue

       fi

       let evensum+=$i

done

echo "evensum : $evensum"


break:提前跳出循环

while CONDITION1; do

CMD1

...

if CONDITIONS2; then

break

fi

done


break #:在循环嵌套时,指明跳出哪层循环;


sleep命令:

delay for a specified amount of time


sleep #

#:为数字默认单位是s秒钟,可用m分钟,h小时,d天为单位;




创建死循环:

while true;do

循环体

done


退出方式:

以上是关于bash脚本总结的主要内容,如果未能解决你的问题,请参考以下文章

Bash脚本编程总结

bash 脚本参数案例总结

bash脚本总结1:[[:not found 错误

bash脚本编程实践总结(图文)

系统管理中 bash shell 脚本常用方法总结

最全的Linux运维bash脚本常见用法总结