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脚本总结的主要内容,如果未能解决你的问题,请参考以下文章