1.shell的基础知识
- 什么是shell脚本?
简单来说,当命令或者程序不在命令行执行,而是通过一个程序文件来执行,这个程序就被叫做shell脚本。也就是在shell脚本内置了多条命令,语句,循环控制,然后将这些命令一次性执行完毕,这种通过文件执行命令的方式被称为非交互式。 - 为什么要使用shell脚本?
1)适合处理操作系统底层的业务,有众多系统命令为其做支撑(还有文本处理三兄弟grep,sed,awk)
2)适合处理纯文本文件,linux中许多服务配置文件,启动脚本,都是纯文本(httpd,nfs,mysql,nginx,lvs)
3)linux系统脚本用shell开发更简单
查看系统默认shell:
- shell脚本的建立:
第一行:#!/bin/bash(必须写在第一行,否则会被认为是注释
指定解释器:由那个程序来执行脚本内容
#!幻数 - 脚本的执行过程
1)先加载系统环境变量
查看系统中的环境变量
2)一条一条命令执行,遇到子脚本,先执行子脚本,然后返回副父脚本继续执行
练习:清空日志的脚本
[root@localhost mnt]# vim clean.sh
#!/bin/bash
#DATE:2018-12-23
#Author:hr
#Connect:XXXXXX
#Desc:
#Version:1.0
LOG_DIR=/var/log
ROOT_UID=0
##判断是否是超级用户
if [ "$UID" -ne "$ROOT_UID" ];then
echo "Error:you should be root to run this scripts!"
exit
fi
##判断是否有目录权限
cd $LOG_DIR || {
echo "Cannot access to directory."
exit
}
cat /dev/null > messages && {
echo "Logs cleand up..."
exit 0
}
echo "Logs cleaned failed..."
> /var/log/messages
echo "Logs cleaned up ..."
执行结果:
练习:下载http并打开,开机自启
[root@localhost mnt]# vim http.sh
#!/bin/bash
rm -fr /etc/yum.repos.d/*
cat >> /etc/yum.repos.d/yum.repo <<EOF
[ddd]
name=ddd
baseurl=http://172.25.55.250/wanggua
gpgcheck=0
EOF
yum clean all >> /dev/null
yum install httpd -y >> /dev/null
systemctl start httpd
systemctl enable httpd >> /dev/null
执行结果:
- 执行脚本方式的
方法一:sh script.sh | bash script.sh (这中方法在没有执行权限时可以使用)
方法二:path/script.sh | ./script.sh (执行文件路径的命令就可。绝对路径或当前路径)
方法三:source script.sh | . script.sh (这种方式会使用source或.号来读如指定shell文件,并会把其他shell中的变量值或函数返回给父shell继续使用
[root@localhost mnt]# vim test1.sh
[root@localhost mnt]# sh test1.sh
hello
[root@localhost mnt]# bash test1.sh
hello
[root@localhost mnt]# chmod +x test1.sh
[root@localhost mnt]# /mnt/test1.sh
hello
[root@localhost mnt]# ./test1.sh
hello
[root@localhost mnt]# vim test.sh
#! /bin/bash
user=`whoami`
2.变量
变量赋值[root@localhost mnt]# a=hello
[root@localhost mnt]# echo $a
hello
[root@localhost mnt]# b='hello'
[root@localhost mnt]# echo $b
hello
[root@localhost mnt]# c="hello"
[root@localhost mnt]# echo $c
hello
[root@localhost mnt]# a=westos-$a
[root@localhost mnt]# echo $a
westos-hello
[root@localhost mnt]# b='westos-$a'
[root@localhost mnt]# echo $b
westos-$a
[root@localhost mnt]# c="westos-$a"
[root@localhost mnt]# echo $c
westos-westos-hello
[root@localhost mnt]# a=we are
bash: are: command not found...
[root@localhost mnt]# a="we are"
注意:建议没有特别要求时,字符串都加双引号,需要原样输出就加单引号
[root@localhost mnt]# echo $a
we are
特殊变量
变量 | 含义 |
---|---|
$0 | 获取shell脚本文件名,如果执行时包含路径,则输出脚本路径 |
$n(>0) | 获取脚本的第n个参数 |
$# | 获取脚本后参数的总个数 |
$* | 获取所有参数 |
$@ | 获取所有参数 |
$? | 获取上一条命令执行状态的返回值,非0为失败 |
$$ | 获取当前shell进程号 |
$0
[root@localhost mnt]# vim test2.sh
#!/bin/bash
echo $0
[root@localhost mnt]# sh test2.sh
test2.sh
[root@localhost mnt]# chmod +x test2.sh
[root@localhost mnt]# /mnt/test2.sh
/mnt/test2.sh
[root@localhost mnt]# ./test2.sh
./test2.sh
$n
[root@localhost mnt]# vim test3.sh
#!/bin/bash
echo $1 $2
[root@localhost mnt]# vim westos.sh
#!/bin/bash
echo $1 $2 $3 $4 $5 $6 $7 $8 $9 $10
[root@localhost mnt]# sh westos.sh {1..10}
1 2 3 4 5 6 7 8 9 10
[root@localhost mnt]# sh westos.sh {4..13} 我们可以看到$10是按照$1再加0得到数值
4 5 6 7 8 9 10 11 12 40
[root@localhost mnt]# sh westos.sh {a..z}
a b c d e f g h i a0
$#
[root@localhost mnt]# vim westos.sh
#!/bin/bash
echo $1 $2 $3 $4 $5 $6 $7 $8 $9 $10
echo $#
[root@localhost mnt]# vim westos.sh
[root@localhost mnt]# sh westos.sh {1..100}
1 2 3 4 5 6 7 8 9 10
100
$?:
[root@localhost mnt]# echo $?
0 上一条命令执行成功
[root@localhost mnt]# ls /etc/passwd12
ls: cannot access /etc/passwd12: No such file or directory
[root@localhost mnt]# echo $?
2 上一条命令执行失败
$$
[root@localhost mnt]# echo $$
4156
[root@localhost mnt]# ps
PID TTY TIME CMD
1715 pts/1 00:00:00 ps
4156 pts/1 00:00:00 bash
4188 pts/1 00:00:00 dbus-launch
变量的计算
1)expr命令
[root@localhost ~]# a=11
[root@localhost ~]# expr $a + 10
21
[root@localhost ~]# expr $a * 10 直接使用*不可以执行,要转义
expr: syntax error
[root@localhost ~]# expr $a \* 10
110
[root@localhost ~]# expr $a / 10
1
[root@localhost ~]# expr $a % 10
1
[root@localhost ~]# expr $a - 10
1
2)$[]和$(())表达式
[root@localhost ~]# echo $[a+10]
21
[root@localhost ~]# echo $[a-10]
1
[root@localhost ~]# echo $[a*10]
110
[root@localhost ~]# echo $[a/10]
1
[root@localhost ~]# echo $[a%10]
1
[root@localhost ~]# echo $((a%10))
1
[root@localhost ~]# echo $((a+10))
21
3)let命令(let命令在执行后会保存新的值)
[root@localhost ~]# let a+=15
[root@localhost ~]# echo $a
26
[root@localhost ~]# let a*=10
[root@localhost ~]# echo $a
260
[root@localhost ~]# let a/=10
[root@localhost ~]# echo $a
26
[root@localhost ~]# let a%=10
[root@localhost ~]# echo $a
6
4)小数运算工具bc
[root@localhost ~]# echo "scale=4;1.22*2.25" |bc
2.7450
[root@localhost ~]# echo "scale=2;1.22*2.25" |bc
2.74
[root@localhost ~]# echo 1.35+3.4 |bc
4.75
[root@localhost ~]# echo 1.35*3.4 |bc
4.59
[root@localhost ~]# echo 5/2 |bc
2
[root@localhost ~]# echo 5%2 |bc
1
脚本
#!/bin/bash
read -t 5 -p "请输入两个整数:" a b
echo "$a+$b=$[$a+b]"
echo "$a-$b=$[a-b]"
echo "$a*$b=$[a*b]"
echo "$a/$b=$[a/b]"
echo "$a**$b=$[a**b]"
echo "$a%$b=$[a%b]"
练习:
打包日志
[root@localhost mnt]# tar zcf log_$(date +%F).tar.gz /var/log/
[root@localhost mnt]# ls
log_2018-12-22.tar.gz read.sh test2.sh test3.sh test.sh westos.sh
3. read用法
[root@localhost mnt]# read a
123
[root@localhost mnt]# echo $a
123
[root@localhost mnt]# read -p "请输入一个整数:" b
请输入一个整数:abc
[root@localhost mnt]# echo $b
abc
脚本:
[root@localhost mnt]# vim read.sh
#!/bin/bash
read -p "请输入一个整数:"
[root@localhost mnt]# sh read.sh
请输入一个整数:123
4.grep,egrep
命令参数 | 含义 |
---|---|
-i | 忽略字母大小写 |
-v | 条件取反 |
-c | 统计匹配行数 |
-q | 静默,无任何输出 |
-n | 显示匹配结果所在的行号 |
[root@localhost mnt]# egrep -c '/sbin/nologin' /etc/passwd
34
[root@localhost mnt]# egrep -m5 '/sbin/nologin' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
[root@localhost mnt]# egrep '^root' /etc/passwd 查找以root开头的行
root:x:0:0:root:/root:/bin/bash
正则表达式
由一类特殊字符及文本字符多编写的模式,其中有些字符不表示字符的字面意思,而表示控制或通配的功能。
字符 | 含义 |
---|---|
^ | 匹配开头 |
$ | 匹配结尾 |
. | 匹配任意字符 |
[ ] | 匹配中括号内的任意字符 |
[^] | 匹配不在括号内的任意字符 |
基本原字符:^
^$代表空行
基本原字符:.
基本元字符:$
基本元字符: + ? *
筛选除大写字母
5.cut命令
以:分列,从passwd文件中截取1到3列
从passwd文件中截取1和4列
练习:获取主机IP
我们可通过截取命令得到ip(以空格为列,第十个空格取到ip)
也可通过awk命令得到ip
练习:检测网络
#!/bin/bash
ping -c1 172.25.55.$1 > /dev/dull && echo 172.25.55.$1 is up || echo 172.25.55.$1 is down
6.sort命令
命令参数 | 含义 |
---|---|
-n | 纯数字排序 |
-r | 倒序 |
-u | 去掉重复数字 |
-o | 输出到指定文件中 |
-t | 指定分隔符 |
-k | 指定要排序的列 |
按第一列数字排序
按整体数字排序
按逆向排序
为第二列排序
将排序好的数字导入到文件中:
每行显示一次并统计重复次数
查看出现重复的行
查看出现一次行
练习:将/tmp目录中的文件取出最大的
7.test命令
[ "$a" = "$b" ] 等于
[ "$a" != "$b" ] 不等于
[ "$a" -eq "$b" ] 等于
[ "$a" -ne "$b" ] 不等于
[ "$a" -le "$b" ] 小于等于
[ "$a" -ge "$b" ] 大于等于
[ "$a" -gt "$b" ] 大于
[ "$a" -lt "$b" ] 小于
[ "$a" -ne "$b" -a "$a" -gt "$b" ] -a必须条件都满足
[ "$a" -ne "$b" -o"$a" -gt "$b" ] -a条件至少满足一个
[ -z "$a" ] 是否为空
[ -e "file" ] 是否存在
[ -f "file" ] 普通文件
[ -b "file" ] 块设备
[ -S "file" ] 套接字
[ -c "file" ] 字符设备
[ -L "file" ] 软链接
练习:检测数字是否在1-10中
[root@localhost mnt]# vim shuzi.sh
#!/bin/bash
read -p "请输入数字:" a
[ -z "$a" ]&&{
echo please input a number !!
exit 1
}
[ "$a" -gt "0" -a "$a" -lt "10" ] && {
echo "$a is in range"
}||{
echo "$a is not in range"
}