老男孩教育专注IT教育10余年,只培养IT技术精英

全国免费咨询电话(渠道合作):400-609-2893

【运维必会】shell脚本语言入门!老男孩SRE工程师培训

老男孩IT教育

技术博客

2022年8月8日 16:41

Shell脚本语言是实现Linux/UNIX系统管理及自动化运维所必备的重要工具,Linux/UNIX系统的底层及基础应用软件的核心大部分涉及Shell脚本的内容。

  文章目录:

  •   shell脚本前言
  •   shell脚本入门
  •   shell变量基础
  •   shell变量子串
  •   shell数值运算
  •   条件表达式
  •   流程控制语句
  •   shell函数
  •   case语句
  •   shell变量数组

shell培训

  shell脚本前言

  | 为什么学习shell编程

  Shell脚本语言是实现Linux/UNIX系统管理及自动化运维所必备的重要工具,Linux/UNIX系统的底层及基础应用软件的核心大部分涉及Shell脚本的内容

  每一个合格的Linux系统管理员或运维工程师,都需要熟练的编写Shell脚本语言,并能够阅读系统及各类软件附带的Shell脚本内容

  只有这样才能提升运维人员的工作效率,适应日益复杂的工作环境,减少不必要的重复工作,从而为个人的职场发展奠定较好的基础

  | 学好Shell编程所需的基础知识

  ①能够熟练使用vim编辑器,熟悉SSH终端

  ②有一定的Linux命令基础,至少需要掌握80个以上Linux常用命令,并能够熟练使用它。

  ③要熟练掌握Linux正则表达式及三剑客命令(grep,sed,awk)

  | 如何学好Shel编程

  ①学好Shel编程的核心:多练-->多思考-->再练-->再思考,坚持如此循环即可!

  ②新手大忌:不可拿来主义,可以模仿,但是要自己嚼烂了吃下去。

  ③格言:你觉得会了并不一定会了,你认为对的并不一定对的。

  大家要勤动手,自行完成学习笔记和代码的书写。

  shell脚本入门

  | shell是什么?

  Shell是一个命令解释器,它在操作系统的最外层,负责直接与用户对话,把用户的输入解释给操作系统,并处理各种各样的操作系统的输出结果,输出屏幕返回给用户

  这种对话方式可以是:

  ①交互的方式:从键盘输入命令,通过/bin/bash的解释器,可以立即得到shell的回应

  ②非交互的方式:脚本

  | Shell能做什么?

  ①安装操作系统:CentOS6.X和CentOS7.X 手动方式安装或克隆方式自动化安装:cobbler、kickstart 底层都是shell脚本实现

  ②优化SSH:关闭Selinux 优化防火墙,放行 80、443、SSH端口、zabbix监控等服务访问端口

  ③个人需求:加大文件描述符、时间同步、硬件时间、软件时间、YUM源等,都可以写入shell脚本

  ④安装服务 Nginx、Apache Tomcat、PHP、MySQL、Redis、Mongo、docker等例如:PHP5.4和PHP7.1写入shell脚本,实现自动化安装不同版本的服务

  ⑤代码上线:shell脚本自动化发布自动化回滚

  ⑥zabbix监控:硬件、软件、进程、端口号、自定义监控都可以通过shell脚本+定时任务完成

  ⑦日志分析日志统计:命令三剑客+定时任务+shell脚本来实现在ELK集群上的日志展示

  ⑧业务层面

  ⑨辅助开发程序:nohup和python的大量的日志处理

  | 如何Shell编程

  ①重点掌握前面的内容:变量、判断、bash,对它们彻底理解

  ②先看懂,读懂shell脚本

  ③讲完判断,将前面学过的脚本进行完善

  ④自己写简单的脚本,如一些小的项目:生活中:随机点餐、大保健、会员办理,消费、服务 对应价格不同 结账 会员账号 密码 密码丢失

  ⑤有基本适合自己的教材,如:跟老男孩学习Shell编程或者完善的文档

  ⑥不能拿来及用,要搞懂、变成自己的,吸收了后可以解决企业中大部分的shell问题

  一个shell脚本

# cat test.sh
#!/bin/bash
echo "Hello World!"

  | 执行脚本的三种常用的方式

  (1)使用bash或者sh通过解释器执行脚本

  在子shell中执行命令

# sh test.sh

Hello World!

# bash test.sh

Hello World!

  (2)使用路径方式

  全路径执行方式或者当前路径,必须给x权限

# chmod +x test.sh

# /server/scripts/test.sh

Hello World!

# ./test.sh

Hello World!

  (3)使用source或者 . 的方式

# . test.sh

Hello World!

# source test.sh

Hello World!

  (4)其他shell的执行方式

# cat test.sh | bash

Hello World!

# echo ls | bash

test.sh

# bash < test.sh

Hello World!

  shell变量基础

  | 什么是变量

  shell变量是一种很“”的变量,默认情况下,一个变量保存一个串,shell不关心这个串是什么含义,所以若要进行数学运算,必须使用一些命令例如let、declare、expr、双括号等

  shell变量可分为两类:局部变量和环境变量

  1.   局部变量只在创建它们的shell中可用
  2.   环境变量则可以在创建它们的shell及其派生出来的任意子进程中使用

  有些变量是用户创建的,其他的则是专用shell变量

  •   变量名必须以字母或下划线字符开头,其余的字符可以是字母、数字(0~9)或下划线字符
  •   变量名字是大小写敏感的,环境变量推荐设置为字母大写
  •   给变量赋值时,等号周围不能有任何空白符,为了给变量赋空值,可以在等号后跟一个换行符

  变量删除:用set命令可以查看所有的变量,unset var命令可以清除变量var,var相当于没有定义过

  变量只读:readonly var可以把var变为只读变量,定义之后不能对var进行任何更改

  对shell变量的引用方式很多,用这些方式可以方便的获取shell变量的值,变量值的长度,变量的一个字串,变量被部分替换后的值等等

  | 变量值的定义

  字符串定义

# name=Iamlizhenya
# name='I am lizhenya'
# name="I am lizhenya"
# echo $name
I am lizhenya

  双引号和单引号的区别:双引号解析变量,单引号所见即所得不能解析变量,不加引号可以解析变量

  数字的定义

# age="12 23 432"
# echo $age
12 23 432

  命令的定义

通过``调用命令

# date +%F-%H-%M-%S

2022-07-07-18-02-34

# time=`date +%F-%H-%M-%S`

# echo $time

2022-07-07-18-02-40

# 时间是固定 每次调用都相同

# echo $time

2022-07-07-18-02-40

通过$()调用命令

# time=$(date +%F-%H-%M-%S)

# echo $time

2022-07-07-18-02-52

  | 变量可以定义变量

# ip=`ifconfig eth0|awk 'NR==2{print $2}'`

# echo $ip

10.0.0.7

# dir=${ip}_${time}

# echo $dir

10.0.0.7_2022-07-07-18-11-34

  当shell脚本中出现2条以上相同的命令就将它们写成变量

  | 核心位置变量

  $0 的使用

# cat test.sh

#!/bin/bash

echo $0

# sh test.sh

test.sh

# sh /server/scripts/test.sh

/server/scripts/test.sh

$0 的使用方法

在脚本给予用户提示 如何使用脚本

# cat test.sh 

#!/bin/bash

echo $0

echo $"Usage: $0 {start|stop|status|restart|force-reload}"

# sh test.sh

test.sh

Usage: test.sh {start|stop|status|restart|force-reload}

  $n 脚本的参数

# cat test.sh

#!/bin/bash

echo $1

# sh test.sh oldboy

oldboy

序列传参

# cat test.sh

#!/bin/bash

echo $3

# sh test.sh {a..z}

c

# sh test.sh {1..10}

3

  $# 获取脚本传参的总个数

# cat test.sh

#!/bin/bash

echo $1 $2 $3

echo $#

# sh test.sh 1 2 3

1 2 3

3

# sh test.sh {1..20}

1 2 3 

20

  $? 获取上一条命令的返回值

# ls

# echo $?

0

# llll

# echo $?

127

案例:

# cat ping.sh 

#!/bin/bash

ping -c1 -W1 $1 &>/dev/null

[ $? -eq 0 ] && echo "$1 通的" || echo "$1 不通"

# sh ping.sh www.baidu.com

www.baidu.com 通的

# sh ping.sh www.baidu.commmmmm

www.baidu.commmmmm 不通

  $$ 在有多个相同名称的shell环境中使用

# cat test.sh 
#!/bin/bash
echo $$ > /tmp/nginx_pid		 # 将当前的pid号写入文本中

  | 脚本传参的三种方式

  1. 直接传参

# cat test.sh

#!/bin/bash

echo $1 $2

# sh test.sh oldboy 100

oldboy 100

  2. 赋值传参

# cat test.sh

#!/bin/bash

name=$1

age=$2

echo $name

echo $age

# sh test.sh oldboy 200

oldboy

200

# cat test.sh

#!/bin/bash

name=$1

age=$2

echo 姓名: $name

echo 年龄: $age

# sh test.sh oldboy 100

姓名: oldboy

年龄: 100

  3. read读入

# read -p "请输入你的姓名: " name

请输入你的姓名: oldboy

# echo $name

oldboy

第一种书写方式

# cat test.sh

#!/bin/bash

read -p "请输入你的姓名: " name 

read -p "请输入你的年龄: " age

echo name=$name

echo age=$age 

第二种书写方式

# cat test.sh 

#!/bin/bash

read -p "请输入你的姓名和年龄: " name age 

echo name=$name

echo age=$age

  shell变量子串

  | 子串的切片

# name=1234567

# echo ${name:2:2}

34

# echo ${name:2:3}

345

# echo ${name:2:4}

3456

  | 子串的长度统计

# name=1234567

第一种统计方式:

# echo $name|wc -L

第二种统计方式:

# expr length "$name"

第三种统计方式:

# echo $name|awk '{print length}'

第四种统计方式:

# echo ${#name}

  | 子串的删除(支持通配符)

# url='www.baidu.com'

1.#从前面往后删除   ## 贪婪匹配

# echo ${url#www.}

baidu.com

# echo ${url#*.}

baidu.com

# echo ${url#*.*c}

om

# echo ${url#*.*.}

com

# echo ${url##*.}

com

2.%从后面往前删除

# echo ${url%.*}

www.baidu

# echo ${url%.*.*}

www

# echo ${url%%.*}

www

  | 子串的替换

格式:/替换谁/替换成谁  /// 贪婪替换

# url='www.baidu.com'

# echo ${url/w/W}

Www.baidu.com

# echo ${url//w/W}

WWW.baidu.com

# echo ${url/www/WWW}

WWW.baidu.com

# echo ${url/baidu/sina}

www.sina.com

  shell数值运算

  | expr 只支持整数运算

# expr 1 + 1

2

# expr 10 - 10

0

# expr 10 \* 10

100

# expr 10 / 10

1

错误运算方式:# expr 1 + 1.5

expr: non-integer argument

# expr 10 * 10

expr: syntax error

案例: 判断传入的参数是否为整数

# cat expr.sh 

#!/bin/bash

read -p "请输入你的年龄: " age

expr 1 + $age &>/dev/null

[ $? -ne 0 ] && echo "请输入整数" && exit

echo $age

  | $(()) 只支持整数运算

  注意不要和$()冲突了 执行的命令和``相同

# echo $((10+10))

20

# echo $((10-10))

0

# echo $((10*10))

100

# echo $((10/10))

1

随机数取余数 RANDOM 0-32767之间的数字

# echo $((RANDOM%100+1))

82

  | $[] 只支持整数运算

# echo $[10+10]

20

# echo $[10-10]

0

# echo $[10/10]

1

# echo $[10*10]

100

平方:# echo $[10**10]

10000000000

  | let 只支持整数运算

# let a=1+1

# echo $a

2

# let a=1*10

# echo $a

10

i++

let i++  =========== let i=i+1

# let i=i+1

# echo $i

2

# let i++

# echo $i

3

直接运算 ++i i++ 相同 都是自增1

++a

# let ++a

# echo $a

1

  在使用变量的情况下两个是有区别i++先赋值在运算++i 先运算在赋值

# a=1

# b=1

# let i=a++

# let c=++b

# echo $i

1

# echo $c

2

  | bc 支持整数和小数运算

# echo 10+10|bc

20

# echo 10+10.5|bc

20.5

# echo 10*10.5|bc

105.0

# echo 10-10.5|bc

-.5

# echo 10/10.5|bc

0

  | awk 支持整数和小数运算

# awk 'BEGIN{print 10+10}'

20

# echo 10 20|awk '{print $1+$2}'

30

# echo 10 20|awk '{print $1*$2}'

200

# echo 10 20|awk '{print $1/$2}'

0.5

# echo 10 20|awk '{print $1^$2}'

100000000000000000000

  条件表达式

  | 文件表达式

  语法结构:

  第一种:

  test -f /etc/hosts

# test -f /etc/hosts && echo "文件存在"

文件存在

# test -f /etc/host && echo "文件存在"

# test -f /etc/host && echo "文件存在" || echo "文件不存在"

文件不存在

# test -f /etc/hosts && echo "文件存在" || echo "文件不存在"

文件存在

  第二种: 常用

# [ -f /etc/passwd ] && echo "文件存在" || echo "文件不存在"

文件存在

# [ -f /etc/passwdddd ] && echo "文件存在" || echo "文件不存在"

文件不存在

# [ -d /etc/passwd ] && echo "文件存在" || echo "文件不存在"

文件不存在

# [ -d /etc/ ] && echo "文件存在" || echo "文件不存在"

文件存在

# [ -x /etc/ ] && echo "文件存在" || echo "文件不存在"

文件存在

# ll -d /etc

drwxr-xr-x. 79 root root 8192 Oct 19 09:14 /etc

# [ -e /etc/ ] && echo "文件存在" || echo "文件不存在"

文件存在

# [ -w /etc/hosts ] && echo "文件存在" || echo "文件不存在"

文件存在

  注意: 表达式中支持变量和命令

# dir=/tmp

# [ -d $dir ] && echo "文件存在" || echo "文件不存在"

文件存在

# dir=/tmppppp

# [ -d $dir ] && echo "文件存在" || echo "文件不存在"

文件不存在

# ls -d /etc/sysconfig/

/etc/sysconfig/

# [ -d `ls -d /etc/sysconfig/` ] && echo "文件存在" || echo "文件不存在"

文件存在

  | shell数值比较

  语法结构第一种:test 整数1 比较符 整数2第二种:[ 整数1 比较符 整数2 ]

# test 10 -eq 10 && echo 成立 || echo 不成立

成立

# test 10 -ne 10 && echo 成立 || echo 不成立

不成立

# [ 10 -eq 10 ] && echo 成立 || echo 不成立

成立

# [ 10 -ne 10 ] && echo 成立 || echo 不成立

不成立

# [ 15 -ne 10 ] && echo 成立 || echo 不成立

成立

# [ 15 -gt 10 ] && echo 成立 || echo 不成立

成立

# [ 10 -ge 10 ] && echo 成立 || echo 不成立

成立

# [ 10 -le 10 ] && echo 成立 || echo 不成立

成立


支持命令

# [ 50 -gt `echo $((RANDOM%100))|tee file.txt` ] && echo "成立" || echo 不成立

成立

# cat file.txt 

20

  由于篇幅过长,文章分两篇进行发布,其他内容见文章链接:https://www.oldboyedu.com/blog/4348.html

本文经授权发布,不代表老男孩教育立场。如若转载请联系原作者。