a脚本调试:
检测脚本中的语法错误: bash -n 文件名
注: 只能检测 语法错误 并不能检测命令语法不存在;
调试执行:bash –x 脚本名 / sh -x 脚本名 ,该方法是通过一行一行执行,有报错的后会提示出来。
解释器是一种命令解释器,主要作用是对命令进行运行和解释,将需要执行的操作传递给操作系统内核并执行,shell 常见的解释器有:
#!/bin/bash (默认)
#!/bin/ksh
#!/bin/bsh
#!/bin/sh
shelll脚本编程:
变成语言的分类:根据运行方式
编译运行:源代码–>编译器(编译)–>程序文件
解释运行:源代码–>运行时启动解释器,由解释器边解释边运行;
编辑模型:过程式编程语言,面向对象的变成语言
程序=指令+数据
过程式:以指令为中心来组织代码,数据是服务于代码
顺序执行
选择执行
循环执行
对象式:以数据为中心来组织代码,围绕数据来组织命令;
类(class):实例化对象,
shell脚本命令的工作方式有两种:交互式和批处理
交互式:用户每输入一条命令就立即执行
批处理:由用户事先编辑好的一个完整的shell脚本,shell会一次性执行脚本中的诸多命令。
查看默认命令行终端解释器:echo $SHELL
配置提示符:username@hostname$ 或root@hostname # 或简单的显示为$/#
$表示普通用户,#表示管理员用户root。
如何写shell脚本:
脚本文件的第一行:给出shebang,解释器路径,用于指明解释器程当前脚本的解释器文件
shell脚本通常以shebang起始:#!/bin/bash
shebang是一个文本行,其实#!位于解释器路径之前,/bin/bashi是Bashi的解释器命令路径。将以#
编写一个简单的shell脚本:
vim ls.sh
#!/bin/bash
#后面跟注释内容,方便以后打开能知道这脚本是干啥的
pwd
ls -al
运行脚本:sh ls.sh
另外一种运行方式 ./ls.sh 但这种需要执行权限 :chomd +x ls.sh 即可
直接写进脚本里的方式:
1) 赋予执行权限,并直接运行次程序文件:
写一个简单但能接收用户输入参数的shell脚本:
vim ex.sh
#!/bin/bash
echo “当前脚本名称为 0 " e c h o " 总 共 有 0" echo "总共有 0"echo"总共有#个参数,分别是$*。”
echo “第一个参数为$1,第五个参数为$5。”
运行脚本:sh ex.sh one two three four five six serven
运行结果:当前脚本名称为ex.sh
总共有7个参数,分别是one tow three four five six serven
第一个参数为one,第五个参数为five
bash的配置文件;
两类:
profile类:为交互式登陆的shell进程提供配置
bashrc类:为非交互式登陆的shell进程提供配置
登陆类型:
交互式登陆shell进程:
直接通过某终端输入账号和密码后打开的shell进程;
使用su命令:su - USERNAME,或者使用su -| USERNAME执行的登陆切换
非交互式登陆shell进程:
su USERNAME执行的登陆切换
图形界面下打开的终端
运行脚本
profile类:
全局:对所有用户都生效
/etc/profile
/etc/profile.d/*.sh
用户个人:仅对当前用户有效:
~/.bash_profile
功能:
1:用于定义环境变量
2:用于命令或脚本
bashrc类:
全局:
/etc/bashrc
用户个人:
~/.bashrc
功能:
1:定义本地变量
2:定义命令别名
注意:仅管理员可修改全局配置文件
交互式登陆shell进程;
/etc/profile --> /etc/porfile.d/* .sh--> ~/.bashrc --> /etc/bashrc
非交互式登陆shell进程:
~/.bashrc --> /etc/bashrc --> /etc/profile.d/*.sh
命令行中定义的特性,例如变量和别名作用域为当前shell进程的生命周期;
配置文件定义的特性,只对随后新启动的shell进程有效。
如:添加一个仅对当前用户有效的bash命令:
vim .bashrc
alias cls=‘clear’
不会立即生效 需要 . .bashrc 后才会生效
当前用户 执行cls命令 即clear命令
如:让所有用户登陆的时候会收到一个自定义提示和当前时间:
vim /etc/profile.d/tishi.sh
echo "hello times: `date` "
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200313213648980.png)
如:定义一个java变量:
vim /etc/profile.d/java.sh
export JAVA_HOME=/user 注:export是定义变量的命令
重读一下 . /etc/profile.d/java.sh 生效
export 查看
让通过配置文件定义的特性立即生效:
1) 通过命令行重复定义一次;
2) 让shell进程重读配置文件;
2. source /PATH/FROM/CONF_FILE
2. ./PATH/FROM/CONF_FILE
提取ip:
ifconfig | egrp -o "'\<(([0-9] | [1-9] [0-9] | 1[0-9] [0-9] | 2[0-4] [0-9] | 25[0-5])\.) {3} ([0-9] | [1-9] [0-9] | 1[0-9] [0-9] | 2[0-4] [0-9] | 25[0-5])\>"
查看 脚本运行路径: hash
删除其中一个路径: hash -d 名称
删除全部路径: hash -r
‘’ :单引号将其中的内容都作为了字符串来,忽略所有的命令和特殊字符,类似于一个字符串的用法
“” :双引号与单引号的区别在于其可以包含特殊字符(单引号直接输出内部字符串,不解析特殊字符;双引号内则会解析特殊字符),包括’, ", $, ,如果要忽略特殊字符,就可以利用\来转义,忽略特殊字符,作为普通字符输出:
`` :反引号用来包含一个命令字符串的,其中的命令会先执行,得到的结果会返回到层命令再执行:
正确的话,返回值是0
不正确的话返回值有很多类型 但为非0 即为不正确
返回值纪录在$?
里(使用方法,先执行一个命令,然后执行echo $?
返回值是0则正确0则不正确)
返回值$?
仅纪录上一条执行是否成功,不仅输入错误会返回非0值,逻辑错误也会返回非0值,逻辑错误有很多,未查询到结果,ping一个ip不同也属于逻辑错误。。。
在编写shell脚本的时候我们要querString上一条命令有没有执行成功,可以通过 ? 返 回 值 判 断 。 再 比 如 : 现 在 查 看 g r u p 密 码 是 否 设 置 了 , 可 以 通 过 ?返回值判断。 再比如:现在查看grup密码是否设置了,可以通过 ?返回值判断。再比如:现在查看grup密码是否设置了,可以通过?来判断,如下
#! /bin/bash
grup_pwd=`cat /etc/grub.conf | grep -v ^# | grep password 2> /dev/null`
if [ $? -eq 0 ];then #返回值是否等于0
echo " [ √ ] 已设置grub密码,符合要求" #等于0
else
echo " [ X ] 没有设置grub密码,不符合要求,建议设置grub密码" #不等于0
fi
写一个简单的脚本测试,如:写一个只有root用户才能执行的脚本,其他用户则提示指定内容后exit退出当前脚本
变量是可变的值
变量名=值
变量名可以包含_,数字,大小写字母,但绝对不可以数字开头
=两边不能有空格
值,如果含有空格的话,要使用’ ’ 或者 " " 引起来
定义变量的时候,变量名前是不需要加$
的。
特点:只能影响当前的shell ,不能影响子shell,关系图如下 (在子进程中定义永久变量(export) 只会影响子进程,不会影响父进程(bash进子进程,子进程中再bash便是子进程的子进程了)
echo $$
查看当前进程id ,父进程id和 子进程id不一样
关于不同执行方式,执行环境也不同,可能是在父进程执行,也可能是在子进程执行,如
bash定义变量是不会影响 子进程,但export定义变量会影响子进程(也可以说 同步到子进程)如:
如:脚本中需要多次使用到一个较长的值,可以定义为变量,后面直接调用变量即可
查看环境变量:echo $PATH , export 或 declare -x
查看已定义的所有变量:set
删除变量:unset name
查看系统自带配置文件:cat /etc/profile
echo $UID - 查看当前用户uid
echo $USER - 查看当前用户
echo $HOME - 查看当前用户家目录
echo $PS1(数字1) - 查看提示符(如:[root@control ~]# ) 详细参考:https://blog.csdn.net/cuichongxin/article/details/103949335
echo $PS2 - 换行提示符
echo $PATH (很重要)- 当我们执行命令的时候,一定要指定这个命令的路径,如果没有写路径,则会到PATH里 所规定的的路径里 进行查询。详细参考:https://blog.csdn.net/cuichongxin/article/details/103950519
在字符界面登陆终端的时候,首先会运行家目录下面的一个隐藏文件: .bash_profile 位置变量。
预定义变量:双引号—> 是能够解析双引号里特殊字符的 单引号—>忽略单引号里所有的特殊字符 ``—>相当于$0
位置变量 主要是向脚本中传递数据。
set命令作用主要是显示系统中已经存在的shell变量,以及设置shell变量的新变量值。set命令不能够定义新的shell变量。如果要定义新的变量,可以使用declare命令以变量名=值的格式进行定义即可。
测试,10以上需要用{}括起来,比如${10}代表接收的第10个参数,如果不加{},会以为是$1+后面的参数
比如说,我定义一个aa为book,花了10美元($10),这时不加{}的效果和加{}的效果如下
更加直观的看出 {} 的区别,现在定义一个dir为/root/目录,然后再次使用dir
@ 与 @与 @与#的区别在于,比如有4个值,使用#@会循环4次,如果使用$#只循环一次(会将所有参数看作一个整体),如下
#!/bin/bash
echo "\s* 效果为 : "
for i in "$*"
do
echo $i
done
echo "\s@ 效果为 : "
for j in "$@"
do
echo $j
done
说一下位置路径中的 basename 和 dirname的使用
basename可以用于,脚本中读取 $0的文件名称,因为$0 也是脚本名称 加上basename后便看不到路径了 : basename $0 即可
#!/bin/bash
echo "脚本的名字是 `basename $0`"
echo "输入的第一个参数是 $1"
echo "输入的第二个参数是 $2"
echo "输入的第三个参数是 $3"
echo "一共输入了 $# 个参数,分别为 $*"
#!/bin/bash
if [ $# -eq 0 ] ; then
echo "请加上需要查询的用户名参数"
exit 1
fi
grep -q $1 /etc/passwd
if [ $? -eq 0 ] ; then
echo "$1 用户是存在的"
else
echo "$1 用户不存在"
fi
||
> 重定向
>> 不会覆盖原有内容 的重定向
; 一行 执行多条命令分隔符
| 管道符
&& 与: 前面的命令执行成功,后面的命令才会执行
|| 非:前面的命令执行失败,后面的命令才会执行
2> /dev/null 错误输出到 指定文件
1> /dev null 正确输出到 指定文件
秒变计算器的运算符 expr 仅支持整数
加:expr 12 + 12
减:expr 12 - 12
乘:expr 12 * 12
除:expr 12 / 12
求余:expr 12 % 12
平方:expr 12 ** 12
科学计算器: bc 注:如果没安装bc命令,可直接用yum安装: yum install -y bc
bc计算器保留多少位小数可以通过scale定义,但是scale只对除法、取余数、乘幂 有效;其他可用除1方法来实现scale功能; 如保留2位数 scale=2;
方法一: 直接输入命令bc 进入计算器模式
方法二: 使用echo 定义参数 用管道符 来输出结果:
&&(与) ||(或)
连接符一般需要判断2个条件,1:整体上是真还是假 2:当判断1完成后,是否要进行判断2
判断1 &&(或) 判断2 :两边为真则真 ($?返回值是0),如果判断1为真,执行判断2 判断2为假 则整体为假 ,如果判断1为假,则不执行判断2
判断1 ||(非) 判断2 :一边为真则整体为真,如果判断1为真 则不执行判断2 ,如果判断1为假($?返回值不为0)则执行判断2,判断2为假 则整体为假
-eq 等于 (equal)
-ne 不等于(not equal)
-gt 大于(greater than)
-lt 小于 (lesser than)
-ge 大于或者等于(greater or equal)
-le 小于或者等于(lesser or equal)
小数(浮点型):Bash中常用的let、expr仅支持整数运算,不支持浮点数计算。要实现浮点数计算,可以使用bc或awk。
字符串(字母)比较其实是自动转换为ASCII码的,虽然比较的是字母,其实系统看到的也是其字母对应的ASCII码而已,如a的ASCII码是97,b就是98
= 相等
!= 不相等
> 大于
>= 大于等于
< 小于
<= 小于等于
[] 是 不识别通配符的,[[]]识别通配符
注: 如果是等于需要使用正则,建议使用: =~ 而非 ==
一个简单的判断数值相等与否的shell:
#! /bin/bash
#判断用户输入的两个数是否相等
#ccx
if [ $1 -eq $2 ] ;
then
echo "$1 等于 $2"
else
echo :$1 不等于 $2"
fi
#! /bin/bash
#创建用户输入的名称 文件
touch $1
if [ $? -eq 0 ] ; then
# 返回0 代表 执行成功 与之相反;
echo "$1 创建成功"
fi
echo "请输入需要创建的文件名称"
顾名思义 read 就是需要用户输入值 比如用于输入密码之类的
原理:read 默认有一个值 $REPLY ,即使单独单独输入read不调用值回车 也会让你输入值
read命令: 先后顺序 t、n、s、p
语法 :read -p “请您输入密码:”
-p:给出提示符,默认不支持“\n”换行 需要echo -e “\n” 实现
-s:隐藏输入的内容
-t:给出等待时间
-n:限制读取字符的个数,触发到临界值会自动执行;
如:现在写一个 根据你输入的年龄判断 该年龄属于什么阶段,并且输入非数字时会提示你输入数字
#!/bin/bash
#echo -n "请输入一个年龄"
#read age
read -p "请输入一个年龄:" age
[[ $age =~ ^[0-9]+$ ]]
if [ $? -ne 0 ] ; then
echo "请输入一个数字"
exit 1
fi
if [ $age -gt 120 ] || [ $age -lt 0 ] ; then
echo "请输入一个合法的年龄"
elif [ $age -ge 60 ] && [ $age -lt 120 ] ; then
echo "该年龄为老年人"
elif [ $age -ge 18 ] && [ $age -lt 60 ] ; then
echo "该年龄为成年人"
else
echo "未成年"
fi
语法:echo -e “\033[字背景颜色;字体颜色;特效m字符串\033[关闭属性”
注:一下中文字部分 可以替换任何内容
#字体色差范围:30-37
echo -e "\033[30m 黑色字 \033[0m"
echo -e "\033[31m 红色字 \033[0m"
echo -e "\033[32m 绿色字 \033[0m"
echo -e "\033[33m 黄色字 \033[0m"
echo -e "\033[34m 蓝色字 \033[0m"
echo -e "\033[35m 紫色字 \033[0m"
echo -e "\033[36m 天蓝字 \033[0m"
echo -e "\033[37m 白色字 \033[0m"
#字背景颜色范围:40-47
echo -e "\033[40;37m 黑底白字 \033[0m"
echo -e "\033[41;30m 红底黑字 \033[0m"
echo -e "\033[42;34m 绿底蓝字 \033[0m"
echo -e "\033[43;34m 黄底蓝字 \033[0m"
echo -e "\033[44;30m 蓝底黑字 \033[0m"
echo -e "\033[45;30m 紫底黑字 \033[0m"
echo -e "\033[46;30m 天蓝底黑字 \033[0m"
echo -e "\033[47;34m 白底蓝字 \033[0m"
#特效范围: 如果“ [ ”后面的0m 加上了特效 那么后面这特效会一直执行 需要手动改回0m后特效才会停止;
echo -e "\033[0m 无任何特效 \033[0m"
echo -e "\033[1m 高亮度 \033[0m"
echo -e "\033[4m 下划线 \033[0m"
echo -e "\033[5m 闪烁 \033[0m"
注:混合使用需要使用 `` 扩起来:
read -t 5 -n 5 -s -p "`echo -e "\033[32;5m 请输入您的密码: \033[5m"`" pass
这样就会闪烁了 否则会失效:
简介:grep、cut、awk、sed 常常应用在查找日志、数据、输出结果等等,并对我们想要的数据进行提取,通常grep,sed命令是对行(hang)进行提取,cut和awk是对列进行提取
grep应用场景: 通常对数据进行 行的提取
语法:grep [选项] …[内容]…[file]
-v #对内容进行取反提取
-n #对提取的内容显示行号
-w #精确匹配
-i #忽略大小写
^ #匹配开头行首
-E #正则匹配
cut应用场景:通常地数据进行列的提取
语法:cut [选项]…[file]
-d #指定分隔符
eg:以‘:’为分隔符,截取出/etc/passwd的第一列跟第三列
cut -d ':' -f 1,3 /etc/passwd #表示通过:截取 1和3列
cut -d ':' -f 1-3 /etc/passwd #表示通过:截取 1到3列
cut -d ':' -f 2- /etc/passwd #表示通过:截取 第二列到最后一列
cut -d ':' -f 1,3 /etc/passwd 注:不加-d 默认我制表符 文件必须+ -d 指明分隔符
本身为表的不需要加 -d
-c #以字符为单位进行分割
eg:截取/etc/passwd 文件第二个字符到第九个字符:
cut -c 2-9 /etc/passwd
注:不加-d选项,默认为制表符,不是空格
eg:截取linux上面所有可登陆用户:
grep '/bin/bash' /etc/passwd
只提取用户并且除去root用户:
grep '/bin/bash' /etc/passwd | cut -d ':' -f 1 | grep -v root
awk简介:其实一门编程语言,支持条件判断,数组,循环等功能,与grep,sed被称为linux三剑客,之所以叫awk是因为取其三位创始人的 family name 首字符
awk的应用场景:通常对数据进行列的提取;
语法:
awk '条件{执行 动作}' 文件名
awk '条件1{执行动作}条件2{执行动作}... ' 文件名
awk [选项] '条件1{执行动作}条件2{执行动作}... ' 文件名
特殊要点举例说明:
printf 不换行:格式printf("", ) 其中括号可省略,其中格式化字符串包括两部分内容:
一部分是正常字符, 这些字符将按原样输出 printf("", ); 另一部分是格式化规定字符,
以"%"开始printf("%.", ), 后跟一个或几个规定字符,用来确定输出内容格式。
(%ns:字符串型,n代表有多少个字符;%ni:整型,n代表输出几个数字;
%.nf:浮点型,n代表的是小数点后有多少个小数)
如:printf '%s\t%s\t%s\t%s\t%s\t%s\t\n' 1 2 3 4 5 6
print #打印出内容,默认会自动换行
\t #制表符
\n #换行符
eg:df -h | grep /dev/sda1|awk '{printf "/dev/sda1的使用率是:"} {print $5} '
提取df -h 命令 中 /dev/sda1中的使用率
小数:echo "scale=2; 0.13+0.1" | bc | awk '{printf "%.2f\n",$0}'
scale定义保留2位小数,通过bc计算,但bc如果首位是0则不会显示0. 这时候通过printf 来显示0,2f代表后面保留2位小数 ,$0表示输出一整列;科学计算中print格式:(printf “%.”, )
$0 #代表第一列
$1 #代表第二列
$2 #代表第三列
eg:df -h | grep /dev/sda1| awk '{print $5}'
-F #指定分隔符
eg : cat /etc/passwd | awk -F":" '{print $1}'
使用:为分隔符,取passwd中的第一行
BEGIN #在读取所有行内容前就开始执行,常常被用于修改内置变量的值
FS #BEGIN时定义分隔符
eg:cat /etc/passwd |awk 'BEGIN {FS=":"} {print $1}'
eg:df -h |awk 'NR==2 {print $5}'
显示多行内容:df -h |awk 'NR>=1 && NR<=3 {print $1,$2}'
eg:awk '(NR>=20 && NR<=30) {print $1} ' /etc/passwd
sed的应用场景:主要对数据进行处理(选取,新增,替换,删除,搜索)
sed语法:sed [选项] [动作] 文件名
常见的选项与参数:
-n #吧匹配到的行输出打印到屏幕
p #以行为单位进行查询,通常与-n一起使用
如:df -h | sed -n '2p'
d #删除
如:df -h |sed '2d'
注:这种只删除内容 并不对源文件做改变,更改源文件需在sed后加 -i
a #在行的下面插入新的内容
如:在第二行下面插入新的内容:sed '2a test yes !!!' df .txt
,注:这操作并不对源文件做出改变,更改源文件需在sed后加 -i
i #在行的上面插入新的内容
如:在第二行上面插入新的内容:sed '2a test yes !!!' df .txt
,注:这操作并不对源文件做出改变,更改源文件需在sed后加 -i
c #替换
如:把第二行的内容替换为 test yes!!!:sed '2c test yes!!!' df.txt
注:这操作并不对源文件做出改变 ,更改源文件需在sed后加 -i
s/ 要被取代的内容/新的字符串/g #指定内容进行替换
如:吧df.txt文件中的0%替换为100%: sed 's/0%/100%/g' df.txt
注:该操作不会对原文件作出改变,更改源文件需在sed后加 -i
-i #对源文件进行修改 高危操作:修改前对原文件备份
如:吧df.txt文件中的0%替换为100%: sed -i 's/0%/100%/g' df.txt
搜索:在文件中搜索内容
如:查找df.txt文件里100%的条目 -n 显示 ,p 查询:2种表达方式
-e #表示可以执行多条动作
sed -i -e '1a #你说一切都是没想好' df.txt -i -e '3a #得到得和想要的对不上号' df.txt -i -e 's/100%/0%/g' df.txt
注:每一次-e 前面的都会重新跑一遍;
这个其实就是一个可以自定义的注释信息,简单来说 就是 用于脚本开头解释
语法:cat << EOF
其中EOF可以替换为任意字符,但开头和结尾必须一致
这儿就可以自定义 信息了 这儿定义什么 屏幕上就会打印什么
EOF
这个单独用于打印屏幕上 没什么意义,但可以用于写入 文本中和在脚本中使用,如写入文本:
以脚本为例:这就是一个手动执行的脚本,如下图,如果想了解该脚本,参考:https://blog.csdn.net/cuichongxin/article/details/101759690
看看执行效果,因为我加了while ,所以每一次操作都会显示该内容
if循环控制(单分支与多分支):
单分支1:
if [条件判断];then
执行动作
fi
单分支2:条件成立执行动作1,否则执行动作2
if [条件判断];then
执行动作1
else
执行动作2
fi
如:判断111.txt文件是否存在,不存在则创建,并写入内容
!#/bin/bash
#。。。。
#ccx
if [ -e 111.txt ]; then
echo '111.txt存在'
else
echo '111.txt不存在,现已为您创建111.txt文本'
touch 111.txt
echo '并且该内容写入进了111.txt文本中'
echo '并且该内容写入进了111.txt文本中' > 111.txt
cat 111.txt
fi
也可以改成用户输入文件判断并创建: 注:if [ -e $1 ] 是想对路径 可写成绝对路径 如 /etc/$1
!#/bin/bash
if [ -e $1 ];
then
echo $1'存在'
else
echo $1'不存在,现已为您创建'$1
touch $1
echo '并且该内容写入进了'$1'文本中'
echo '并且该内容写入进了'$1'文本中' > $1
cat $1
fi
多个判断(多分支循环);
if [条件判断];
then
执行动作
elif [条件判断];then
执行动作
elif [条件判断];then
执行动作
…
fi
(1) for 变量名 in 值1 值2 值3
do
执行动作
命令1,$变量名
….
done
如:每隔1秒打印一次1-10的循环条件 sleep睡眠命令
(2) for 变量名 in 命令
do
执行动作
done
如:每隔1秒打印一次1-10的循环条件 sleep睡眠命令
seq –w(补0) 直接 seq –w 1 10 即可
其实可以利用利用该方法来批量建用户之类的
也可以使用正则,如列出某目录下所有以.d结尾的文件
(3) for ((条件))
do
执行动作
done
如:每隔1秒打印一次1-10的循环条件 sleep睡眠命令
break是满足条件跳出循环
continue 提前结束本次循环而开始进行下一轮(跳出满足条件的条件)
做一个break的测试(命令要放在break之前,也就是先执行后判断)
做一个continue的测试(命令要放在continue之后,也就是先判断后执行)
来一个多次循环嵌套的说明一下(这是正常的循环)
加一个brack试试
应用场景:case循环常用语多重分支,与if不同的是,if可以判断多个条件,case只能判断一种条件
语法结构:
case 变量 in
'值1')
执行动作
;;
'值2')
执行动作
;;
'值3')
执行动作
;;
...
esac
#!/bin/bash
cat << !!
********************************************
* 这是一个询问脚本 *
********************************************
!!
read -p "请问是否已经吧光盘连接起来了?(y/n):" say
case $say in
y|Y)
;;
n|N)
echo "请先吧光盘连接上去"
exit 1
;;
*)
echo "只能输入y/n!!!"
exit 1
esac
echo ‘下面是正常的操作’
#该处放输入y以后需要执行的命令
#如 mount …
应用场景:while 循环是条件循环也是不定循环,只要条件判断式成立,循环就会一直进行着,直到判断式不成立 或者 选择跳出循环 才会结束;也就是说 每次执行完do和done之间的语句,会再次到while后面的条件进行对比,如果城里,再次执行do和done之间的语句。
while [ 条件判断式 ]
do
执行动作
done
写一个遍历1-10的数 自动跳过第4个
语法: while read 变量名 ; do
执行动作
done < 读取文件
说一下执行读取读取文件的操作
遍历之前先来说一下,read,这个平常是用来接收用户输入的值的,当然也可以读取文件中的值,只是 单独使用read读取某文件的值 只能读取第一行
如果用read纪录/etc/passwd全部文件,就需要用到while
while也可以用来读取某个某个文件的值 而做下一步操作,比如 把一堆ip写在一个文件中(注意 必须一行一个ip) 批量ping 或者啥的, 也或者 把 一堆用户名写在一个文件里 批量建用户, 现在测试批量建用户
实现wc –l 这个功能,后面必须跟上一个文本本间,来统计这个文件的行数
declare
declare或typeset内建命令(它们是完全相同的)可以用来限定变量的属性.这是在某些编程语言中使用的定义类型不严格的方式。命令declare是bash版本2之后才有的。命令typeset也可以在ksh脚本中运行。 -i 整数
#!/bin/bash
if [ $# -eq 0 ] ; then
echo "请输入一个参数"
exit 1
fi
declare -i num=0
while read aa ;do
let num=$num+1
done < $1
echo "${num}行 $1"
死循环 顾名思义 就是循环一直存在 直到手动取消
语法有3种:
1、 while true ; do
执行语句
done
2、 while ((1)) ; do
执行语句
done
3、 while : ; do
执行语句
done
有时候需要while一直循环下去(死循环)
比如说 某个服务 有时候会自动停止,我们不知道,但如果使用while语句一直检测,某服务,如果检测停止后 就自动 start 启动, 先说明一下,如果查看服务是启动的 返回值是0 如果不是启动的 返回结果则非0
现在以http 服务 为例,写一个脚本自动检测 该服务是否是active,如果不是 则自动start启动该服务,运行时 sh 脚本名称 > /dev/null & 最下面有说明 为什么这么执行以及执行后如果停止。
#!/bin/bash
while true ; do
systemctl is-active httpd
if [ $? -ne 0 ] ; then
systemctl start httpd
fi
done
如果不吧输出结果 放到/dev/null 和放在后台执行后结果
放到后台以后,jobs 查看 后台进程 kill -9 %1 杀死该进程
until循环和 while循环 相反,while是满足条件条件后执行 ,rntil是不满足条件后执行
语法:
untile 条件 ; do
执行命令
done
如:
let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。
deckare 是定义变量类型,-i 是整数
对until这种反人类语法 感兴趣的就自己去深究一下
就是一个功能模块,调用这个函数的时候,就可以直接调用这个功能了,不需要再次重复写代码。
函数不引用是不执行的,并且只能再同一个脚本里重复引用,其他脚本里不能引用该函数
语法有3种:
1、 function函数名 (){
…….执行命令
}
2、function 函数名{
……执行命令
}
来一个简单的使用规则
#!/bin/bash
function x1 () {
date
}
x1
x1
x1
#!/bin/bash
function x1 () {
declare -i num=0
while read aa ; do
let num=$num+1
done < $1
echo "${num}行 $1"
}
函数是只能在自己脚本中使用,如果想在其他脚本中使用,就得使用库。
语法:
库名 (){
….执行命令
}
另外一个文件 直接 . 库名 即可调用
调用死参数意义不大,但可以这么实现,死参数可以替换为灵活的,比如用户输入的 $1 $2 等等。了解就行,一般脚本用到的几率不高!