1.shell编程简介
1.1什么是shell编程
- shell命令解释器
- 红帽系列:bash
- Centos/Ubuntu20.04都是bash解释器,Ubuntu之前的命令解释器是dash
- 不同的命令解释器语法格式是有区别的
1.2 开发语言中程序代码的分类
- 编译型:写完后需要编译才能运行,编译完才能运行
- 解释型:书写完成通过命令解释器运行,写完就能运行
1.3书写与执行脚本习惯
1.书写脚本
#!/bin/bash #必须以该命令开头,代表你使用的命令解释器#当然也有其他的命令解释器#!/usr/bin/python#!/bin/sed#!/bin/awk
2.执行脚本
方法1:直接运行,需要添加x权限(用于系统执行脚本)
chmod +x test.sh #设置权限./test.sh #运行脚本 通过当前路径/root/home/test.sh #运行脚本 通过绝对路径
方法2:使用sh运行
#不用给权限,使用命令直接运行bash test.sh #运行脚本
方法3:source或 . 替你在当前环境中 执行1次脚本
source或 . 应用场景:
- 让环境变量生效 source /etc/profile
- 类似include功能:把放在其他位置的配置文件包含进主配置文件中
source /etc/profile #刷新配置文件,其实该文件就是shell脚本. test.sh #运行脚本vim test1.sh #创建脚本,写入以下内容#!/bin/bashsource /etc/init.d/functions #这里就类似将functions中的代码拉入到该脚本中,然后就可以使用了action "web is ok" /bin/true #是因为source了funtions才能使用action
1.4 Shell的编程习惯
- 书写脚本加上第一行的命令解释器
- 版权说明:作者,创建时间,作用,版本号
- 不要添加中文,容易出问题
- 成对的符号
() {} [] '' ""一定要提前写好 - 脚本文件名尽量不要包含文件服务名称,并且要一眼就能看出来脚本作用
1.5 案例编写流程
- 找出操作步骤
- 找出对应的命令
- 测试命令
- 最后书写脚本
1.6 Shell中的变量
1.变量
用一个固定的字符串(英文),替代更多复杂的内容。可以用来放数值,时间等。当你写一个变量就在内存中划分一块区域,你可以使用变量名来调用其中的内容。
2.变量命名规则
- 不能以数字开头
- 要做到看见变量名就知道变量的作用
- 建议使用’_’来连接字符
liao_mysql_isntall.sh -
3.变量分类
环境变量(全局变量) 常是系统创建,也可以自己创建 global var
- 普通变量(局部变量)
- 特殊变量 匹配脚本 参数服务装填 特殊替换
4.环境变量
env #查看环境变量declareexport #三条命令都是查看环境变量/etc/profile #在其中直接添加unset #删除环境变量
- 常见环境变量
| 环境变量 | 含义 | Shell中的用法 |
| —- | —- | —- |
| LANG language | 记录系统字符集 语言 |
| | PS1 | 命令行格式 [\u@\h \W]\$ |
| | PATH | 环境变量,执行命令/系统会在PATH中查找 |
| | UID | 记录用户的UID信息 | 脚本中判断用户是否是root | | HOSTNAME | 主机名 |
| | 历史命令相关 |
|
| | HISTSIZE | history命令记录最多条数 | 在生产环境设置的小一些 | | HISTFILESIZE | history文件记录最多条数 |
| | HISTFILE | 指定历史记录文件的位置 | /root/.bash_history | | TMOUT | 设置离开多久不操作自动断开时间 |
| | HISTCONTROL | 控制history命令是否记录以空格开头的命令 | HISTCONTROL=ignoredups | | PROMPT_COMMAND | 存放的命令/脚本会在下一个命令执行前运行 |
|
5.普通变量
week=3echo $week3echo $weekdayecho $week.day3.dayecho $week_dayecho ${week}_day3_day
6.环境变量有关的文件
[root@localhost ~]# ll -d /etc/profile /etc/bashrc ~/.bashrc ~/.bash_profile /etc/profile.d/-rw-r--r--. 1 root root 2853 4月 1 2020 /etc/bashrc-rw-r--r--. 1 root root 1819 4月 1 2020 /etc/profiledrwxr-xr-x. 2 root root 280 2月 15 11:12 /etc/profile.d/-rw-r--r--. 1 root root 176 12月 29 2013 /root/.bash_profile-rw-r--r--. 1 root root 176 12月 29 2013 /root/.bashrc
| 文件名称 | 存放内容 | 生效范围 |
|---|---|---|
| /etc/profile | 存放环境变量 别名 函数 | 全局范围 |
| /etc/bashrc | 官方说法中存放别名 函数 | 全局范围 |
| ~/.bashrc | 当前用户的别名 | 局部生效 |
| ~/.bashrc_profile | 当前用户的环境变量 | 局部生效 |
| /etc/profile.d/ | 用户登录系统后,执行这个目录下以.sh结尾的脚本 | 自己写个跳板机,跳板机脚本放这里 |
2.特殊变量
应用场景:
- 提高书写脚本执行效率
- 可以更加简单方便判断服务状态,文件目录状态,进程状态。
| 符号 | 含义 | 应用场景 |
|---|---|---|
| $0 | 脚本的名称 | 脚本执行错误给出错误提示或者使用帮助 |
| $n(数字) | 脚本的第n个参数 | 命令中参数传递给脚本,在脚本中使用 |
| $# | 脚本参数的个数,一共有多少个参数 | 脚本开头 判断参数个数是否正确 |
| $* | 取出所有的参数 加上双引号,相当于是1个整体1个参数 | |
| $@ | 取出所有的参数 加上双引号 就是每个都是独立的 |
1.脚本名字 $0
常在脚本出错或者提供帮助时使用
vim 01_test.sh#!/bin/bashecho "使用方法: $0 {start/stop/reload}"sh 01_test.shecho "使用方法: 01_test.sh {start/stop/reload}"
2.位置参数 $n
命令行传参,启动脚本时后面跟着的参数
- 特殊情况:
- $n >= 10 时会出现错误,需要使用${10} ${11}。
- 并且$1test 是可用的 $11会被判定成2个$1 ```bash vim 02_test.sh
!/bin/bash
echo $1 $2 $3 $4
sh 02_test.sh 10 100 1000 10000 10 100 1000 10000
<a name="cXtes"></a>## 3.脚本参数个数 $#脚本参数的个数```bashvim 03_test.sh#!/bin/bashif [ $# -eq 0 ]; thenecho "Usage:$0 [stop|start|reload]"sh 03_test.shecho "Usage:$0 [stop|start|reload]"sh 03_test.sh
4.取出脚本参数 $* $@
| 符号 | 含义 | 区别 |
|---|---|---|
| $* | 取出所有参数 | 加了双引号所有的参数是 一个整体 |
| $@ | 取出所有参数 | 加了双引号所有的参数是 独立的 |
3.特殊变量-返回值
| 符号 | 含义 | 常用/用法 |
|---|---|---|
| $? | 上一条命令的返回值 为0时正常 非0失败 |
判断各种东西是否执行,服务是否成功,用来配置判断 |
| $$ | 当前运行脚本的pid | 在脚本中把pid记录到文件 方便后面进行kill |
| $! | 上一个脚本的的pid | 在脚本中把pid记录到文件 方便后面进行kill |
| $_ | 上一个命令或脚本的最后一个参数 | _环境变量 |
1.查看命令的返回值 $?
上一条命令的返回值,0为正常,非0有错误
案例
检查域名是否可以ping通,通了就显示正常
2>&1:将错误和标准输出都输入到文件
#ping 百度是否可通信ping -c4 www.baidu.com#判断命令执行情况#!通过if判断$?是否成功#优化脚本#!此时的脚本会显示ping的情况,我们将内容重定向#!/bin/bashping -c5 www.baidu.com > /dev/null 2>&1 #如果脚本没有任何提示,则执行成功if [ $? -eq 0 ]; thenecho "baidu.com is ok"fi
2.当前脚本的pid $$
应用场景:
脚本运行的时候,生成一个pid文件,方便以后kill
vim 09_pid.sh#!/bin/bashecho $$ > /var/run/first.pid #查看当前脚本pidsleep 9999sh 09_pid.sh & #后台执行

killcat /var/run/first.log``
3.上一个运行的脚本的pid $!
sh 09_pid.sh &[1] 3153echo $!3153
4.上一个命令或者脚本的最后一个参数 $_
相当于按了 esc + .

案例
制作一个ping命令脚本,能够确定网站是否通信,并且显示域名与成功与否
#!/bin/bashurl=$1ping -c5 -W0.5 -i0.1 $url > /dev/null 2>&1if [ $? -eq 0 ]; thenecho "$url is ok"elseecho "$url is field"fi
4.变量子串
案例
一个英语句子,显示这串字符中 单词字符大于6的单词。
- 流程分析
- 一句话,进行分割
- 分割后的单词如果大于6
- 则进行显示 ```shell
!/bin/bash
text=echo I am liao jiang,I like my family.| tr '.,' ' '
for i in $text do if [ ${#i} -gt 3 ]; then echo $i fi done
**AWK实现**<br />-F 指定输入文件折分隔符<br />-RS 记录分隔符(默认是一个换行符)<br />-v 赋值一个用户定义变量。```shellecho I am liao jiang,I like my family. | awk -F '[,. ]' '{for(i=1;i<=NF;i++)if(length($i)>3)print $i}'echo I am liao jiang,I like my family. | awk -vRS="[,. ]" 'length()>3'
2.字符截取 切片
${变量:起点} 从起点显示到结束
${变量:起点:长度} 从起点开始显示最多长度个字符
name=liao996.icuecho ${name:4}#996.icuecho ${name:2}#ao996.icuecho ${name:2:6}#ao996.
3.删除
${变量#字符} 左边开始(开头)
${变量%字符} 右边开始(结尾)*从只查询开头变为从开头查询全部的第一个两个##或%% 从开头或者末尾查询全部
echo ${test#I} #纯纯的只判断开头#am oldboy teacherecho ${test#am} #因为只判断开头,所以这里什么都没修改#I am oldboy teacherecho ${test#*o}#ldboy teacherecho ${test##*a}#cherecho ${test%a*} #从末尾删除到该行出现的第一个a#I am oldboy teecho ${test%%a*} #从末尾删除到该行出现的最后一个a#I
案例
获得一个路径的时候,想要获取文件名和路径文件夹
name=/etc/systemctl/ifconfig/123.txtecho ${name##*/}#123.txtecho ${name%/*}#/etc/systemctl/ifconfig
4.字符串替换
${变量/字符/想要替换的字符}//多加一个 “/“ 就是变成全部替换
echo ${name/123.txt/qwe.txt}#/etc/systemctl/ifconfig/qwe.txtecho ${name//s/_} #替换全部的字符/etc/_y_temctl/ifconfig/123.txtecho ${var//[a-z]/.} #使用正则,将所有的字母设置为...123...
5.变量扩展
- 给变量设置默认值 | 内容 | 含义 | 简单理解 | | —- | —- | —- | | ${p:-word} | 如果p没有被赋值或者值为空,word就作为他的值 | 没内容就用我的 | | ${p:=word} | 如果p没有被赋值或者值为空,word就作为他的值,并且将word赋值给p | 没内容就赋值为我的值 | | ${p:?word} | 如果p没有被赋值或者其值为空,那么就把word作为错误输出,否则显示p内容 | 没内容就把我当做报错输出,有内容就显示变量内容 | | ${p:+word} | 如果p没有被赋值或者其值为空,就什么都不做,否则用word替换变量内容 | 没内容啥都不做,有内容就用我的 |
6.变量赋值与read
- 直接赋值:name=liao,url=$1
- 引用其他命令结果进行赋值:ip=’hostname -I | awk ‘{print $2}’’
- 交互式变量赋值:read -s 不显示输入信息,-t 超时时间, -p指定输出/提示
- 脚本传参:shell表示位置的特殊变量 $1 $2 $3
read交互式赋值
-p 显示设置的提示
-s 不显示输入的内容,可以用来设置密码
-t 设置超时时间,单位为秒
-p 参数一定要在最后
read -p "input url or ip: " addr#input url or ip: 192.168.1.1echo $addr192.168.1.1
7.运算
案例:
echo $RANDOM #取随机数,0-2的15次方echo $(($RANDOM%10)) #取10的余数,就是0-9的随机数
7.1运算方式
$(())
在$(())中运算变量,并且无法直接计算小数
echo $(1+1)echo 1+1echo (1+1)#上面这些操作都无法运算echo $((1+1))2echo $((2**2))4echo $((100%10))0n1=111n2=222echo $((n1+n2))333n3='echo $((n1+n2))'echo $n3333((n4=n1+n2+n3))echo $4666
Let
赋值并运算,并且支持++,—
n1=111n2=234let n3=n1+n2echo $n3345
expr
还可以判断两个字符是否是数字,并且 需要反斜杠转义 \
expr 1+1 #必须要加 空格1+1expr 1 + 1 #此时才能正确运算2expr 5 * 5 #运算乘法需要添加转义符expr: syntax errorexpr 5 \* 525expr 5 '*' 525expr 1 + 1echo $?0expr aa + 1echo $?2
bc
bc是一个计算器工具
yum install -y bc 安装需要的bc工具
可以浮点运算,平方次方运算
echo 1+1 | bc2echo $n1*$n2 | bc28782echo 2^10 | bc1024#也可以输入bc进入工具 直接使用echo "obase=16;16"|bc10echo "obase=16;15"|bcFecho "obase=16;14"|bcE
expr还可以对字符串操作
expr length "string" #获取字符串长度6expr substr "string" 2 5 #截取字符串tringexpr substr "string" 2 4trinexpr index "string" ing #获取字符在字符串中出现的位置4expr match "string" s.* #获取字符串开始字符出现的长度6expr match "string" str3
$[] ★
也无法直接计算小数
echo $[123+321]444echo $[123**3]1860867
awk
awk也可以进行运算,并且显示小数,显示多个运算。
awk 'BEGIN{print 1/3,2**10}'0.333333 1024#想要计算变量,需要特殊操作 -vx=1y=3awk -vn1=1 -vn2=3 'BEGIN{print n1/n2}'0.333333awk -vn1=$x -vn2=$y 'BEGIN{print n1/n2}'0.333333
总结
| 方法 | 用法 |
|---|---|
| awk ‘BEGIN{}’ | 在脚本中进行统计计算 -v |
| echo+ bc -l | 小数,进制化转化 |
| $(()) | 进行整数计算 |
| let | |
| expr | 检查变量或参数是否为数字 |
| $[] |
案例
书写简单的计算器
!/bin/bash
expr $1 + $2 >/dev/null 2>&1 if [ $? -eq 0 ]; then awk -vn1=$1 -vn2=$2 “BEGIN{print n1+n2,n1-n2,n1*n2,n1/n2}” else echo “error!” fi
使用read制作计算器```shell#!/bin/bashread -p "请输入第一个数字: " a1read -p "请输入第二个数字: " a2expr $a1 + $a2 > /dev/null 2>&1if [ $? -eq 0 ]; thenawk -vn1=$a1 -vn2=$a2 'BEGIN{print n1+n2,n1-n2,n1*n2,n1/n2}'elseecho "error!!!!!!"fi
8.条件测试语句
- 以后用于各种判断中的条件
- 条件测试语句类型
- 文件相关表达式
- 数字对比
- 字符串对比
- 逻辑的 与 或 非
条件测试语句格式:
| 格式 | 作用 |
|---|---|
| [ <条件> ] | 一般情况 |
| [[ <条件> ]] | []升级版,支持正则表达式 |
| (( <条件> )) |
1.文件相关
| 名称 | 含义 |
|---|---|
| -d | directory目录是否存在 |
| -f | file是否存在 |
| -e | exist是否存在,不管是文件,文件夹 |
| -r | read文件是否存在,并且是否有r权限 |
| -w | write文件是否存在,并且是否有w权限 |
| -x | execute文件是否存在,并且是否有x权限 |
| -s | 判断文件是否为空,空文件时为false |
| -L | Symlink文件是否存在,是否为软链接 |
| f1 -nt f2 | file1 newer than file2 比较创建时间新 |
| f1 -ot f2 | file2 older than file2 比较创建时间晚 |
[ -f /etc/hosts ] && echo 存在 || echo 不存在#存在[ /etc/ -nt /root/1.txt ] && echo 'true' || echo 'false'#false
2.脚本的判断简写
&& cmd1 && cmd2 前一个命令执行成功,再执行后面的命令
|| cmd1 && cmd2 前一个命令执行失败,再执行后面的命令
案例优化
针对前面的计算机脚本的优化
#!/bin/bash[ $# -ne 2 ] && {echo "error!!!"exit 1}expr $1 + $2 >/dev/null 2>&1if [ $? -eq 0 ]; thenawk -vn1=$1 -vn2=$2 "BEGIN{print n1+n2,n1-n2,n1*n2,n1/n2}"elseecho "error!"fi
3.字符串的对比
| 表达式 | 含义 |
|---|---|
| -n | net zero 如果变量/字符串不是空则成立 |
| -z | zero 如果变量/字符串是空 则成立 |
| “n1”=”n2” | 判断两个字符串/变量内容 是否一致 如果相等则成立 |
| “n1”!=”n2” | 判断两个字符串/变量内容 是否一致 如果不相等则成立 |
name=liao[ -n "$name" ] && echo "成立" || echo "失败" #判断是否不为空成立[ -z "$test" ] && echo "成立" || echo "失败" #判断是否为空成立name1=liao[ "$name"="name1" ] && echo "成立" || echo "失败"成立[ "$name" = "$name1" ] && echo "成立" || echo "失败"成立[ "$name" != "$name1" ] && echo "成立" || echo "失败"失败
4.常用的shell脚本
1.删除开头注释
egrep -v '#|^$' sshd_configsed -r '/#|^$/d' sshd_config#-r 支持正则表达式#d 表示删除awk '!/#|^$' sshd_config
2.查看主机名,IPv4地址,版本,内核版本
hostname #查看主机名hostname -I | awk '{print $1}' #IPv4地址cat /etc/redhat-release #查看版本uname -r #查看内核版本
3.获得当前日期,时间,用户名和当前目录
date +%Fdate +%Twhoamipwd
4.将文件中的小写字母转换为大写字母
tr 'a-z' 'A-Z' < passwdawk '{print toupper($0)}' passwd #$0 整行sed 's#[a-z]#\U&#g' passwd #& 表示前面匹配到的小写字母 \U 转换为大写
5.检测当前用户是否为root,如果是则用yum安装vsftpd
#查看uid是否为0#取出当前用户名#!/bin/bashif [ $UID -ne 0 ]; thenecho "error!"exit 1elseyum install vsftpd -yfi#!/bin/bashname=`whoami`if [ $name -ne "root" ]; thenecho "error!"exit 1elseyum install vsftpd -yfi
6.设计一个shell程序,在每月第一天备份并压缩/etc目录的所有内容,存放在/root/bak目录中,且文件名为yymmdd_etc。shell程序fileback存放在/usr/bin目录下
#shell+定时任务+备份#1.检查目录和备份文件是否存在#2.创建指定的文件夹#3.打包压缩#!/bin/bashdir=/root/baktime=`date +%y%m%d`[ -d $dir ] || mkdir -p $dirtar zcf ${dir}/${time}_etc.tar.gz /etc/crontab -e#backup /etc/ by liao at 2022-3-2700 00 01 * * /bin/sh /usr/bin/filebak &>/dev/null
7.统计当前Linux系统中可以登录的账户有多少个。
命令用户解释器是/bin/bash的
grep '/bin/bash' /etc/passwd| wc -lgrep -c '/bin/bash' /etc/passwd
8.删除字符串中的所有空格
str='I am liao,I like Linux!!! wuhu~'echo ${str// /}echo $str|tr -d ' 'echo $str|sed 's# ##g'
9.在脚本文件中重定向标准输出和标准错误流到log.txt
cmd &> /tmp/log.txtcmd > /tmp/log.txt 2>&1
9.条件判断
1.if语法
if判断,适用只需要一步判断,条件返回真时执行命令或者条件返回假执行命令。
| 括号类型 | 用法 |
|---|---|
| [] | 条件判断 |
| [[]] | 在条件中使用通配符 |
| (()) | 在条件中植入数学表达式 |
if [ 条件判断 ]thencommandsfi
如果登录用户是root则提示管理员你好,如果是普通用户则提示guest你好
#!/bin/bashif [ $USER == 'root' ]thenecho "管理员,你好"elseecho "guest,你好"fi
判断$1 $2两个整数的关系
#!/bin/bashif [ $1 -eq $2 ]thenecho "$1=$2"elif [ $1 -gt $2 ]thenecho "$1 > $2"elseecho "$1 < $2"fi
查询字符串中,那些是以r开头的
#!/bin/bashfor i in rr1 rrr2 rr3 lw fc rr5doif [[ $i == r* ]]thenecho "$i"fidone
案例
判断 crond 进程是否运行
#!/bin/bashNAME=crondNUM=$(ps -ef|grep $NAME | grep -vc grep)if [ $NUM -eq 1 ]thenecho "$NAME is alived"elseecho "$NAME is not running"fi
根据发行版不同来安装程序
#!/bin/bashif [ -e /etc/redhat-release ]thenyum install -y wgetelif [ $(cat /etc/issue | cut -d'' -f1) == "Ubuntu" ]thenapt-get install wget -yelseecho "I don't know"fi
2.for循环
脚本在执行任务的时候,总会遇到需要循环执行的时候2,比如说我们需要脚本每隔5分钟执行一次ping命令的操作。除了计划任务,我们还可以用脚本来完成。此时就需要循环语句。
for 变量名 in 取值列表; do命令donefor 变量名 in 取值列表do命令donefor 变量名 in 取值列表{命令}#甚至还有一套c语言风格的语法for ((i=1;i<=5;i++)); do # 也可以 i--echo $idone
打印输出1-9
#!/bin/bashfor i in `seq 1 9`{echo $i}
输出输入的字符
#!/bin/bashfor i in "$@" #脚本输入的的参数赋值给$i{echo $i}#!/bin/bashfor i in 12 13 14 15 16 #自己输入的参数赋值给$i{echo $i}
3.while语句
while 循环用于不断执行一系列命令,也用于从输入文件中读取数据。其语法格式为:
while 条件表达式; do命令done
循环打印1-5
#!/bin/bashN=0while [ $N -lt 5 ]dolet N++ #++ 我们使用letecho $Ndone
无限循环
主要就是将while后的判断为true,或者状态为0。第一个就是为true,第二个使用 : 就是为0。
#!/bin/bashwhile true;doecho "yes"donewhile :; doecho "yes"done
while逐行读取文件内容
推荐第二种形式
#!/bin/bashDIR1=$1cat $1 | while read LINE; doecho $LINEdone#!/bin/bashDIR1=$1while read LINE; doecho $LINEdone < $DIR1
4.until
until 循环执行一系列命令直至条件为 true 时停止。
until 循环与 while 循环在处理方式上刚好相反。
一般 while 循环优于 until 循环,但在某些时候—也只是极少数情况下,until 循环更加有用。
until 语法格式:
until conditiondocommanddone
condition 一般为条件表达式,如果返回值为 false,则继续执行循环体内的语句,否则跳出循环。
以下实例我们使用 until 命令来输出 0 ~ 9 的数字:
#!/bin/basha=0until [ ! $a -lt 10 ]doecho $aa=`expr $a + 1`done
5.break和continue
在循环过程中,有时候需要在未达到循环结束条件时强制跳出循环,Shell使用两个命令来实现该功能:break和continue。
break命令允许跳出所有循环(终止执行后面的所有循环)。
continue命令与break命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环。
创建无限循环,当N=1000时停止
#!/bin/bashN=2while true; dolet N++if [ $N -eq 1000 ]thenecho $Nbreakfidone
1-100打印偶数
#!/bin/bashfor N in {1..100}; doif (( $N%2 == 0 )); thenecho $Nfidone
6.case语句
case … esac 为多选择语句,与其他语言中的 switch … case 语句类似,是一种多分支选择结构,每个 case 分支用右圆括号开始,用两个分号 ;; 表示 break,即执行结束,跳出整个 case … esac 语句,esac(就是 case 反过来)作为结束标记。
可以用 case 语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令。并且支持正则表达式
case … esac 语法格式如下:
case 值 in模式1)command1command2...commandN;;模式2)command1command2...commandN;;esac
case 工作方式如上所示,取值后面必须为单词 in,每一模式必须以右括号结束。取值可以为变量或常数,匹配发现取值符合某一模式后,其间所有命令开始执行直至 ;;。
取值将检测匹配的每一个模式。一旦模式匹配,则执行完匹配模式相应命令后不再继续其他模式。如果无一匹配模式,使用星号 * 捕获该值,再执行后面的命令。
模仿脚本的start restart stop
#!/bin/bashcase $1 instart)echo "this jb is starting";;restart)echo "this jb is restarting";;stop)echo "this jb is stopping";;*)echo "Usage: $0 {start|restart|stop}"esac
7.select语句
select 是一个类似于 for 循环的语句。 在for循环中,我们指定的变量群他会自动逐个赋值循环,而用了select,我们自己从变量群中选择某个字符循环。
#!/bin/bashselect mysql_version in 5.1 5.6; doecho $mysql_versiondone[root@hecs-215335 ~]# sh 20_select1.sh1) 5.12) 5.6#? 15.1#? 25.6
用户输入编号会直接赋值给变量 mysql_version。作为菜单用的话,循环第二次后就不再显示菜单 了,并不能满足需求。 在外面加个死循环,每次执行一次 select 就 break 一次,这样就能每次显示菜单了:
#!/bin/bashwhile true; doselect mysql_version in 5.1 5.6; doecho $mysql_versionbreakdonedone[root@hecs-215335 ~]# sh 21_select2.sh1) 5.12) 5.6#? 15.11) 5.12) 5.6#? 25.61) 5.12) 5.6#? 15.11) 5.12) 5.6#?
如果再判断对用户输入的编号执行相应的命令,如果用 if 语句多分支的话要复杂许多,用 case 语 句就简单多了。
#!/bin/bashwhile true; doselect mysql_version in 5.1 5.6 5.8 quit; docase $mysql_version in5.1)echo "mysql 5.1"break;;5.6)echo "mysql 5.6"break;;5.8)echo "mysql 5.8"break;;quit)echo "exit,Bye~"exit;;*)echo "you input error"breakesacdonedone
10.函数
linux shell 可以用户定义函数,然后在shell脚本中可以随便调用。
shell中函数的定义格式如下:
[ function ] funname [()]{action;[return int;]}
说明:
- 1、可以带function fun() 定义,也可以直接fun() 定义,不带任何参数。
- 2、参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return后跟数值n(0-255)
```shell
!/bin/bash
demofunc(){ echo “wuhu” } demofunc
wuhu
<a name="FVgGN"></a>## 1.函数返回值return 在函数中定义状态返回值,返回并终止函数,但返回的只能是 0-255 的数字,类似于 exit。```shell#!/bin/bashfunc() {VAR=$((1000+1234))return $VARecho "this is a function"}funcecho $?186
2.函数传参
通过 Shell 位置参数给函数传参。
#!/bin/bashfuntest(){echo $1echo $2echo $3echo $*}funtest 1 23 232312323231 23 2323
并且还支持递归
11.数组
数组是相同类型的元素按一定顺序排列的集合。 数组中可以存放多个值。Bash Shell 只支持一维数组(不支持多维数组),初始化时不需要定义数组大小(与 PHP 类似)。与大部分编程语言类似,数组元素的下标由 0 开始。
Shell 数组用括号来表示,元素用”空格”符号分割开,语法格式如下:
array_name=(value1 value2 ... valuen)
定义方法:
定义方法 1:初始化数组 array=(a b c) 定义方法 2:新建数组并添加元素 array[下标]=元素 定义方法 3:将命令输出作为数组元素 array=($(command))
创建并获取数组
#!/bin/bashmy_arrys=("abc" "1231" "bsvf" 666)echo ${my_arrys[0]}echo ${my_arrys[1]}echo ${my_arrys[2]}echo ${my_arrys[3]}echo ${my_arrys[*]}echo ${my_arrys[@]}abc1231bsvf666abc 1231 bsvf 666abc 1231 bsvf 666
获取数组长度
#!/bin/bashmy_arrys=("abc" "1231" "bsvf" 666)echo ${#my_arrys[@]}echo ${#my_arrys[*]}44
数组的添加与删除
my_arrys=("abc" "1231" "bsvf" 666)my_arrys[4]="qwq" #添加一个元素echo ${my_arrys}abc 1231 bsvf 666 qwqmy_arrys+=("avc" "ghz" "casd") #添加多个元素echo ${my_arrys}abc 1231 bsvf 666 qwq avc ghz casdunset my_arrys[2] #删除第三个元素echo ${my_arrys}abc 1231 666 qwq avc ghz casdunset my_arrys #删除数组
生成指定数量的随机数放入到数组中
#!/bin/bashfor ((i=1;i<=$1;i++)); doarray[i]=$((RANDOM%10))doneecho ${array[*]}
