1. Shell基础介绍
1.1 Shell编程的意义
为什么使用shell编程
节约时间
1.2 显示脚本执行过程
前面有+表示执行过的命令的
前面没有东西,表示输出到屏幕上的内容。
[root@CentOS scripts]# sh bak-etc-adv.sh tar: Removing leading `/' from member names [root@CentOS scripts]# sh -x bak-etc-adv.sh ++ hostname -I ++ awk '{print $1}' + ip=10.0.0.200 + mkdir -p /backup/10.0.0.200 ++ date +%F + tar zcf /backup/10.0.0.200/etc-2018-08-17.tar.gz /etc/ tar: Removing leading `/' from member names
2. 变量
x + y = 10 x=20 y=? 未知数(变量)
2.1 变量命名规则
变量命名规则: 不能以数字开头
ip=10.0.0.200
赋值(把数据存放在变量中)
[root@CentOS /server/scripts]# echo $ip 查看变量内容 10.0.0.200 [root@CentOS /server/scripts]# 1ip=10.0.0.200 无法设置变量 -bash: 1ip=10.0.0.200: command not found
2.2 变量分类
普通变量(局部变量)
环境变量(全局变量)
特殊变量:(重点)
2.3 普通变量(局部变量)
用=可以配置局部变量
如ip=10.0.0.200 [root@CentOS /server/scripts]# ip=10.0.0.200 设置普通变量 [root@CentOS /server/scripts]# echo $ip 查看变量内容 10.0.0.200
2.4 环境变量(全局变量)
大写的
系统定义的
在大部分地方可以使用
env命令可以查看所有的环境变量
export 设置环境变量
unset 取消环境变量
目前已经学习过的有PATH PS1 LANG
2.4.1 取env的第一列内容(回顾)
env可以查看所有的环境变量
[root@CentOS scripts]# env [root@CentOS scripts]# env |awk -F "=" '{print $1}' [root@CentOS scripts]# env |sed -r 's#=.*##g' [root@CentOS scripts]# env | egrep -o '^[A-Z0-9_]+' [root@CentOS scripts]# env | egrep -o '^[^=]+'
2.5 普通变量与全局变量的区别
[root@CentOS /server/scripts]# OLDBOY=10 配置一个普通变量 [root@CentOS /server/scripts]# echo $OLDBOY 查看变量 10 [root@CentOS /server/scripts]# cat show.sh 脚本的内容 echo $OLDBOY [root@CentOS /server/scripts]# sh show.sh 执行 没有变量的内容 [root@CentOS /server/scripts]# sh -x show.sh 显示执行过程 没有 + echo [root@CentOS /server/scripts]# export OLDBOY=10 配置成全局变量(环境变量) [root@CentOS /server/scripts]# sh -x show.sh 有结果了 + echo 10 10 [root@CentOS /server/scripts]# env |grep -i oldboy 配置成全局变量 在env也可以查到 HOSTNAME=oldboyedu50-lnb OLDBOY=10 [root@CentOS scripts]# cat show.sh 查看脚本内容 #!/bin/bash echo $oldboy [root@CentOS scripts]# oldboy=10 配置oldboy的变量 普通变量 [root@CentOS scripts]# env |grep old 检查env是否有oldboy的全局变量 检查没有发现 [root@CentOS scripts]# source show.sh 使用source 可以使局部变量在脚本内生效 10 [root@CentOS scripts]# . show.sh 局部变量生效 10 [root@CentOS scripts]# sh show.sh 使用sh局部变量没有生效
2.6 特殊变量(重点)
2.6.1 特殊变量介绍
$1 $2 表示 第一个 第二个参数
$# 表示参数的个数
$? 表示上一个命令执行后的状态
状态为0 表示执行正确
状态非0 表示执行错误
$0 表示文件名
特殊变量小结:
$1 $2 $数字 awk:第1列 第2列 第3列
shell脚本:第1个参数
$0 awk:整行
shell脚本:文件名
$# 脚本的参数个数
判断脚本的参数个数
$? 上一个命令的执行结果(返回值)
0 执行正确
非0 执行失败
2.6.2 特殊变量测试
{}的用处
[root@CentOS /server/scripts]# week=6 配置一个变量 [root@CentOS /server/scripts]# echo $week 查看 6
想要在变量后面加上天数显示6day
[root@CentOS /server/scripts]# echo $weekday [root@CentOS /server/scripts]# echo ${week}day 6day
2.7 特殊变量的使用
2.7.1 $1 $2
第1个参数 第2个参数
[root@CentOS /server/scripts]# cat cal.sh 查看脚本内容 #!/bin/bash n1=$1 n2=$2 awk -vnum1=$n1 -vnum2=$n2 'BEGIN{print num1+num2 }' awk -vnum1=$n1 -vnum2=$n2 'BEGIN{print num1-num2 }' awk -vnum1=$n1 -vnum2=$n2 'BEGIN{print num1*num2 }' awk -vnum1=$n1 -vnum2=$n2 'BEGIN{print num1/num2 }' [root@oldboyedu50-lnb /server/scripts]# sh cal.sh 10 20 执行脚本 10表示第一个变量$1 20表示的是$2 30 -10 200 0.5
2.7.2 $0的使用
$0 shell脚本中表示文件名
[root@CentOS scripts]# cat cal-read.sh #!/bin/bash echo "当前编辑的文件为: $0" [root@CentOS scripts]# sh cal-read.sh 当前编辑的文件为: cal-read.sh
2.7.3 $? 的使用
$? 表示上一个命令执行后的状态
状态为0 表示执行正确
状态非0 表示执行错误
[root@znix ~]# aaa 执行一个字符 -bash: aaa: command not found 执行失败 [root@znix ~]# echo $? 查看$? 127 非0 表示上一个命令执行错误执行错误 [root@znix ~]# sh /server/scripts/show2.sh aa bb aa bb 2 [root@znix ~]# echo $? 0表示上一个命令执行成功
2.7.4 $#的使用
$# 表示参数的个数
【示例】脚本内容 [root@znix ~]# cat /server/scripts/show2.sh #!/bin/bash echo 112 $# if [ $? == 0 ];then echo "OK" fi 执行的不同结果 [root@znix ~]# sh /server/scripts/show2.sh 1 2 3 4 6 5个参数 $# 显示参数的个数 1 2 5 表示一个五个参数 [root@znix ~]# sh /server/scripts/show2.sh aa bb 2个参数 $# 显示参数的个数 aa bb 2 两个参数 [root@znix ~]# sh /server/scripts/show2.sh aa bb cc 3个参数 $# 显示参数的个数 aa bb 3 三个参数
3. awk的变量
命令行中的变量 放在awk中 无法直接使用 需要用awk的方式重新定义变量
用-v重新定义变量 如-vnum1=10
书写一个计算器 加减乘除
变量中 把两个数字放在变量中
[root@CentOS /server/scripts]# n1=10 在命令行定义变量n1 [root@CentOS /server/scripts]# n2=20 在命令行定义变量n2 [root@CentOS /server/scripts]# awk 'BEGIN{print n1/n2}' 使用awk计算 awk: fatal: division by zero attempted 报错无法执行 [root@CentOS /server/scripts]# awk 'BEGIN{print n1,n2}' 显示也无法显示 变量不可用 [root@CentOS /server/scripts]# awk -vnum1=10 'BEGIN{print num1 }' 10 [root@CentOS /server/scripts]# awk -vnum1=10 -vnum2=20 'BEGIN{print num1/num2 }' 0.5 书写脚本计算10与20的加减乘除 cal.sh #!/bin/bash n1=10 n2=30 awk -vnum1=$n1 -vnum2=$n2 'BEGIN{print num1+num2 }' awk -vnum1=$n1 -vnum2=$n2 'BEGIN{print num1-num2 }' awk -vnum1=$n1 -vnum2=$n2 'BEGIN{print num1*num2 }' awk -vnum1=$n1 -vnum2=$n2 'BEGIN{print num1/num2 }' awk -v {num1=$n1,num2=$n2} 'BEGIN{print num1/num2 }' 也可以这种写法
4. read命令
4.1 read命令介绍
通过read 交互式
read交互式赋予变量内容
read -p "提示信息:" 变量名字
read -p "提示信息:" p
执行之后会把输入的信息存放在变量中
-p 为显示提示信息。p作为输出,一定要写在其他参数的最后面。
-t5 等待5秒
-s 输入的时候不显示输入内容。
[root@znix ~]# read a 定义变量 呵呵 此处是输入的内容 [root@znix ~]# echo $a 查看变量 呵呵 让执行命令后出现提示信息 -p 为显示提示信息。p作为输出,一定要写在其他参数的最后面。 [root@znix ~]# read -p "请输入:" a 请输入:呵呵 [root@znix ~]# echo $a 呵呵 设置等待(超时)的时间 -t5 等待5秒 [root@znix ~]# read -t5 -p "请输入密码:" a 请输入密码: [root@znix ~]# [root@znix ~]# read -t5 -p "请输入密码:" a 请输入密码:123 不显示输入的内容 -s 输入的时候不显示输入内容。 [root@znix ~]# read -s -t50 -p "请输入密码:" a 请输入密码: [root@znix ~]# echo $a admin
4.2 将read命令运用到脚本上
修改计算器脚本的内容,让他能够更智能。
[root@znix ~]# vim /server/scripts/cal.sh #!/bin/bash read -p "input 1st num:" a 写入read命令的内容 read -p "input 2st num:" b 测试脚本 [root@znix ~]# sh /server/scripts/cal.sh input 1st num:1 输入1 input 2st num:2 输入2 0.5 3 -1 2
4.3 read同时读入多个字符。
[root@znix ~]# read -p "输入第一个 第二关数字:" a b 输入第一个 第二关数字:123 456 [root@znix ~]# echo aab 123 456 修改脚本的内容。 使用一条read命令,读取两个参数。 [root@znix ~]# vim /server/scripts/cal.sh #!/bin/bash read -p "input 1st&2st num:" a b awk -vnum1=a−vnum2=a−vnum2=b 'BEGIN{print num1/num2}' awk -vnum1=a−vnum2=a−vnum2=b 'BEGIN{print num1+num2}' awk -vnum1=a−vnum2=a−vnum2=b 'BEGIN{print num1-num2}' awk -vnum1=a−vnum2=a−vnum2=b 'BEGIN{print num1*num2}' "/server/scripts/cal.sh" 15L, 355C written 测试脚本。 同时传入两个参数的时候,参数之间要使用空格分割. [root@znix ~]# sh /server/scripts/cal.sh input 1st&2st num:1 2 0.5 3 -1 2
5. 判断
判断一个 文件/目录 是否存在
符号 |
参数 |
含义 |
英文 |
> |
-gt |
大于 |
great than |
>= |
-ge |
大于等于 |
great equal |
< |
-lt |
小于 |
less than |
<= |
-le |
小于等于 |
less than or equal |
== |
-eq |
等于 |
equal |
!= |
-ne / ! -eq |
不等于 |
not equal |
5.1 test命令
test命令不会自己输出执行的结果
配合$?查询上一条命令是否执行成功,就能够判断是否存在这个文件或目录.
判断文件是否存在
-f 为判断的对象是文件,0为存在,1为不存在 [root@znix ~]# test -f /clsn/clsn.txt 使用test -f命令 查看文件是否存在 [root@znix ~]# echo $? 查看变量 0 存在 [root@znix ~]# test -f /clsn/clsn 查看文件是否存在 [root@znix ~]# echo $? 查看变量 1 不存在 判断目录是否存在 -d 为对目录进行判断,0为存在,1为不存在. [root@znix ~]# test -d /znix 使用test -d命令 查看目录是否存在 [root@znix ~]# echo $? 查看变量 1 不存在 [root@znix ~]# test `-d /clsn/ 使用test -d命令 查看目录是否存在 [root@znix ~]# echo $? 查看变量 0 存在
5.2 使用[ ]判断
使用[ ]的时候注意中间的空格,两边都要有两个空格
[ ]与test命令的功能相似,可以进行判断,相比test命令更为便捷
判断文件是否存在
与test命令一样 [ ] 判断的结果也0为存在,1为不存在
-f 为判断的对象是文件 [root@znix ~]# [ -f /zinx.txt ] 查看znix.txt文件是否存在 [root@znix ~]# echo $? 查看上一条命令的执行结果 1 不存在 [root@znix ~]# [ -f /root/clsn.txt ] 查看/root/clsn.txt文件是否存在 [root@znix ~]# echo $? 查看上一条命令的执行结果 0 存在 判断文件/目录是否存在,判断成功执行后面的内容,输出ok ;判断失败,不执行后面的命令. [root@znix ~]# [ -f /clsn/znix.txt ] && echo "ok" ##/clsn/znix.txt该文件不存在 所以没有执行后面的命令 所以没有结果 [root@znix ~]# [ -d /clsn ] && echo "ok" 该目录存在 所以执行了后面的命令 输出OK ok 如果这个文件不存在,就创建 (使用 || ), || 前面命令执行错误,才执行后面的命令. [root@znix ~]# [ -f /clsn/znix.txt ] || touch /clsn/znix.txt 前面文件不存在 执行错误 执行了后面的 创建了/clsn/znix.txt 文件 [root@znix ~]# ls -l /clsn/znix.txt -rw-r--r-- 1 root root 0 Sep 20 10:31 /clsn/znix.txt 如果/root/clsndir 目录不存在就创建 [root@znix ~]# [ -d /root/clsndir ] || mkdir -p /root/clsndir [root@znix ~]# ls -ld /root/clsndir drwxr-xr-x 2 root root 4096 Sep 20 10:36 /root/clsndir 如果/root/clsndir 目录不存在,就创建这个目录 [root@znix ~]# [ ! -d /root/clsndir/1 ] && mkdir -p /root/clsndir/1 使用 && ,前面的执行成功,执行后面的; ! 表示非,不存在. [root@znix ~]# ll -d /root/clsndir/1 drwxr-xr-x 2 root root 4096 Sep 20 10:41 /root/clsndir/1
5.3 判断在脚本的使用
如果 [ 这个文件存在 ];然后
提示文件存在
否则
创建这个文件
果如
判断文件是否存在,不存在就创建
写入脚本的时候,注意脚本的基本格式.
[root@znix ~]# vim /server/scripts/if.sh #!/bin/bash if [ -f /root/clsn.txt ];then echo "文件存在" else touch /root/clsn.txt fi [root@znix ~]# sh /server/scripts/if.sh 测试脚本 文件存在 在脚本中进行判断的格式 如果cal2.sh脚本的参数个数不等于2,就显示 "命令错误" 书写脚本 != 表示判断两个是否不相等,如果不相等就显示命令错误 #/bin/bash if [ $# != 2 ];then echo "命令错误" fi 对脚本进行测试. [root@znix ~]# sh /server/scripts/cal2.sh ##当参数的个数为2的时候,不会输出,个数不为二的时候输出 命令错误 命令错误 [root@znix ~]# sh /server/scripts/cal2.sh 1 2 [root@znix ~]# sh /server/scripts/cal2.sh 1 2 3 命令错误
5.4 修改计算机的脚本
修改之前的计算器,进行两个数字的加减乘除,在计算器前面加上参数个数判断。当输入的参数是2个的时候执行计算,不为2的时候显示参数错误.
当输入的参数不为2的时候 执行 echo "Usage: NUM1 NUM2", 然后执行 exit..
exit 表示前面的执行完成后就结束(跳出),不会再执行脚本后面的内容.
[root@znix ~]# vim /server/scripts/cal2.sh #!/bin/bash if [ $# -ne 2 ];then echo "Usage: NUM1 NUM2" exit fi a=$1 b=$2 awk -vh=a−vz=a−vz=b 'BEGIN{print h/z}' awk -vh=a−vz=a−vz=b 'BEGIN{print h+z}' awk -vh=a−vz=a−vz=b 'BEGIN{print h-z}' awk -vh=a−vz=a−vz=b 'BEGIN{print h*z}' 测试脚本 当输入的参数个数不为2的时候执行echo 命令 当输入的参数个数为2的时候进行计算 [root@znix ~]# sh /server/scripts/cal2.sh Usage: NUM1 NUM2 ##提示信息 [root@znix ~]# sh /server/scripts/cal2.sh 22 22 1 44 0 484
6. 编程题目练习
6.1 检查进程
检查进程 crond是否运行
6.1.1 方法一
进程的名字不要作为脚本的名字
#! /bin/bash /etc/init.d/crond status >/dev/null 2>&1 if [ $? -eq 0 ];then echo "crond is running " else echo "crond is not running" fi
6.1.2 方法二
#! /bin/bash a=ps -ef |grep crond|grep grep if [ $a -eq 1 ];then echo "crond is running " else echo "crond is not running" fi
6.2. 让脚本带有OK或false的字样
/bin/true OK 该命令可以省略
/bin/false FAILED的的命令
[root@CentOS scripts]# . /etc/init.d/functions [root@CentOS scripts]# action "crond is running" 成功省略了 /bin/true crond is running [ OK ] [root@CentOS scripts]# action "crond is running" /bin/false crond is running [FAILED]
6.3 生成循环
6.3.1 要求
生成如下面一样的字符
tao,01week 01group take you to 大保健, find 01woman.
tao,02week 02group take you to 大保健, find 02woman.
tao,03week 03group take you to 大保健, find 03woman.
tao,04week 04group take you to 大保健, find 04woman.
tao,05week 05group take you to 大保健, find 05woman.
tao,06week 06group take you to 大保健, find 06woman.
6.3.2 解答
[root@CentOS scripts]# cat xunhuan.sh #!/bin/bash for a in {01..6} do echo "tao,${a}week ${a}group take you to 大保健, find ${a}woman." done [root@CentOS scripts]# for j in {01..6}; do echo "tao,${a}week ${a}group take you to 大保健, find ${a}woman.";done 每行结束加一个分好 for循环可以直接在命令行使用 tao,week group take you to 大保健, find woman. tao,week group take you to 大保健, find woman. tao,week group take you to 大保健, find woman. tao,week group take you to 大保健, find woman. tao,week group take you to 大保健, find woman. tao,week group take you to 大保健, find woman.
6.4. 优化系统开机启动项
只保留crond,sshd,network,rsyslog,sysstat其余服务都关闭
[root@CentOS scripts]# vim guanbi.sh #!/bin/bash a=`chkconfig | egrep -v 'crond|sshd|network|rsyslog|sysstat'|awk '{print $1}'` for j in $a do chkconfig $j off done chkconfig xxxx off 默认处理的是2345等级的自启动 所以 0 1 6 不参与
6.5 添加用户并设置密码
批量添加用户并设置八位随机密码
6.5.1 取8位随机密码
方法一 [root@CentOS scripts]# date +%N|md5sum |cut -c-8 220e5595 方法二 [root@CentOS scripts]# echo $((RANDOM+1000000)) 1011213 [root@CentOS scripts]# echo $RANDOM+1000000|bc 1020914
6.5.2 生成随机数并记录密码
tee命令用于读取标准输入的数据,并将其内容输出成文件。
tee指令会从标准输入设备读取数据,将其内容输出到标准输出设备,同时保存成文件。
参数:
-a附加到既有文件的后面,而非覆盖它.
[root@CentOS scripts]# vim piliang.sh #!/bin/bash for j in stu{01..3} do useradd $j date +%N|md5sum |cut -c-8 | tee -a /oldboy/passwd.txt|passwd --stdin $j done