目录
shell概述:
属于解释型语言,程序运行不需要提前编译,shell语言支持大部分编程语言都支持的功能,如if判断,for循环,变量,数组,函数,加减乘除逻辑运算。
当命令或程序语句不在交互式命令行下执行,而是通过一个程序文件来执行时,该程序就可以被称为脚本,在shell脚本中写入命令、变量、语句、及流程控制语句,然后将这些命令“一次性”执行完毕,这种批量执行命令的方式被称为非交互式的方式。
shell在生产环境中常被用于:软件一键自动化安装、优化,监控报警、软件启动、日志分析等。
由于shell与linux关系密切,因此更加适合通过shell脚本语言来帮助用户实现轻松、高效的运维任务。
shell书写规范
创建tset.sh脚本文件
写脚本都是以.bash结尾;第一行声明解释器,第二行开始写注释相关脚本信息,如作者信息等等,接下来就是可执行代码
用chomd +x test.sh 赋予该脚本执行权限 , #sh test.sh 和 #bash test.sh 都可以执行该脚本,sh和bash是不同的解释器。
PS:在vim中用 set nu打开行号,方便对脚本错误进行定位进一步修改
编写批量查看用户脚本
脚本执行方式
方法一:赋予脚本执行权限后,可用绝对路径或者当前路径执行
方法二:调用解释器执行脚本文件
如果没在当前目录opt下,用bash /opt/user.sh执行
SH
使用案例如下
变量
所有的编程语言都利用变量来存放数据,以备后续使用或者修改,和编译型语言不同,大多数脚本语言不要求在创建变量之前声明其变量类型,用到什么类型就是什么类型。在变量名前面加上一个美元符号就可以访问到变量的值,shell定义了一些变量,用于保存用到的配置信息,比如可用的打印机、搜索路径等,这些变量叫作环境变量。
变量名由一系列字母、数字、下划线组成,其中不包括空白字符,常用惯例是在脚本中使用大写字母为环境变量命名,或者使用驼峰命名法和小写字母为其他变量命名
简单地说:变量就是用一个固定的字符串(字母、数字、符号等组合)代替更多、更复杂的内容。在使用这些更多、更复杂内容时,通过简短固定的变量名称来代替。
变量类型:变量分为环境变量(全局变量)和普通变量(局部变量)。
环境变量可以创建在他们的shell及子shell中使用,环境变量又分为自定义变量和bash内置环境变量。
普通变量只能在创建他们的shell函数或shell脚本中使用,普通变量一般由开发者在开发脚本程序时创建。
(一)自定义变量:
定义环境变量的三种方法
- # 变量名=变量值;export 变量名 (先定义局部变量然后升级)
- # export 变量名=变量值
- # declare -x 变量名=变量值
(二)撤销变量
# unset AB
# user='' (等于空值)
(三)注意事项
变量名由字母数字下划线组成,区分大小写,不能以数字开头,不要使用命令和特殊符号。
若指定的变量名已经存在,相当于为此变量重新赋值。
案例:
通过变量定义用户名
(四)read标准输入取值
(五)整数比较
命令执行为真时结果为0,反之为1。
字符串比较:==为相等 !=为不相等
字符串判断:
判断文件非空,返回结果为真
Shell条件判断与循环
(一)逻辑关系
-f是判断是否是文件,-d判断是否是目录。
A && B是A命令执行成功才会执行B,A执行失败则不执行B。A || B是A执行失败才会执行B,A执行成功则不执行B。 A : B 是执行A之后执行B,两者没有逻辑关系。
(二)if条件判断结构
if单分支结构----条件成立时才能执行命令,条件不成立时无法完成后续工作
单分支举例
检测目录cdrom是否存在,若不存在则创建
# vim a.sh
#!/bin/bash
MOUNT_DIR="/media/cdrom/"
if [ -z $MOUNT_DIR ]
then
mkdir -p $MOUNT_DIR
echo "目录'${MOUNT_DIR}'已创建成功!"
fi
if双分支语句
脚本示例
if多分支语句
(三)case条件判断结构
case从变量中取值,如果变量中的值与预设的值匹配,则执行对应的命令
(1)case语句和if条件语句的适用性
case语句比较适合变量值较少且为固定的数字或字符串集合的情况,如果变量的值是已知固定的start/stop/restart等元素,那么采用case语句来实现就比较适合。
(2)case语句和if条件语句的常见应用场景
case主要是写服务的启动脚本。
if就是取值判断、比较,应用面比case更广。
几乎所有的case语句都可以用if条件语句来实现。
(3)case语句的特点及优势
case语句就相当于多分支的if/elif/else语句,但是case语句的优势是更规范、易读。
示例
判断用户键入的字符类型:
# cat hitkey.sh
#!/bin/bash
read -p "请输入一个字符,并按Enter键确认:" KEY
case "$KEY" in
[a-z]|[A-Z])
echo "您输入的是 字母。"
;;
[0-9])
echo "您输入的是 数字。"
;;
*)
echo "您输入的是 空格、功能键或其他控制字符。"
esac
编写服务控制脚本:
#!/bin/bash
# chkconfig: - 85 15
case "$1" in
start)
/usr/sbin/apachectl start
echo "正在启动服务:httpd,-----服务启动成功!"
;;
stop)
/usr/sbin/apachectl stop
echo "正在停止服务:httpd,-----服务停止成功!"
;;
*)
echo $"请参照以下规则输入: {start|stop}"
esac
(四) for循环
根据变量的取值重复执行命令,语法结构如下
自动创建多个已定义的用户名及相同的密码:
# vim a.txt
a
b
c
d
e
# vim a.sh
#/bin/bash
ABC=`cat /root/a.txt`
for name in $ABC
do useradd $name
echo "redhat" | passwd --stdin $name
done
########思考:
根据已定义的用户列表创建相关用户及与用户名相同的密码:
#!/bin/bash
B=`cat /root/user.txt`
NULL="/dev/null"
for A in $B
do
useradd $A &> $NULL
echo "$A" | passwd --stdin $A &> $NULL
done
根据列出的主机IP,判断这些主机是否能够通信:
# vim ipadds.txt
192.168.1.1
192.168.1.2
192.168.1.3
192.168.1.4
192.168.1.5
192.168.1.6
192.168.1.7
192.168.1.8
192.168.1.9
192.168.1.10
# vim chkhosts.sh
#!/bin/bash
HLIST=$(cat /root/ipadds.txt)
for IP in $HLIST
do
ping -c 3 -i 0.2 -W 3 $IP &> /dev/null
if [ $? -eq 0 ] ; then
echo "Host $IP is up."
else
echo "Host $IP is down."
fi
done
-c //发送包个数
-i //每个包发送间隔,单位为秒
-W //等待数据包回应时间,网络延迟低时可以设置为1,网络延迟高可设置高些。
按照递增顺序创建20个用户及设置密码:
通过命令批量创建多个用户:
# echo abc{01..10} |xargs -n1 | sed -r 's#(.*)#useradd \1#g' | bash
xargs -n1 //换行显示
-r //因为用到了(),因此要使用-r启用sed的扩展正则
s#(.*)#useradd \1#g //将括号(括号中的内容就是通过echo输出的内容)里的内容替换为useradd,再通过\1将之前括号里的东西输出到替换后的命令后面,最终结果就是:useradd abc01 -10
再通过最后的bash将之前生成的命令执行,即可创建10个用户。
通过命令批量创建多个用户及相同的密码:
# echo abc{01..10} |xargs -n1 | sed -r 's#(.*)#useradd \1;echo 123456 | passwd --stdin \1#g' | bash
通过命令批量创建多个用户及不同的密码:
# echo abc{01..10} |xargs -n1 | sed -r 's#(.*)#useradd \1;echo \1 | passwd --stdin \1#g' | bash
(四)while循环
死循环,只要条件成立就重复执行命令
脚本示例
(五)脚本中断及退出
#结束当前循环,进入下一次循环
#!/bin/bash
for i in {1..5}
do
[ $i -eq 3 ] && continue;
echo $i
done
echo Over
[root@localhost yunwei]# ./for1.sh
1
2
4
5
Over
#结束整个循环
#!/bin/bash
for i in {1..5}
do
[ $i -eq 3 ] && break
echo $i
done
echo Over
[root@localhost yunwei]# ./for1.sh
1
2
Over
#直接退出脚本
[root@localhost yunwei]# vim for1.sh
#!/bin/bash
for i in {1..5}
do
[ $i -eq 3 ] && exit
echo $i
done
echo Over
[root@localhost yunwei]# ./for1.sh
1
2