流程控制语句
单分支语句
if [ 满足条件 ];then 执行代码 fi
#!/bin/bash if [ while 1>0 ];then #如果1>0 echo "ok" fi
双分支语句
if [ 满足条件 ];then 执行代码 else #如果上面条件不满足 执行另一条代码 fi
#!/bin/bash if grep "$1" /etc/passwd;then echo "ok" else echo "error" fi
多分支语句
if [ 满足条件1 ];then 执行代码1 elif [ 满足条件2 ];then 执行代码2 else #如果以上条件都不满足 执行最后代码 fi
例:
#!/bin/bash read -p "请输入用户名:" User if grep $User /etc/passwd &> /dev/null;then echo "用户$User存在" elif ls -d /home/$User &> /dev/null;then echo "用户$User不存在" echo "但是$User宿主目录存在" else echo "用户$User不存在" echo "$User宿主目录也不存在" fi
文件比较
-e 文件或目录是否存在 [ -e file ]
-s 文件存在且至少有一个字符则为真 [ -s file ]
-d 目录是否存在 [ -d file ]
-f 文件是否存在 [ -f file ]
-r 文件存在且可读 [ -r file ]
-w 文件存在且可写 [ -w file ]
-x 文件存在且可执行 [ -x file ]
#!/bin/bash if [ -e /etc/passwd ];then echo "/etc/passwd存在" else echo "/etc/passwd不存在" fi #判断/etc/passwd是否存在
与或非格式
&& #与 1 && 1 = 1 0 && ? = 0 两者同时满足
|| #或 1 || ? = 1 0 || 1 = 1 两者满足其一
! #非 取反 !真 = 假 反之则为真
流程控制语句-整数比对
-eq #等于则为真 [ $? -eq 0 ]
-ne #不等则为真 [ $? -ne 0 ]
-gt #大于则为真 [ 1 -gt 2 ]
-lt #小于则为真 [ 1 -lt 2 ]
-ge #大于等于则为真 [ 1 -ge 2 ]
-le #小于等于则为真 [ 1 -le 2 ]
例1:监控nginx状态,nginx故障则停止keepalived服务
#!/bin/bash killall -0 nginx if [ $? -ne 0 ];then systemctl stop keepalived fi
例2:判断服务是否运行
#!/bin/bash if [ $# -ne 1 ];then echo "请在运行代码后输入一个服务名称" exit fi systemctl status "$1" &> /dev/null if [ $? -eq 0 ];then echo "$1 服务正在运行" else echo "$1 服务没有运行" systemctl restart $1 echo "$1 服务已重新启动" fi
流程控制语句-字符对比
= 等于则为真 [ "$a" == "$b" ]
!= 不等则为真 [ ! "$b" == "$a" ]
-z 字符长度为零则为真 [ -z "$a" ]
-n 字符长度不为零则为真 [ -n "$a" ]
str1>str2 str1大于str2则为真 [ str1>str2 ]
str1<str2 str1小于str2则为真 [ str1<str2 ]
例
#!/bin/bash read -p "请输入yes/no:" n if [ ${n} = "yes" ];then echo "this is ok" else echo "this is no" fi
#!/bin/bash read -p "请输入你的分数" fs expr $fs + 1 &> /dev/null if [ $? -ne 0 ];then echo "请输入一个数字" exit fi if [ $fs -ge 0 -a $fs -le 60 ];then echo "成绩不及格,请补考" elif [ $fs -gt 60 -a $fs -le 80 ];then echo "成绩合格" elif [ $fs -gt 80 -a $fs -le 100 ];then echo "成绩优秀,恭喜" else echo "成绩应在0-100之间" fi
正则表达式
$ #匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 '\n' 或 '\r'。要匹配 $ 字符本身,请使用 \$。
( ) #标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 \( 和 \)。
* #匹配前面的子表达式零次或多次。要匹配 * 字符,请使用 \*。
+ #匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 \+。
. #匹配除换行符 \n 之外的任何单字符。要匹配 . ,请使用 \. 。
? #匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用 \?。
\ #将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如, 'n' 匹配字符 'n'。'\n' 匹配换行符。序列 '\\' 匹配 "\",而 '\(' 则匹配 "("。
^ #匹配输入字符串的开始位置,除非在方括号表达式中使用,当该符号在方括号表达式中使用时,表示不接受该方括号表达式中的字符集合。要匹配 ^ 字符本身,请使用 \^。
{ #标记限定符表达式的开始。要匹配 {,请使用 \{。
| #指明两项之间的一个选择。要匹配 |,请使用 \|。
限定符:
* #匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于 {0,}。
+ #匹配前面的子表达式一次或多次。例如,zo+ 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。
? #匹配前面的子表达式零次或一次。例如,do(es)? 可以匹配 "do" 、 "does"、 "doxy" 中的 "do" 。? 等价于 {0,1}。
{n} #n 是一个非负整数。匹配确定的 n 次。例如,o{2} 不能匹配 "Bob" 中的 o,但是能匹配 "food" 中的两个 o。
{n,} #n 是一个非负整数。至少匹配n 次。例如,o{2,} 不能匹配 "Bob" 中的 o,但能匹配 "foooood" 中的所有 o。o{1,} 等价于 o+。o{0,} 则等价于 o*。
{n,m} #m 和 n 均为非负整数,其中 n <= m。最少匹配 n 次且最多匹配 m 次。例如,o{1,3} 将匹配 "fooooood" 中的前三个 o。o{0,1} 等价于 o?。请注意在逗号和两个数之间不能有空格。
x|y #匹配 x 或 y。例如,'z|food' 能匹配 "z" 或 "food"。'(z|f)ood' 则匹配 "zood" 或 "food"
[xyz] #字符集合。匹配所包含的任意一个字符。例如, '[abc]' 可以匹配 "plain" 中的 'a'。
#注意!在中括号里面包含 ^ 表示"排除"
[^xyz]#负值字符集合。匹配未包含的任意字符。例如, '[^abc]' 可以匹配 "plain" 中的'p'、'l'、'i'、'n'。
[a-z] #字符范围。匹配指定范围内的任意字符。例如,'[a-z]' 可以匹配 'a' 到 'z' 范围内的任意小写字母字符。
\b #匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
\B #匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。
\d #匹配一个数字字符。等价于 [0-9]。
\D #匹配一个非数字字符。等价于 [^0-9]。
\s #匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
\S #匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
\w #匹配字母、数字、下划线。等价于'[A-Za-z0-9_]'。
\W #匹配非字母、数字、下划线。等价于 '[^A-Za-z0-9_]'。
举例
^[a-z][0-9]$ #匹配以字母开头,以数字结尾
^[^0-9][0-9]$ #匹配以非数字开头,以数字结尾
[^a-z] #除了小写字母以外的所有字符
[^\\\/\^] #除了(\)(/)(^)之外的所有字符
[^\"\'] #除了双引号(")和单引号(')之外的所有字符
^[a-zA-Z_]$ #所有的字母和下划线 _
^a$ #字母a
^a{4}$ #aaaa
^a{2,4}$ #aa,aaa或aaaa
^a{1,3}$ #a,aa或aaa
^a{2,}$ #包含多于两个a的字符串
^a{2,} #如:aardvark和aaab,但apple不行
a{2,} #如:baad和aaa,但Nantucket不行
^[a-zA-Z0-9_]{1,}$ # 所有包含一个以上的字母、数字或下划线的字符串
^[1-9][0-9]{0,}$ # 所有的正整数
^\-{0,1}[0-9]{1,}$ # 所有的整数
^[-]?[0-9]+\.?[0-9]+$ # 所有的浮点数
流程控制语句-正则比对
#判断当前用户是否r开头 [[ "$USER" =~ ^r ]] && echo $? #判断num变量是否为多个数字 [[ $num =~ ^[0-9]+$ ]]&& echo "成立"||echo "不成立"
脚本创建用户
#!/bin/bash read -p "请输入用户名前缀:" q if [[ ! ${q} =~ ^[a-Z]+$ ]];then echo "前缀应为字母组合" quit fi read -p "请输入用户名后缀(应为数字):" w if [[ ${w} =~ ^[0-9]+$ ]];then user=${q}${w} useradd $user echo "123456" | passwd --stdin ${user} &> /dev/null echo "您当前指定的用户名为${user},初始密码为123456" fi
同时创建多个用户
seq 100 #生成100个序列
#!/bin/bash read -p "请输入要创建的用户名" name if [[ $name =~ ^[0-9]+$ ]];then echo "用户名必须是数字" exit fi read -p "请输入要创建的个数" num if [[ $num =~ ^[^0-9]+$ ]];then echo "用户数量必须是数字" exit fi for i in $(seq $num) do user=${name}${i} useradd ${user} &> /dev/null echo '123' |passwd -stdin ${user} &> /dev/null done echo "创建完成,初始密码为123" read -p "请输入要删除的用户名" name read -p "请输入数量" num for i in $(seq ${num}) do user=${name}${i} userdel -r ${user} &> /dev/null done echo "删除完成"
case语句
主要用在对菜单的处理。比if更简单明了,if适合针对一个范围进行判断。case适合等值判断
cat << END ------选项菜单------- 1.----copy----------- 2.----mv------------- 3.----backup--------- --------------------- END read -p "请输入您的选择" n case ${n} in 1) echo "copy" ;; 2) echo "mv" ;; 3) echo "backup" ;; *) echo "不在菜单内" ;; esac
案例:服务启动停止脚本
#!/bin/bash if [ $1 == "start" ];then rsync --daemon echo "rsync已启动" elif [ $1 == "stop" ];then killall rsync echo "rsync已关闭" else echo "请配合start|stop" exit fi #/var/run/ #程序pid日志文件存储目录 sed -i 's/# pid file/pid file/' /etc/rsyncd.conf #启动rsync的pid配置文件 . /etc/init.d/functions case $1 in start) if [ ! -f /var/run/rsyncd.pid ];then rsync --daemon action "rsync running.." /bin/true else action "rsync 已启动" /bin/false fi ;; stop) killall rsync ;; status) echo "状态" ;; *) echo "不在选项内" ;; esac
举例
case启停nginx
#!/bin/bash . /etc/init.d/functions case $1 in start) if [ -f /var/run/nginx.pid ];then action "nginx已在运行状态无法重复运行" /bin/false else sudo systemctl start nginx if [ $? -eq 0 ];then action "nginx启动成功" /bin/true else action "nginx启动失败请检查原因" /bin/false fi fi ;; stop) if [ -f /var/run/nginx.pid ];then sudo systemctl stop nginx if [ $? -eq 0 ];then action "nginx关闭成功" /bin/true else action "nginx关闭失败" /bin/false fi else action "nginx并未在运行" /bin/false fi ;; reload) if [ -f /var/run/nginx.pid ];then sudo systemctl restart nginx if [ $? -eq 0 ];then action "nginx重启成功" /bin/true else action "nginx重启失败" /bin/false fi else action "nginx未在运行中,无法进行重启" /bin/false fi ;; status) if [ -f /var/run/nginx.pid ];then echo "nginx正处于运行状态" else echo "nginx现在未在运行" fi ;; *) echo "请输入start|stop|reload|status" ;; esac
循环语句
#重新定义分隔符 IFS= #累加 ((i=1;i<=100;i++)) #i的初始值为1,当i小于等于一百,i做累加 #结构 for 变量名 in do 循环命令语句 done read -p "请输入最大值" n for i in $(seq ${n}) do echo ${i} done a=1 b=9 for i in {1..9} do let a++ let b-- echo $a:$b done
批量创建用户
echo $((RANDOM)) #生成随机数 echo $((RANDOM))|md5sum #无序乱码随机数 echo $((RANDOM))|md5sum|cut -c 2-10 #截取第二位到第十位
#!/bin/bash if [! $UID -eq 0 ];then echo "非管理员无权访问" exit fi read -p "请输入用户前缀" name read -p "请输入创建数量" num echo "创建用户${name}1到${name}-${num}" read -p "确认创建(y/n)" m case $m in y) for i in $(seq $num) do user=${name}${i} id ${user} &> /dev/null if [ $? -eq 0 ];then echo "${user}已存在" else useradd ${user} pass=$(echo $((RANDOM))|md5sum|cut -c 2-10) echo ${pass}|passwd --stdin ${user} $> /dev/null echo "用户名:${user} 密码:${pass}" >> /sh/user.txt fi done echo "用户已创建完成,信息存放在/sh/user.txt中" ;; n) exit ;; *) echo "请输入y或n" ;; esac
批量探测主机是否存活
#!/bin/bash for i in $(seq 10) do ip=192.168.154.${i} ping -c 1 -w 1 ${ip} &> /dev/null if [ $? -eq 0 ];then echo "${ip} 可到达" else echo "${ip}无法到达" fi echo ${ip} >> /tmp/ip.txt done wait echo "ping 测试结束,端口测试开始" for i in $(cat /tmp/ip.txt) do nmap ${i} |grep 22 &> /dev/null if [ $? -eq 0 ];then echo "${i} 22端口正常" else echo "${i} 22端口未检出" fi done echo "测试完成"
随机点名
#!/bin/bash #随机数公式,得到1-n范围的随机数 #RANDOM%n+1 #sed -n "1p" student.txt #打印student.txt中的第一行 num=$(wc -l /sh/student.txt|awk '{print $1}') for i in $(seq ${num}) do n=$((RANDOM%${num}+1)) sed -n "${n}p" student.txt sleep 1 #暂停一秒 done s=$(sed -n "${n}p" student.txt) echo -e "就是你了:\033[32m $s \033[0m"
随机猜数
while true #无限循环 continue #继续上一次操作 break #退出循环到done后
#!/bin/bash i=0 num=$((RANDOM%100+1)) while true do read -p "请猜一个1-100的数字" s if [[ $s =~ ^[^0-9]+$ ]];then echo "输入错误,请输入1-100的纯数字" continue fi if [ $s -gt $num ];then echo "你猜大了" elif [ $s -lt $num ];then echo "你猜小了" else echo "你真厉害,猜对了" break fi let i++ done echo "你总共猜了$(( $i + 1 ))次"
程序语句
exit #退出程序
break #打断循环执行循环之后的代码
continue #重新开始循环
最后给大家带上函数简单应用以便大家自己去进行拓展
函数与数组
定义函数 命令的集合,用来完成特定的功能; 提前定义函数,在脚本中任意调用函数名。 使用函数使代码模块化,便于重复使用,增加可读性。
#!/bin/bash #函数定义格式: #函数名(){ # shell命令 #} # #或 # #function 函数名 { # shell命令 #} #定义menu函数内容 #menu(){ #定义菜单时,应贴着左侧写 #cat << END #1.创建用户 #2.删除用户 #3.退出程序 #END #} #调用menu #menu menu(){ cat << END 1.创建用户 2.删除用户 3.退出程序 END } input(){ while true do read -p "请输入用户前缀:" name if [[ $name =~ [0-9]+ ]];then echo "前缀不能包含数字" continue fi break done while true do read -p "请输入用户数量" num if [[ $num =~ ^[^0-9]+$ ]];then echo "数量应为数字" continue fi break done } function create { input read -p "将创建${name}1~${name}${num} {y/n}" m case ${m} in y) for i in $(seq $num) do user=${name}${i} id ${user} &> /dev/null if [ $? -eq 0 ];then echo "用户:${user}已存在" else useradd ${user} &> /dev/null pass=$(echo $((RANDOM))|md5sum|cut -c 2-10) echo ${pass}|passwd --stdin ${user} &> /dev/null echo "用户名:${user} 密码:${pass}" >> /tmp/user.txt echo "${user}创建成功" fi sleep 1 done ;; n) ;; *) echo "输入无效应为 y|n" create ;; esac } while true do menu read -p "请对菜单进行选择(1-3)" y case $y in 1) create ;; 2) echo 删除用户 ;; 3) ;; *) echo "选择无效,请选择 1|2|3" ;; esac done