条件测试:判断某需求是否满足,需要由测试机制来实现,专用的测试表达式需要由测试命令辅助完成测试过程。通过布尔值的返回结果来判定条件测试的结果。
若真,则状态码变量 $?返回0
若假,则状态码变量 $?返回1
条件测试命令
test expression
[ expression ] 和test等价,建议使用 []
[[ expression ]] 增强版的[],支持[]的用法,且支持扩展正则表达式和通配符
注意:expression前后必须有空白字符
[root@rocky8 ~]# help [[
[[ ... ]]: [[ expression ]]
Execute conditional command.
Returns a status of 0 or 1 depending on the evaluation of the conditional
expression EXPRESSION. Expressions are composed of the same primaries used
by the `test' builtin, and may be combined using the following operators:
( EXPRESSION ) Returns the value of EXPRESSION
! EXPRESSION True if EXPRESSION is false; else false
EXPR1 && EXPR2 True if both EXPR1 and EXPR2 are true; else false
EXPR1 || EXPR2 True if either EXPR1 or EXPR2 is true; else false
When the `==' and `!=' operators are used, the string to the right of
the operator is used as a pattern and pattern matching is performed.
When the `=~' operator is used, the string to the right of the operator
is matched as a regular expression.
The && and || operators do not evaluate EXPR2 if EXPR1 is sufficient to
determine the expression's value.
Exit Status:
0 or 1 depending on value of EXPRESSION.
[root@rocky8 ~]#
通配符
正则表达式 (使用=~匹配)
判断是否是一个.sh后缀的文件
[root@rocky8 ~]# type [
[ is a shell builtin
[root@rocky8 ~]# help [
[: [ arg... ]
Evaluate conditional expression.
This is a synonym for the "test" builtin, but the last argument must
be a literal `]', to match the opening `['.
[root@rocky8 ~]# help test
test: test [expr]
Evaluate conditional expression.
Exits with a status of 0 (true) or 1 (false) depending on
the evaluation of EXPR. Expressions may be unary or binary. Unary
expressions are often used to examine the status of a file. There
are string operators and numeric comparison operators as well.
The behavior of test depends on the number of arguments. Read the
bash manual page for the complete specification.
File operators:
-a FILE True if file exists.
-b FILE True if file is block special.
-c FILE True if file is character special.
-d FILE True if file is a directory.
-e FILE True if file exists.
-f FILE True if file exists and is a regular file.
-g FILE True if file is set-group-id.
-h FILE True if file is a symbolic link.
-L FILE True if file is a symbolic link.
-k FILE True if file has its `sticky' bit set.
-p FILE True if file is a named pipe.
-r FILE True if file is readable by you.
-s FILE True if file exists and is not empty.
-S FILE True if file is a socket.
-t FD True if FD is opened on a terminal.
-u FILE True if the file is set-user-id.
-w FILE True if the file is writable by you.
-x FILE True if the file is executable by you.
-O FILE True if the file is effectively owned by you.
-G FILE True if the file is effectively owned by your group.
-N FILE True if the file has been modified since it was last read.
FILE1 -nt FILE2 True if file1 is newer than file2 (according to
modification date).
FILE1 -ot FILE2 True if file1 is older than file2.
FILE1 -ef FILE2 True if file1 is a hard link to file2.
String operators:
-z STRING True if string is empty.
-n STRING
STRING True if string is not empty.
STRING1 = STRING2
True if the strings are equal.
STRING1 != STRING2
True if the strings are not equal.
STRING1 < STRING2
True if STRING1 sorts before STRING2 lexicographically.
STRING1 > STRING2
True if STRING1 sorts after STRING2 lexicographically.
Other operators:
-o OPTION True if the shell option OPTION is enabled.
-v VAR True if the shell variable VAR is set.
-R VAR True if the shell variable VAR is set and is a name
reference.
! EXPR True if expr is false.
EXPR1 -a EXPR2 True if both expr1 AND expr2 are true.
EXPR1 -o EXPR2 True if either expr1 OR expr2 is true.
arg1 OP arg2 Arithmetic tests. OP is one of -eq, -ne,
-lt, -le, -gt, or -ge.
Arithmetic binary operators return true if ARG1 is equal, not-equal,
less-than, less-than-or-equal, greater-than, or greater-than-or-equal
than ARG2.
Exit Status:
Returns success if EXPR evaluates to true; fails if EXPR evaluates to
false or an invalid argument is given.
变量测试
数值测试
-eq #equal(等于)
-ne #not-equal(不等于)
-lt #less-than(小于)
-le #less-than-or-equal (小于或等于)
-gt #greater-than(大于)
-ge #greater-than-or-equal(大于或等于)
[ 1 -eq 1 ] #1是否等于1 echo $?=0 (0是真,1是假)
[ 1 -ne 2 ] #1是否不等于2 echo $?=0
[ 2 -gt 3 ] #2是否大于3 echo $?=1
数值测试的应用,
1.测试分区利用率是否大于某个值时,就报警。
2.判读是否是一个合法的ip
字符串测试
在比较字符串时,建议变量放在“”双引号中
-z string True if string is empty.字符串是否为空,没定义或空为真,不空为假
-n string True if string is not empty.字符串是否不空,不空为真,空为假
STRING1 = STRING2 True if the strings are equal.
STRING1 != STRING2 True if the strings are not equal.
STRING1 < STRING2 True if STRING1 sorts before STRING2 lexicographically.
STRING1 > STRING2 True if STRING1 sorts after STRING2 lexicographically.
文件测试
判断某个文件是否存在
-a FILE True if file exists.
-e FILE True if file exists.(推荐使用 -e)
-a和-e的区别(官方没有给出区别的解释,那我们自己使用感叹号!做区别测试)
建议使用-e
判读一个文件是否有些权限
[root@rocky8 ~]# ll /etc/shadow
----------. 1 root root 1338 Nov 12 17:44 /etc/shadow
[root@rocky8 ~]# [ -w /etc/shadow ]
[root@rocky8 ~]# echo $?
0
[root@rocky8 ~]#
root权限不受控制
关于()和{}
(cmd1;cmd2;…;)和 {cmd1;cmd2;…;}都可以将多个命令组合在一起,批量执行。
(list) list is executed in a subshell environment (see COMMAND EXECUTION ENVIRONMENT below). Variable assignments
and builtin commands that affect the shell's environment do not remain in effect after the command com‐
pletes. The return status is the exit status of list.
{ list; }
list is simply executed in the current shell environment. list must be terminated with a newline or semi‐
colon. This is known as a group command. The return status is the exit status of list. Note that unlike
the metacharacters ( and ), { and } are reserved words and must occur where a reserved word is permitted to
be recognized. Since they do not cause a word break, they must be separated from list by whitespace or
another shell metacharacter.
( list ) 会开启shell,并且list中变量复制及内部命令执行后,将不在影响后续的环境;
{list;}不会启shell,在当前shell中运行,会影响当前shell环境。
组合测试条件
[ expression1 -a expression2 ] 并且(and),1和2都是真,结果才是真
[ expression1 -o expression2 ] 或者(or),1和2只要有一个真,结果就为真
[ ! expression ] 取反
注意:-a和-o需要使用测试命令进行,[[]]不支持
短路与和短路或
command1 && command2 并且,短路与,代表条件性的 and then (如果cmd1成功,则执行cmd2,否侧不执行cmd2) # [ $[RANDOM%6] -eq 0 ] && rm -rf /*
command1 || command2 或者,短路或,代表条件性的 or else (如果cmd1成功,将不执行cmd2,否则将执行cmd2)
!command 非,取反
应用:创建一个nginx账号,如果有就提示已经存在,否侧就创建
USER=nginx
id $USER &> /dev/null && echo $USER is exit || { useradd $USER; echo $USER is created; }
编写磁盘空间检测脚本,空间利用率大于80后,发邮件报警。
1.邮件发送第一步:怎么取出分区利用率的百分率数字?
[root@rocky8 ~]# df -h |grep '^/dev' |sed -rn 's/.* ([0-9]+)%/\1/p'
9 /
1 /home
26 /boot
[root@rocky8 ~]#
[root@rocky8 ~]# df -h |grep '^/dev' |sed -rn 's/.* ([0-9]+)%.*/\1/p'
9
1
26
[root@rocky8 ~]#
[root@rocky8 ~]# df -h |grep '^/dev' |sed -rn 's/.* ([0-9]+)%.*/\1/p'|sort -nr|head -1
26
[root@rocky8 ~]#
2.编写触发邮件报警的脚本
#! /bin/bash
USE=`df -h |grep '^/dev' |sed -rn 's/.* ([0-9]+)%.*/\1/p'|sort -nr|head -1`
WARING=80
[ $USE -gt $WARING ] && echo "Disk will be full" | mail -s "Disk Waring 磁盘要爆啦,快去扩容吧,攻城狮!" 1760359513@qq.com
~
3.执行脚本
以上报警邮件可以优化,让程序自动检查,比如每隔多久检查一次。
read命令
read命令读取键盘输入
[root@rocky8 ~]# help read
read: read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [name ...]
Read a line from the standard input and split it into fields.
Reads a single line from the standard input, or from file descriptor FD
if the -u option is supplied. The line is split into fields as with word
splitting, and the first word is assigned to the first NAME, the second
word to the second NAME, and so on, with any leftover words assigned to
the last NAME. Only the characters found in $IFS are recognized as word
delimiters.
If no NAMEs are supplied, the line read is stored in the REPLY variable.
Options:
-a array assign the words read to sequential indices of the array
variable ARRAY, starting at zero
-d delim continue until the first character of DELIM is read, rather
than newline
-e use Readline to obtain the line in an interactive shell
-i text use TEXT as the initial text for Readline
-n nchars return after reading NCHARS characters rather than waiting
for a newline, but honor a delimiter if fewer than
NCHARS characters are read before the delimiter
-N nchars return only after reading exactly NCHARS characters, unless
EOF is encountered or read times out, ignoring any
delimiter
-p prompt output the string PROMPT without a trailing newline before
attempting to read
-r do not allow backslashes to escape any characters
-s do not echo input coming from a terminal
-t timeout time out and return failure if a complete line of
input is not read within TIMEOUT seconds. The value of the
TMOUT variable is the default timeout. TIMEOUT may be a
fractional number. If TIMEOUT is 0, read returns
immediately, without trying to read any data, returning
success only if input is available on the specified
file descriptor. The exit status is greater than 128
if the timeout is exceeded
-u fd read from file descriptor FD instead of the standard input
Exit Status:
The return code is zero, unless end-of-file is encountered, read times out
(in which case it's greater than 128), a variable assignment error occurs,
or an invalid file descriptor is supplied as the argument to -u.
编写脚本,输入一个分数值,判断是否通过60分
#! /bin/bash
read -p "请输入你的考试成绩:" SCORE
[[ $SCORE =~ ^(100|[0-9]{1,2})$ ]] || { echo "不合法,请输入合法成绩!";exit; }
[ $SCORE -ge 60 ] && echo "pass" || echo "Not Pass"
流程控制语句
#if后面的有空格
age=11; if [ $age -lt 18 ] ; then echo "Too young too native!";fi
#! /bin/bash
read -p "请输入你的考试成绩:" SCORE
[[ $SCORE =~ ^(100|[0-9]{1,2})$ ]] || { echo "不合法,请输入合法成绩!";exit; }
#[ $SCORE -ge 60 ] && echo "pass" || echo "Not Pass"
if [ $SCORE -lt 60 ];then
echo "不及格啊,小伙子!"
elif [ $SCORE -lt 80 ];then
echo "成绩还行!"
else
echo "哎呦,不错哦!"
fi
#! /bin/bash
read -p "请输入身高(单位/m):" HIGH
if [[ ! "$HIGH" =~ ^[0-2](\.[0-9]{,2})?$ ]];then
echo "错误的身高!"
exit 1
fi
read -p "请输入体重(单位/kg):" WEIGHT
if [[ ! "$WEIGHT" =~ ^[0-9]{1,3}$ ]];then
echo "错误的体重!";
exit 2
fi
#身体质量指数(BMI)计算公式为:BMI=体重÷身高^2。(体重:千克;身高:米。)
BMI=`echo $WEIGHT/$HIGH^2|bc`
if [ $BMI -le 18 ];then
echo "太瘦了,多吃点!"
elif [ $BMI -lt 24 ]; then
echo "身材很棒!"
else
echo “太胖了,加强运动!”
fi
应用:为不同版本的系统装软件,centos和rocky的安装命令为“yum -y install gcc” 而ubuntu的安装命令为“apt install gcc”
那就需要先判读系统的版本
#! /bin/bash
. /etc/os-release
if [ $ID = "rocky" -o $ID = "centos" ];then
echo os version is rocky or centos
yum -y install gcc
elif [ $ID = "Ubuntu" ];then
echo os version is Ubuntu
apt update
apt -y install gcc
else
echo "不支持的OS"
exit
fi
条件判断case语句
#! /bin/bash
echo -en "\E[$[RANDOM%7+31];1m"
cat <<EOF
请选择:
1)备份数据库
2)清理日志
3)软件升级
4)软件回滚
5)删库跑路
6)完犊子啦
EOF
echo -en '\E[0m'
read -p "请输入上面数字1-6:" MENU
case $MENU in
1)
echo "执行备份数据库"
;;
2)
echo "清理日志"
;;
3)
echo "软件升级"
;;
4)
echo "软件回滚"
;;
5)
echo "删除跑路"
;;
6)
echo "完犊子"
;;
*)
echo "INPUT FALSE!"
esac