Shell 脚本
管理服务器,看懂运维写的脚本,管理集群,提高开发效率
1. Shell 概述
Shell 是一个命令行解释器,它接收应用程序/用户命令,然后调用操作系统。
优点:易编写,易调试,灵活性强
2. Shell 解析器
Linux 提供的Shell 解析器有
[root@master ~]# cat /etc/shells
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
/bin/tcsh
/bin/csh
bash 和 sh 的关系
bash
sh -> bash
CentOS 默认解析器是bash
[root@master ~]# echo $SHELL
/bin/bash
3.Shell 入门
-
脚本格式
以#!/bin/bash 开头(指定解释器)
#!/bin/bash echo "hello world!"
-
运行方式
-
sh 文件地址
-
bash 文件地址
-
./文件名称.sh 需要先提高权限 chmod 777 文件名称.sh
-
-
多命令处理
#!/bin/bash cd /zhj/shellfile/ mkdir data touch data/love.txt echo "I love you!" >> data/love.txt
4 变量
-
常用的系统变量
H O M E 、 HOME、 HOME、PWD、 S H E L L 、 SHELL、 SHELL、USER等
(1)变量 = 值
(2)撤销变量:unset 变量
(3)声明静态变量:readonly 变量,注意:不能unset
-
变量定义规则
(1)变量名称可以由字母、数字、下划线组成,但不能以数字开头,变量名建议大写
(2)等号两侧不能有空格
(3)在 bash 中,变量默认类型都是字符串类型,无法直接进行数值运算
(4)变量的值如果有空格,需要使用双引号获单引号括起来
-
案例实操
(1)定义变量A
[root@master /]# A=5 [root@master /]# echo $A 5
(2)给变量重新赋值
[root@master /]# A=8 [root@master /]# echo $A 8
(3)撤销变量
[root@master /]# unset A [root@master /]# echo $A
(4)声明静态变量B=2 ,不能unset
[root@master /]# readonly C=2 [root@master /]# echo $C 2 [root@master /]# unset C -bash: unset: C: 无法反设定: 只读 variable
(5)在bash中,变量默认类型都是字符串类型,无法直接进行数值运算
[root@master /]# D=1+2 [root@master /]# echo $D 1+2
(6)变量的值如果有空格需要用双引号或单引号括起来
[root@master /]# E="I love you" [root@master /]# echo $E I love you [root@master /]# F=I love you bash: love: 未找到命令... [root@master /]# G='I love you!' [root@master /]# echo $G I love you!
(7)可把变量提升为全局变量,供其他Shell使用
export 变量名
# 直接声明都是局部变量 export E
-
特殊变量
-
$n n为数字,$0代表该脚本名称,$1- 9 代 表 第 一 到 第 九 个 参 数 , 十 个 及 以 上 需 要 大 括 号 包 含 , 如 9代表第一到第九个参数,十个及以上需要大括号包含,如 9代表第一到第九个参数,十个及以上需要大括号包含,如{10}
[root@master shellfile]# touch parameter.sh [root@master shellfile]# vim parameter.sh #!/bin/bash echo "$0 $1 $2 $3" [root@master shellfile]# ll 总用量 16 -rwxr-xr-x. 1 root root 99 4月 22 17:32 batch.sh drwxr-xr-x. 2 root root 4096 4月 22 17:32 data -rwxrwxrwx. 1 root root 33 4月 22 17:18 helloworld.sh -rw-r--r--. 1 root root 33 4月 22 19:16 parameter.sh [root@master shellfile]# chmod 777 parameter.sh [root@master shellfile]# ./parameter.sh ./parameter.sh [root@master shellfile]# ./parameter.sh is My Shell ./parameter.sh is My Shell
-
$# 获取输入参数个数
[root@master shellfile]# vim parameter.sh #!/bin/bash echo "$0 $1 $2 $3" echo $# [root@master shellfile]# ./parameter.sh ./parameter.sh 0 [root@master shellfile]# ./parameter.sh is My Shell ./parameter.sh is My Shell 3
-
∗ 命 令 行 所 有 参 数 , * 命令行所有参数, ∗命令行所有参数,*看成一个整体
@ 变 量 代 表 命 令 行 所 有 参 数 , @ 变量代表命令行所有参数, @变量代表命令行所有参数,@把每个参数区分对待
[root@master shellfile]# vim parameter.sh #!/bin/bash echo "$0 $1 $2 $3" echo $# echo $* echo $@ [root@master shellfile]# ./parameter.sh ./parameter.sh 0 [root@master shellfile]# ./parameter.sh is My Shell ./parameter.sh is My Shell 3 [root@master shellfile]# vim parameter.sh [root@master shellfile]# vim parameter.sh [root@master shellfile]# ./parameter.sh is My Shell ./parameter.sh is My Shell 3 is My Shell is My Shell [root@master shellfile]# ./parameter.sh is My ./parameter.sh is My 2 is My is My
-
$? 上一条命令的返回状态,如果为0,则证明上一个命令正确,非零,则上个命令不正确
[root@master shellfile]# ./parameter.sh is My ./parameter.sh is My 2 is My is My [root@master shellfile]# ./parameter.sh ./parameter.sh 0 [root@master shellfile]# echo $? 0
-
5 运算符
-
基本语法
(1)" ( ( 运 算 式 ) ) " 或 " ((运算式))"或" ((运算式))"或"[运算式]"
(2)expr +,-,*,/,% 加,减,乘,除,取余
[root@master shellfile]# expr 3+2 3+2 [root@master shellfile]# expr [3+2] [3+2] [root@master shellfile]# expr 3 + 2 5 # `优先执行` [root@master shellfile]# expr `expr 2 + 3` \* 5 25 [root@master shellfile]# s=$[(2+3)*5] [root@master shellfile]# echo $s 25
6 条件判断
-
基本语法
[ condition ] 注意 condition 前后都要有空格
注意;条件非空即为true,[ zhj ] 返回true ,[] 返回false
-
常用判断条件
(1) 比较大小
= 字符串之间比较
-lt 小于(less than) -le 小于等于(less equal)
-eq 等于(equal) -gt 大于(greater than)
-ge 大于等于(greater equal) -ne 不等于 (Not equal)
(2)文件权限
-r 有读权限 (read) -w有写权限(write)
-x 有执行权限(execute)
(3)文件类型
-f 文件存在并且是一个常规文件(file)
-e 文件存在(existence) -d 文件存在并且是一个目录(directory)
-
案例实操
[root@master shellfile]# [ 23 -gt 32 ] [root@master shellfile]# [23 -gt 32] bash: [23: 未找到命令... [root@master shellfile]# echo $? 127 [root@master shellfile]# [ 23 -gt 32 ] [root@master shellfile]# echo $? 1 [root@master shellfile]# [ 23 -lt 32 ] [root@master shellfile]# echo $? 0 [root@master shellfile]# [ -f x.txt ] [root@master shellfile]# echo $? 1 [root@master shellfile]# [ -f helloworld.sh ] [root@master shellfile]# echo $? 0 [root@master shellfile]# [ condition ] && echo OK || echo not OK
7 流程控制
7.1 if 判断
-
基本语法
if [ 条件判断式 ];then
程序
fi
或者
if [ 条件判断式 ]
then
程序
fi
-
注意事项
(1) [ 条件判断式 ] 条件判断式两边必须有空格
(2) if后要有空格
#!/bin/bash
if [ $1 -eq 1 ];then
echo "$1 == 1"
elif [ $1 -eq 2 ]
then
echo "$1 == 2"
fi
[root@master shellfile]# ./if.sh 1
1 == 1
[root@master shellfile]# ./if.sh 2
2 == 2
[root@master shellfile]# ./if.sh 3
7.2 case 语句
-
基本语法
case $变量名 in
“值1”)
如果变量值等于值1,执行程序1
;;
“值2”)
如果变量值等于值2,执行程序2
;;
省略其他分支。。。
*)
如果以上都不满足,则执行此程序
;;
esac
-
注意事项
1)case 行尾必须为单词"in",每一个模式匹配必须以右括号)结束
2)双";;"表示命令序列结束,相当于break
3) 最后的"*)" 表示默认模式,相当于java 中的default
-
案例实操
[root@master shellfile]# touch case.sh [root@master shellfile]# vim case.sh #!/bin/bash case $1 in 1) echo "1 == 1" ;; 2) echo "2 == 2" ;; 3) echo "3 == 3" ;; *) echo "!!!" ;; esac [root@master shellfile]# ./case.sh 1 1 == 1 [root@master shellfile]# ./case.sh 2 2 == 2 [root@master shellfile]# ./case.sh 3 3 == 3 [root@master shellfile]# ./case.sh 4 !!! [root@master shellfile]# ./case.sh 5 !!!
7.3 for 循环
-
基本语法
for (( 初始值;循环控制;变量变化 ))
do
程序
done
或者
for 变量 in 值1 值2 值3 …
do
程序
done
-
案例实操
[root@master shellfile]# touch for.sh [root@master shellfile]# vim for.sh #!/bin/bash for ((i=0;i<10;i++)) do s=$[$s+$i] done echo $s [root@master shellfile]# sh for.sh 45 # 打印所有输入参数 #!/bin/bash for i in $* do echo "params is $i" done [root@master shellfile]# vim for2.sh [root@master shellfile]# sh for2.sh we are family params is we params is are params is family #!/bin/bash for i in $@ do echo "params is $i" done [root@master shellfile]# sh for3.sh we are family params is we params is are params is family #!/bin/bash for i in "$*" do echo "params is $i" done for j in "$@" do echo "params is $j" done [root@master shellfile]# sh for4.sh we are family params is we are family params is we params is are params is family
7.4 while 循环
-
基本语法
whle [ 条件判断式 ]
do
程序
done
-
案例实操
#!/bin/bash
i=1
s=0
while [ $i -le 100 ]
do
s=$[$s+$i]
i=$[$i+1]
done
echo $s
[root@master shellfile]# sh while.sh
5050
8 read 读取控制台输入
-
基本语法
read(选项)(参数)
-p 指读取时的提示符
-t 指读取时等待时间(秒)
-
案例实操
#!/bin/bash
read -t 7 -p "Enter your name in 7 seconds !" NAME
echo $NAME
[root@master shellfile]# sh read.sh
Enter your name in 7 seconds !zhj
zhj
9 函数
9.1 系统函数
-
basename 基本用法
basename [string/pathname] [suffix] (basename 会删掉所有的前缀包括最后一个(‘/’)字符,然后将字符显示出来
suffix 为后缀 如果指定了会将pathstring的后缀去掉
[root@master shellfile]# basename /zhj/shellfile/helloworld.sh helloworld.sh [root@master shellfile]# basename /zhj/shellfile/helloworld.sh .sh helloworld
-
dirname 基本语法
dirname 文件绝对路径 (返回除去文件名的路径)
[root@master shellfile]# dirname /zhj/shellfile/helloworld.sh /zhj/shellfile
9.2 自定义函数
-
基本语法
[ function ] funname[()]
{
Action;
[return int;]
}
funname
-
经验技巧
(1)必须在调用函数前,先声明函数,shell脚本逐行运行,不会先编译
(2)函数返回值,只能通过$?系统变量获得,可以显示加:return 返回如果不加,将以最后一条命令运行结果,作为返回值。return 后跟数值n(0-255)
-
案例实操
#!/bin/bash function sum() { s=0 s=$[$1+$2] echo $s } read -p "input you paratemer1:" P1 read -p "input you paratemer2:" P2 sum $P1 $P2 [root@master shellfile]# vim sum.sh [root@master shellfile]# sh sum.sh input you paratemer1:2 input you paratemer2:3 5
10 Shell工具
10.1 cut 从大段文字切割出我们想要的内容
cut [选项参数] filename 剪数据 不改变原文件
参数 -f 列号 第几列 -d 分割符,按指定分割符分割
# vim
Beijin
Shang hai
wo
lai le
[root@master shellfile]# cut -d " " -f 1 cut.txt
Beijin
Shang
wo
lai
[root@master shellfile]# cut -d " " -f 2 cut.txt
Beijin
hai
wo
le
[root@master shellfile]# cut -d " " -f 2,3 cut.txt
Beijin
hai
wo
le
[root@master shellfile]# cut -d " " -f 2 cut.txt
Beijin
hai
wo
le
[root@master shellfile]# cut -d " " -f 2,3 cut.txt
Beijin
hai
wo
le
# | 将上条结果做为下条参数 grep 搜索
[root@master shellfile]# vim cut.txt
[root@master shellfile]# cat cut.txt | grep shang
[root@master shellfile]# cat cut.txt | grep Shang
Shang hai
[root@master shellfile]# cat cut.txt | grep Shang | cut -d " " -f 1
Shang
[root@master shellfile]# cat cut.txt | grep Shang | cut -d " " -f 2
hai
[root@master shellfile]# cat cut.txt | grep Shang | cut -d " " -f 2-
hai
[root@master shellfile]# cat cut.txt | grep Shang | cut -d " " -f 3-
10.2 sed 流编辑器
sed 是一种流编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”,接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并未改变,除非你使用重定向存储输出。
sed [选项参数] ‘command’ filename
选项参数: -e 直接在指令模式上进行sed的动作编辑
a 新增 a的后边接字符串,在下一行出现 d 删除 s 查找并替换
wo jia zhu
zai
bei jing tian an meng
wo jia da
meng chang da kai
# 原文件并不改变
sed "2a mei nv" sed.txt
wo jia zhu
mei nv
zai
bei jing tian an meng
wo jia da
meng chang da kai
[root@master shellfile]# sed "/wo/d" sed.txt
zai
bei jing tian an meng
meng chang da kai
[root@master shellfile]# sed "s/wo/ni/g" sed.txt
ni jia zhu
zai
bei jing tian an meng
ni jia da
meng chang da kai
[root@master shellfile]# sed -e "2d" -e "s/wo/ni/g" sed.txt
zai
bei jing tian an meng
ni jia da
meng chang da kai
10.3 awk
一个强大的文本分析工具,把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行处理
awk [选项参数] ‘pattern1{action1} pattern2{action2}…’ filename
pattern:表示AWK在数据中查找的内容,就是匹配模式
action: 在找到匹配内容时所执行的一系列命令
选项参数: -F 指定输入文件的分隔符 -v赋值一个用户定义变量
[root@master shellfile]# awk -F : '/^root/ {print $7}' passwd
/bin/bash
[root@master shellfile]# awk -F : '/^root/ {print $1,$7}' passwd
root /bin/bash
[root@master shellfile]# awk -F : '/^root/ {print $1","$7}' passwd
root,/bin/bash
[root@master shellfile]# awk -F : 'BEGIN{print "user,shell"} {print $1","$7} END{print "zhj, bin/zhj"}' passwd
user,shell
root,/bin/bash
bin,/sbin/nologin
daemon,/sbin/nologin
adm,/sbin/nologin
lp,/sbin/nologin
sync,/bin/sync
shutdown,/sbin/shutdown
halt,/sbin/halt
mail,/sbin/nologin
zhj,/bin/bash
zhj, bin/zhj
[root@master shellfile]# awk -F : -v i=1 '{print $3+$i}' passwd
0
1
2
3
4
5
6
7
8
11
[root@master shellfile]# awk -F : -v i=1 '{print $3+i}' passwd
1
2
3
4
5
6
7
8
9
12
[root@master shellfile]# awk -F : '{print FILENAME ":" NR ":" NF}' passwd
passwd:1:7
passwd:2:7
passwd:3:7
passwd:4:7
passwd:5:7
passwd:6:7
passwd:7:7
passwd:8:7
passwd:9:7
passwd:10:7
passwd:11:7
passwd:12:7
# 空行
[root@master shellfile]# awk -F : '/^$/{print NR}' passwd
[root@master shellfile]# awk -F : '/^$/{print NR}' sed.txt
1
sort
sort 命令 文件进行排序,并将排序结果标准输出
sort (选项)(参数)
-n 依照数值大小 -r 以相反的顺序排序
-t 设置排序所用的分隔符 -k指定需要排序的列
[root@master shellfile]# vim sort.sh
bb:40:5.4
bd:20:4.2
xz:50:2.3
cls:10:3.5
ss:30:1.6
[root@master shellfile]# sort -t : -nrk 3 sort.sh
bb:40:5.4
bd:20:4.2
cls:10:3.5
xz:50:2.3
ss:30:1.6
[root@master shellfile]# sort -t : -nrk 2 sort.sh
xz:50:2.3
bb:40:5.4
ss:30:1.6
bd:20:4.2
cls:10:3.5
11 面试
-
使用linux命令查询file 中空行所在行号 awk ‘/^$/{print NR}’ sed.txt
-
linux命令计算第二列的和 cat chengji.txt | awk -F " " ‘{sum+=$2} END {print sum}’
-
查看一个文件是否存在
if [ -f file.txt ];then
echo “文件存在”
else
echo :文件不存在"
fi
-
对无序文字排序
cat test.txt
sort -n test.txt | awk ‘{a+=$0;print$0}’ END {print "sum="a}’
-
查找/home 下文件包含 shen的文件名称
grep -r “shem” /home | cut -d “:” -f 1