shell_编程基础

shell_编程基础

Scroll Down

查看shell编程帮助手册 man test

01.为什么学习shell脚本,脚本的用途

我们为什么学习shell脚本?
Shell可实现的功能

  1. 不管手动安装操作系统, 还是使用 Kickstart/Cobbler 自动化安装操作系统,系统底层的功能都是使用shell脚本实现的
  2. 使用shell脚本初始化操作系统,优化SSH、修改默认端口禁止root登陆、使用普通登陆提权方式、DNS解析、关闭SElinux 、设置防火墙允许的规则或端口、调整文件描述符、时间同步、字符集调整、安装常用软件、命令行安全等。
  3. 安装服务: 使用Shell脚本根据服务不同的版本号进行安装, 统计开发常用的版本号,写成脚本
    配置服务: 使用shell脚本进行修改.
  4. 启动服务的脚本 C6/C7 /etc/init.d/network Nginx启动脚本,停止程序,自发开发的程序会写启动脚本
    比如启动一个py文件:
    nohup python3.5 test.py --mysql-ip 10.0.0.51 --redis-ip 10.0.0.52 --port 6379 &
    停止py程序:
    ps 查找py进程 然后KILL掉
  5. Shell脚本进行代码上线.
    开发写代码,写完代码给运维,运维进行打包,备份源码,放到站点目录解压,把这过程写入shell脚本进行自动化代码上线.
    现在代码上线:Git+Jenkins+Shell脚本进行代码发布.
    从开发修改-页面发布-用户可以浏览-代码上线.
  6. 监控 Zabbix Cacti网卡流程 Nagios监控硬件交换机路由器
    取值 --- 测试 -- 加入zabbix中
    (使用Shell脚本进行取值)
    硬件 服务监控 端口监控 连接状态监控 流量监控 日志监控等
  7. 日志分析 ELK日志展示 Shell脚本进行日志统计分析 AWK sed Grep等
    日志切割 1.MV 2.重载服务

02.学习shell脚本用到的基础知识

  1. 熟练掌握VIM编辑器
  2. 熟悉SSH终端 Xshell CRT
  3. 熟练掌握Linux基础命令,因为命令的集合就是脚本
  4. 熟练掌握Linux正则表示式及AWK sed Grep

03.如何学习shell脚本

  1. Shell包含的内容: 变量基础 条件表达式 if判断 For循环 While循环 Utile循环 Case语句 循环过程中控制指令 Continue Break Exit 数组
  2. 能看懂别人写的代码,掌握常见的各种语法,练习-重复编写Shell脚本
    从简单的变量 判断循环开始
    阅读-模仿 重复 分析 总结-->文档
  3. 要有编程思维
  4. 找一本合适的教材(老男孩Shell脚本 项目最多) 较全面的笔记
    大忌: 不可拿来主意 可以模仿 一定要吃透 看懂 ->提升编程水平
    学完Shell可以解决企业大部分脚本问题

4书写shell脚本规范

  1. 脚本存放固定的目录 mkdir /server/scripts -p 为了方便统一管理
  2. 开头需要加脚本的解释器 #!/bin/sh 指定解释器
  3. 附带作者及版本信息 对当前版本的说明
    #作者 Author lzy
    #时间 Crete time 20201010
    #事件 cut log backup
    #联系方式 QQ 110
    #版本 Version v1.0
  4. 脚本扩展名使用.sh结尾
  5. 注释尽量不使用中文
  6. 成对的符号和循环格式一次性书写完毕

05.shell脚本执行的三组方式

  1. 使用bash执行脚本,在子shell中执行
    sh test.sh
    ./test.sh
  2. 使用source和.执行,在父shell中执行
    . test.sh
    source test.sh
  3. 其它方式
    cat test.sh | bash
    bash < test.sh

06.变量的分类

  • 环境变量(全局变量)
  • 普通变量(局部变量)

07.变量的生命周期划分

  • 永久的: 需要修改环境变量配置文件,变量永久生效 /etc/profile
  • 临时的: 直接使用export声明变量即可,关闭shell则变量失效

08.变量名字的定义

  • 变量名的要求: 字母、数字、下划线的组成,尽量以字母开头,见名知其意,等号两遍不允许有空格。

  • 变量名=变量值

  • 获取值变量的值: $变量名

  • 系统环境都是大写字母

  • 查看系统的环境变量env

  • oldboy_age 全小写

  • Oldboy_Age 大驼峰语法 首字母大写

  • oldboy_Age 小驼峰语法

  • OLDBOY_AGE 全大写

09.值的定义 数字 字符串

  1. 数字变量内容定义, 必须为连续的数字
    oldboy_age=18
  2. 字符串的定义方式, 默认是双引号 混合字符串必须加双引号 数字 字符串 变量
    oldboy='I am oldboy teacher'
  3. 单引号和双引号的区别
  • 单引号: 所见即所得 吃什么吐什么 定义的什么值输出或者调用的就是什么值 不会解析变量
  • 双引号:可以解析变量

10.定义变量加export和不加的区别

  • 不加export: 则只对当前的shell生效
  • 加 export: 则对当前打开窗口所有的shell生效

11.shell特殊变量

$0 - 获取当前Shell脚本的文件名, 如果脚本全路径执行则显示全路径, basename 只获取脚本名称。

$n - 获取当前脚本的第n个参数,n为0则是脚本名称,从$1开始代表脚本的第一个参数, $9以后需要加{} ${10}

$# - 获取shell脚本所有传参的总个数

$* 和 $$$@
获取shell脚本所有传参的参数,如果不加双引号则和$@相同,在循环语句中如果加上双引号,则表示将所有的参数视为单个字符串

$? - 获取执行上一条命令的执行状态结果,返回值0为成功 非0失败

$$ - 获取当前脚本的PID
echo $$ > /tmp/test_sh.pid

$! - 获取上一个后台工作脚本进行的PID
echo $!

$_ - 获取脚本最后的一个参数 类似于ESC .

12.传参的三种方法

1.直接传参

[root@shell scripts]# cat test.sh
    #!/bin/bash
    ping -c1 -W1 $1 &>/dev/null
    [ $? -eq 0 ] && echo "ping $1 is ok" || echo "ping $1 is error"
[root@shell scripts]# sh test.sh www.baidu.com
	ping www.baidu.com is ok
[root@shell scripts]# sh test.sh www.baiduuuu.com
	ping www.baiduuuu.com is error

2.变量赋值


[root@shell scripts]# cat test.sh
    #!/bin/bash
    url=$1
    ping -c1 -W1 $url &>/dev/null
    [ $? -eq 0 ] && echo "ping $url is ok" || echo "ping $url is error"
[root@ldx ~]#sh test.sh 
	ping  is error
[root@ldx ~]#sh test.sh www.baidu.com
	ping www.baidu.com is ok

3.read读入


    [root@shell scripts]# cat test.sh
        #!/bin/bash
        read -p "Please input url: " url
        ping -c1 -W1 $url &>/dev/null
        [ $? -eq 0 ] && echo "ping $url is ok" || echo "ping $url is error"
    ----------------
        read -p "Please input name:" name
        read -p "Please input age:"  age
        echo $name
        echo $age
    -----------------
        read -p "Please input name and age: " name age
        echo $name
        echo $age

13.变量的切片和获取字符长度的操作

  1. 变量子串切片
  • ${变量:n:m} - 从下标2开始,切m个字符
[root@ldx ~]#name='I am lidexian'
[root@ldx ~]#echo ${name:2:4}
am l
  1. 统计变量值字符串长度
  • 统计字符串的方法
[root@ldx ~]#echo $name
I am lidexian
[root@ldx ~]#echo $name | wc -L
13
[root@ldx ~]#echo $name | awk '{print length}'
13
  • 使用变量统计的方法 -- $
[root@ldx ~]#echo ${#name}
13
  • 示例 -- 输出每个单词的长度
[root@ldx ~]#echo $name | xargs -n1 | awk '{print length}'
1
2
8

14.变量的删除和替换

  1. 变量删除 -- ${变量#*.}
  • # 表示从行首开始删除
  • * 删除任意字符
  • . 删除到第一个点结束
[root@ldx ~]# url='www.sina.com.cn'
[root@ldx ~]# echo ${url#*.}
sina.com.cn
  1. ${变量#..} - 删除到第二个点结束
[root@ldx ~]#url='www.sina.com.cn'
[root@ldx ~]#echo ${url#*.*.}
com.cn
  1. ${变量##*.} - 2个#表示贪婪匹配,匹配到最后一个点
[root@ldx ~]#url='www.sina.com.cn'
[root@ldx ~]#echo ${url##*.}
cn
  1. ${url%.*}
  • % 表示从行尾开始删
  • * 删除任意字符
  • . 删除到点结束
[root@ldx ~]#url='www.sina.com.cn'
[root@ldx ~]#echo ${url%.*}
www.sina.com
  1. ${url%%.*} - 贪婪匹配,匹配到第一个点结束
[root@ldx ~]#url='www.sina.com.cn'
[root@ldx ~]#echo ${url%%.*}
www
  1. 变量的替换
  • ${变量/被替换内容/替换内容} - 替换第一个就结束
[root@ldx ~]#url='www.sina.com.cn'
[root@ldx ~]#echo ${url/w/a}
aww.sina.com.cn
  • ${变量//被替换内容/替换内容} - 全局替换
[root@ldx ~]#url='www.sina.com.cn'
[root@ldx ~]#echo ${url//w/a}
aaa.sina.com.cn

15. 变量数值运算

  1. expr - 只能做整数运算
[root@ldx ~]#num1=3
[root@ldx ~]#num2=5
[root@ldx ~]#expr $num2 - $num1 + $num1 \* $num2 / $num1
7
  1. $(()) 双括号是运算,单括号是执行变量,只支持整数运算
[root@ldx ~]#num1=3
[root@ldx ~]#num2=5
[root@ldx ~]#echo $(($num2 - $num1 + $num1 * $num2 / $num1))
7
  1. $[] 只支持整数运算
[root@ldx ~]#num1=3
[root@ldx ~]#num2=5
[root@ldx ~]#echo $[$num2 - $num1 + $num1 * $num2 / $num1]
7
  1. let a++ 只支持整数运算
[root@ldx ~]#let a++
[root@ldx ~]#echo $a
1
[root@ldx ~]#let a++
[root@ldx ~]#echo $a
2
  1. bc - 支持小数运算
[root@ldx ~]#a=1.2
[root@ldx ~]#b=2.1
[root@ldx ~]#echo $a + $b | bc
3.3

16.shell条件判断语句

  1. 文件判断语句
  • [ -e file|dir ] 文件或目录存在即为真
  • [ -f file ] 文件存在即为真
  • [ -d dir ] 目录存在即为真
  • [ -r file ] 文件存在,且拥有读权限则为真
  • [ -w file ] 文件存在,且拥有写的权限则为真
  • [ -x file ] 文件存在,且拥有执行权限则为真
  1. 整数数值比较
表达式描述英文
[ $num -eq 10 ]等于equal
[ $num -ne 10 ]不等于not equal
[ $num -ge 10 ]大于等于greater or equal
[ $num -le 10 ]小于等于less or equal
[ $num -gt 10 ]大于greater than
[ $num -lt 10 ]小于less than

注意 如果是在[[]] (()) 中的比较使用 = != > >= < <=

  1. 多条判断语句
  • -a and 两端都要成立则为真
  • -o or 一端成立则为真
[root@ldx ~]#[ 10 -eq 10 -a 3 -gt 5 ] && echo true || echo error
error
[root@ldx ~]#[ 10 -eq 10 -o 3 -gt 5 ] && echo true || echo error
true

16.字符串对比和正则比对

  1. 字符串对比
  • [ str1 = str2 ] 等于
  • [ str1 != str2 ] 不等于
  1. 正则比对 - 需要使用双中括号 [[]]
  • [[字符串 =~ 正则]]
[root@ldx ~]#name='I am lidexian'
# 匹配与n结尾的字符串
[root@ldx ~]#[[ $name =~ n$ ]] && echo success || echo failed
success

# 匹配以i开头的字符串
[root@ldx ~]#[[ $name =~ ^i ]] && echo success || echo failed
failed

17. if判断语句

  • fi - 表示判断语句结束
  1. 单分支判断
if [ $num -eq 10 ];then
    # 成立则执行
    echo "$num == 10"
fi
  1. 双分支判断
if [ $num -eq 10 ];then
    # 成立则执行
    echo "$num == 10"
else
    # 否则执行
    echo "$num != 10"
fi
  1. 多项分支
if [ $num -eq 10 ];then
    # 成立则执行
    echo "$num == 10"
elif [ $num -gt 10 ];then
    # 判断条件成立,且上面的都不成立则执行
    echo "$num > 10"
else
    # 上面的都不成立执行
    echo "$num != 10"
fi

18. case判断语法

    1. 等于0则执行
  • ;; 表示结束
num=1
case $num in
  0)
     echo 000000
     ;;
  1)
     echo 111111
     ;;
  *)
     echo p、匹配任意字符
     ;;

19. 循环语句

break 跳出循环
continue 跳过当前一次循环
do 表示开始执行操作
done 表示循环语句结束

  1. for循环
[root@ldx scripts]#cat test.sh 
 #!/bin/bash
for i in 1 2 3
do
echo $i
done
[root@ldx scripts]#sh test.sh 
1
2
3
  1. while循环
# 直接执行
while 判断条件
do
  执行语句
done

# 逐行读取文本进行操作
while read line
do
  echo $line
done < file

20. function 函数

  1. 定义方式
# 简写方式
func(){
	echo $1
}

# 官方完整版
function func(){
	echo $1
}
  1. 调用方式
function func(){
	echo $1
}

# 调用
func
  1. 传参方式
# $1 为第一个参数,$2 第二个参数
function func(){
	echo $1 $2
}

# 调用
func 10 20

# 调用结果
10 20

21. 多线程执行

  • 用大括号包裹,在大括号后面加&
for i in `seq 100`
do
    {
	ping www.baidu.com &>/dev/null
	if [ $? -eq 0 ];then
	    echo 'ping www.baidu.com ok'
	else
	    echo 'ping www.baidu.com failed'
	fi
    }&
done

22. wait 等待

  • 会等待wait上面的程序全部执行完成,才会执行下面的
for i in `seq 100`
do
    {
	ping www.baidu.com &>/dev/null
	if [ $? -eq 0 ];then
	    echo 'ping www.baidu.com ok'
	else
	    echo 'ping www.baidu.com failed'
	fi
    }&
done
wait
echo 'ping 全部执行完成'

23. 数组

  • unset array 取消数组定义
  1. 定义
  • 数组的值写在小括号()里,元素以空格分割
array=(1 2 3)
array[4]=4
  1. 查看
# 查看全部值
echo ${array[*]}

# 查看数组所有下标
echo ${!array[*]}

# 查看数组长度
echo ${#array[*]}

# 查看单个值
echo ${array[1]}
  1. 关联数组定义
declare -A  array
array=([a]=1 [b]=3)
array[c]=4