shell 笔记

shell脚本

一、什么是shell脚本

将需要执行的命令保存到文本中,按照顺序执行,它是解释型的,意味着不需要编译

若干命令+脚本的基本格式+脚本特定语法+思想=shell脚本

二、脚本用途

重复化复杂化的工作,通过把工作的命令写成脚本,以后仅仅需要执行脚本就能完成这些工作。

①自动化软件部署 LAMP/LNMP/Tomcat……

​ ansible

②自动化管理 系统初始化脚本,批量更改主机密码,推送公钥

​ 初始环境一致,防火墙,yum源 修改主机名……

③自动化分析处理 统计网站访问量

​ 日志统计 ip 访问量 阿帕奇 ngx

④自动化备份 数据库备份、日志转储……

⑤自动化监控脚本 CPU使用率 硬盘大小……调用脚本预处理

三、如何学习shell脚本

1.记忆更多的命令(记忆命令使用功能和场景)

2.掌握脚本的标准格式(指定魔法字节、使用标准的执行方式运行脚本)

3.必须熟悉掌握脚本的基本语法(重点呢)

4.多看并理解–>多模仿(多练)–>多思考(多写)

shell脚本的基本写法
脚本第一行

魔法字符#!指定解释器【必写】

#!/bin/bash 表示以下内容使用bash解释器解析

如果直接将解释器路径写死在脚本里,可能在某些系统就会存在找不到解释器的兼容性问题,所以可以使用:#!/bin/env 解释器

脚本第二部分

注释#说明 对脚本的基本信息进行描述

#!/bin/env bash

#以下是对脚本内容的基本信息的描述

#Name:名字

#Desc:描述 describe

#Path:存放路径

#Usage:用法

#Update:更新时间

#下面是脚本具体内容

#commands

……

脚本第三部分

脚本要实现的具体代码内容

脚本的执行方式
标准执行方式

#赋予可执行权限 chmod +x first_shell.sh
[root@master shell01]# ll
总用量 4
-rwxr-xr-x 1 root root 239 8月 17 01:29 first_shell.sh
[root@master shell01]# pwd
/shell01
[root@master shell01]# /shell01/first_shell.sh
hello word
hello word
hello word
[root@master shell01]# ./first_shell.sh
hello word
hello word
hello word

非标准执行方式

[root@master shell01]# bash first_shell.sh
hello word
hello word
hello word
[root@master shell01]# sh first_shell.sh
hello word
hello word
hello word
[root@master shell01]# dash first_shell.sh
hello word
hello word
hello word
[root@master shell01]# bash -x first_shell.sh

  • echo ‘hello word’
    hello word
  • echo ‘hello word’
    hello word
  • echo ‘hello word’
    hello word

bash -x 一般用于排错,查看脚本执行过程

bash -n 看脚本语法是否有问题

[root@master shell01]# source first_shell.sh
hello word
hello word
hello word

四、变量
什么是变量

变量是用来临时保存数据的,该数据是可以变化的数据

什么时候需要变量

如果某个内容需要多次使用,并且在代码中重复出现,那么可以用变量代表该内容。这样在修改内容的时候,仅仅需要修改变量的值。

在代码运作的过程中,肯会把某些命令的执行结果保存起来,后续代码需要使用这些结果,就可以直接使用这个变量

变量如何定义

变量名=变量值

[root@master ~]# A=hello 定义变量A
[root@master ~]# echo A 调用变量 A ,要给钱,不是人民币而是美元“ A 调用变量A,要给钱,不是人民币而是美元“ A调用变量A,要给钱,不是人民币而是美元”hello
[root@master ~]# echo ${A} 不管姿势多优雅都要给钱
hello
[root@master ~]# A=world 因为是变量所以可以变
[root@master ~]# echo $A 不管你是谁,调用就要给钱
world
[root@master ~]# unset A 取消变量,不玩了
[root@master ~]# echo $A

[root@master ~]#

变量定义规则

①严格区分大小写

②变量名不能包含特殊符号(*?#@)

③变量名不能以数字开头

④等号两边不能有任何空格

⑤变量名尽量做到见名知意

变量定义方式

调用变量中的某一部分

A=123456

echo $A

echo ${A:2:3}

345

可以把一个命令的结果赋值给变量

[root@localhost ~]# A=hostname
[root@localhost ~]# echo KaTeX parse error: Expected 'EOF', got '#' at position 43: …ot@localhost ~]#̲ unset A [root@…(uname -r)
[root@localhost ~]# echo B
B
[root@localhost ~]# echo $B
4.18.0-305.10.2.el8_4.x86_64

交互式定义变量

目的:让用户自己给变量赋值,比较灵活

语法:read [选项] 变量名

选项 释意

-p 定义提示用户信息

-n 定义字符数(限制变量值的长度)

-s 不显示(不显示用户输入的内容)

-t 定义超时时间,默认单位为秒(限制用户输入变量值时间)

  • 用户自定义变量

[root@localhost ~]# read name
gzh
[root@localhost ~]# echo $name
gzh
[root@localhost ~]#
[root@localhost ~]# read -p “Input your name:” name
Input your name:LYY
[root@localhost ~]# echo $name
LYY
[root@localhost ~]#

[root@localhost ~]# read -s -p “Input your password:” pass
Input your password:[root@localhost ~]#
[root@localhost ~]# echo $pass
456

[root@localhost ~]# read -t 10 -n 5 -p “Input your name:” name
Input your name:12[root@localhost ~]#
[root@localhost ~]# echo $name
12
[root@localhost ~]#

  • 变量值来自文件

    [root@localhost ~]# mkdir shell01
    [root@localhost ~]# chmod +x shell01/
    [root@localhost ~]#
    [root@localhost ~]# cd shell01/
    [root@localhost shell01]# vim ip.txt
    [root@localhost shell01]# cat ip.txt
    10.1.1.1
    [root@localhost shell01]# read -p “请输入IP地址:” IP < ip.txt
    [root@localhost shell01]# echo $IP
    10.1.1.1

定义有类型的变量(delare)

目的:给变量做一些限制,固定变量的类型,比如:整型,只读

用法:declare 选项 变量名=变量值

选项 释意 举例

-i 将变量看成整数(整型) delcare -i A=123

-r 定义只读变量 delacre -r B=hello

-a 定义普通数组;查看普通数组

-A 定义关联数组;查看关联数组

-x 将变量通过环境导出 delacre -x AAA=123456 等于 export AAA=123456

root@localhost shell01]# A=123
[root@localhost shell01]# echo $A
123
[root@localhost shell01]# A=hello
[root@localhost shell01]# echo $A
hello
[root@localhost shell01]# declare -i A=123

[root@localhost shell01]# echo $A
123
[root@localhost shell01]# A=hello
[root@localhost shell01]# echo $A
0
[root@localhost shell01]# A=333
[root@localhost shell01]# echo $A
333

[root@localhost shell01]# declare -r B=hello
[root@localhost shell01]# echo $B
hello
[root@localhost shell01]# B=888
-bash: B: 只读变量
[root@localhost shell01]# unset B
-bash: unset: B: 无法取消设定: 只读 variable
[root@localhost shell01]# exit 退出程序 只读变量是临时的

[root@localhost shell01]# AAAA=gzh
[root@localhost shell01]# env|grep AAAA
[root@localhost shell01]# export AAAA
[root@localhost shell01]# env|grep AAAA
AAAA=gzh
[root@localhost shell01]# declare -x BBBB=itcast
[root@localhost shell01]# env|grep BBB
BBBB=itcast
[root@localhost shell01]#

变量分类

本地变量:当前用户自定义的变量。当前进程中有效,

环境变量:当前进程有效,并且能够被子进程调用。

  • env 查看当前用户的环境变量
  • set 查询当前用户的所有变量(临时变量与环境变量)
  • export 变量名=变量值 或者 变量名=变量值;export 变量名
全局变量

全局所有的用户和程序都能调用,且继承,新建用户也默认能调用

文件名 说明 备注

$HOME/.bashrc 当前用户的bash信息 定义别名、umask、函数等

​ 用户登录时读取

$HOME/.bash_profile 当前用户的环境变量

​ 用户登录时读取

$HOME/.bash_logout 当前用户退出当前 定义用户退出时执行的程序等

​ shell时最后 读取

/etc/bashrc 全局的bash信息,

​ 所有用户都生效

/etc/profile 全局环境变量信息 系统和所有用户都生效

系统变量(内置bash中变量):shell本身已经固定好了它的名字和作用
内置变量含义
$?上一条命令执行后返回的状态;状态值为0表示执行正常,非零表示执行异常或错误
$0当前执行的程序或者脚本名
$#脚本后面接的参数的个数
$*脚本后面所有参数,参数当成一个整体输出,每个变量参数之间以空格隔开
$@脚本后面所有的参数,参数是独立的,也是全部输出
$1~$9脚本后面的位置参数,$1表示第一个位置参数,依次类推
10   {10}~ 10 {n}扩展位置参数,第10个位置变量必须用{}大括号括起来(2位数字以上括起来)
$$当前所在进程的进程号如echo $$
$!后台运行的最后一个进程号 PID(当前终端)
!$调用最后一条命令历史中的参数
五、简单的四则运算

运算符号

表达式举例
$(())echo $((1+1))
$[]echo $[10-5]
exprexpr 10 / 5
letn=1;let n+=1 等价于 let n=n+1

[root@localhost ~]# echo $((1+1))
2
[root@localhost ~]# echo $((10-5))
5
[root@localhost ~]# echo $[85*74]
6290
[root@localhost ~]# echo $[10/8] 求商
1
[root@localhost ~]# echo $[10%8] 求余
2
[root@localhost ~]# echo $[8/10] 求商
0
[root@localhost ~]# echo $[8%10] 求余
8
[root@localhost ~]# echo $[5%10] 求余
5
[root@localhost ~]# echo $[10%7] 求余
3

两个程序

[root@localhost ~]# expr 1+1
1+1
[root@localhost ~]# expr 1 + 1
2
[root@localhost ~]# expr 10 - 5
5
[root@localhost ~]# expr 10 * 5
expr: syntax error: unexpected argument “公共”
[root@localhost ~]# expr 10 * 5 #反斜杠转义一下
50
[root@localhost ~]#

[root@localhost ~]# expr 10 / 5
2

[root@localhost ~]# n=1;let n=n+1;echo $n
2
[root@localhost ~]# let n+=2
[root@localhost ~]# echo $n
4

[root@localhost ~]# let n-+2
[root@localhost ~]# echo $n
4

[root@localhost ~]# let n*=2
[root@localhost ~]# echo $n
8

[root@localhost ~]# let n/=2
[root@localhost ~]# echo $n
4
[root@localhost ~]# let n=n**3 #求次幂
[root@localhost ~]# echo $n
64

小数计算

[root@localhost ~]# echo $[1+1.5]
-bash: 1+1.5: 语法错误: 无效的算术运算符 (错误符号是 “.5”) #普通无法计算
[root@localhost ~]# echo 1+1.5|bc #调用bc
2.5
[root@localhost ~]# bc #或者进入bc
bc 1.07.1
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006, 2008, 2012-2017 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty’.
1+4.5
5.5
quit

i++ #先赋值,再运算

++i #先运算,再赋值

条件判断语句
条件判断语法格式
  • 格式1:test 条件表达式
  • 格式2: [ 条件表达式 ]
  • 格式3: [[ 条件表达式 ]] 支持正则 =~

特别说明:

①[ 两边有空格 ]

②[[ 两边有空格 ]]

③更多判断,man test 去查看,很多参数都用来进行条件判断

条件判断相关参数

问:你要判断什么?
答:我要判断文件类型,判断文件新旧,判断字符串是否相等,判断权限等等

判断文件类型

判断参数含义
-e判断文件是否存在(任何类型文件)
-f判断文件是否存在并且是一个普通文件
-d判断文件是否存在并且是一个目录
-L判断文件是否存在并且是一个软连接文件
-b判断文件是否存在并且是一个块设备文件
-S判断文件是否存在并且是一个套接字文件
-c判断文件是否存在并且是一个字符设备文件
-p判断文件是否存在并且是一个命名管道文件
-s判断文件是否存在并且是一个非空文件(有内容)

判断文件权限

判断参数含义
-r当前用户对其是否可读
-w当前用户对其是否可写
-x当前用户对其是否可执行
-u是否有suid,高级权限冒险位
-g是否sgid,高级权限强制位
-k是否有t位,高级权限粘滞位

判断文件新旧

说明:这里的新旧是指文件的修改时间

判断参数含义
file1 -nt file2比较file1是否比file2新
file1 -ot file2比较file1是否比file2旧
file1 -ef file2比较是否为同一个文件,或者用于判断硬连接,是否指向同一个inode

判断整数

判断参数含义
-eq相等
-ne不等
-gt大于
-lt小于
-ge大于等于
-le小于等于

判断字符串

判断参数含义
-z判断是否为字符串,字符串长度为0则成立
-n判断是否为非空字符串,字符串长度不为0则成立
string1 = string2判断字符串是否相等
string1 = string2判断字符串是否不相等

多重条判断

判断符号含义举例
-a 和 &&逻辑与[ 1 -eq 1 -a 1 -ne 0 ] [1-eq 1 ] && [ 1 -ne 0]
-o 和 ||逻辑或[1 -eq 1 -o 1 -ne 1 ] [ 1-eq 1]

特别说明:

&& 前面的表达式为真,才会执行后面的代码

|| 前面的表达式为假,才会执行后面的代码

; 只用于分割命令或者表达式

类C数值判断

判断是“==” 两个等于号

赋值是“=” 一个等于号

[root@localhost shell01]# (( 1==1 ));echo $? #判断1是否等于1
0 #结果为0 代表真 结果为1 代表假
[root@localhost shell01]#
[root@localhost shell01]# (( 1>=1 ));echo $?
0
[root@localhost shell01]# (( 1>=2 ));echo $?
1
[root@localhost shell01]# (( 1=2 ));echo $?
-bash: ((: 1=2 : 尝试给非变量赋值 (错误符号是 "=2 ")
1
[root@localhost shell01]# (( A1=2 ));echo $?
0
[root@localhost shell01]# echo $A1
2
[root@localhost shell01]# (( 1!=2 ));echo $? #判断不相等只要一个等号
0

字符串比较

注意:双引号引起来,看作一个整体,= 和 == 在 [ 字符串 ] 比较中都表示判断

[root@localhost shell01]# A=hello;B=world;[ “ A " = " A" = " A"="B” ];echo KaTeX parse error: Expected 'EOF', got '#' at position 7: ? 1 #̲判断相等 [root@loca…A" != “$B” ];echo $?
0 #判断不相等

[root@localhost shell01]# A=hello;B=world;[ “ A " = = " A" == " A"=="B” ];echo $?
1

[ ] 和 [[ ]] 的区别

判断字符串为空的时候

一个大括号会出问题(要加双引号)两个没问题(不用加双引号)

判断链接文件是否存在(有效)

[root@localhost shell01]# [ -e test1 -a -L test1 ];echo $?
0

流程控制语句

关键词:选择

1.基本语法结构

if结构

箴言1:只要正确,就一直往前冲

F:表示false 为假

T:表示true 为真

if [ condition ];then

​ command

​ command

fi

if test 条件;then

​ 命令

fi

if [[ 条件 ]];then

​ 命令

fi

[ 条件 ] && command

2.if…else 结构

箴言2:分岔路口,二选一

if [ condition ];then

​ command1

​ else

​ comand2

fi

[ 条件 ] && command1 || command2

3.if…elif…else结构

箴言3:选择很多,能走的只有一条

if [ condition1];then

​ command1 结束

​ elif [ condition2 ];then

​ command2 结束

​ else

​ command3

fi

注释:

如果条件1满足,执行命令1,如果条件1不满足,再看条件2,如果条件2满足执行命令2后结束;如果条件1和条件2都不满足执行命令3结束。

4.层层嵌套结构

箴言4,多次判断,带你走出人生迷雾

if [ condition1 ];then

​ command1

​ if [ condition2 ];then

​ command2

​ fi

​ else

​ if [ condition3 ];then

​ command3

​ elif [ condition4 ];then

​ command4

​ else

​ command5

​ fi

fi

注释:

如果条件1满足,执行命令1,;如果条件2也满足执行命令2,如果不满足就执行命令1结束;如果条件1不满足,不看条件2;直接看条件3,如果条件3满足执行命令3;如果不满足则看条件4,如果条件4满足执行命令4;否则执行命令5

应用案例
1.判断两台主机是否ping通

**需求:**判断当前主机是否和远程主机是否ping通

​ ①思路

​ 1.使用哪个命令实现 ping -c 次数

​ 2.根据命令的执行结果状态来判断是否ping通

​ 3.根据逻辑和语法结构来编写脚本

​ ②落地实现

#!/bin/env bash
#该脚本用于判断当前主机是否和远程指定主机互通

#交互式定义变量,让用户自己决定ping哪个主机


read -p “请输入你要ping的主机IP:” ip

#使用ping程序判断主机是否互通

ping -c1 $ip &>dev/null

if [ $? -eq 0 ];then
	echo "当前主机和远程主机$ip是互通的"
else		
echo "当前主机和远程主机$ip不通的"

fi
2.判断一个进程是否存在

需求:判断web服务器中httpd进程是否存在

​ ①思路

​ 1.查看进程的相关命令 ps pgrep

​ 2.根据命令的返回状态值来判断进程是否存在

​ 3.根据逻辑用脚本语言实现

​ ②落地实现

#!/bin/env bash
#判断一个程序(httpd)的进程是否存在
pgrep httpd &>/dev/null
test $? -eq 0 && echo "当前httpd进程存在" || echo "当前httpd进程不存在"

3.判断一个服务器是否正常

需求:判断门户网站是否能够正常访问

​ ①思路

​ 1.可以判断进程是否存在,用/etc/init.dhttpd status 判断状态等方法

​ 2.最好的方法是直接去访问一下,通过访问成功和失败的返回值来判断

​ linux环境,wget (优先选择)curl elinks -dump 都是没有交互的

​ ②落地实现

#!/bin/env bash
#判断门户网站是否能正常提供服务

#定义变量
web_server=www.itcast.cn#或者写地址
wget -P /shell02/ $web_server &>/dev/null
[ $? -eq 0 ] && echo "当前网站ok" && rm -f /shell02/index.* || echo "当前网站服务不ok,请立刻处理"

grep -w 精确匹配

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WD9w7Gvo-1677225141897)(C:\Users\57736\AppData\Roaming\Typora\typora-user-images\image-20210906113316491.png)]

for循环语句

关键词:爱的魔力转圈圈

列表循环

列表for循环:用于将一组命令执行已知次数

基本语法格式
for variable in {list}
	do
		command
		command
		...
	done
或者
for variable in a b c
	do
		command
		command
	done
	


#!/bin/env bash
#...
for i in {1..199}
	do
		echo $hello 666
	done
不带列表循环

不带列表循环的for循环执行时由用户指定参数和参数的个数

基本语法格式

for variable
	do
		command
		command
		...
	done
类C风格的for循环
for((expr1;expr2;expr3;))
	do
		command
		command
		...
	done
for (( i=1;i<=5;i++ ))
	do
		echo $i
	done
	
# expr1:定义变量并赋初值
# expr2:决定是否进行循环(条件)
# expr3:决定循环变量如何改变,决定循环什么时候退出
应用案例
脚本计算1-100奇数和

①思路

​ 1.定义一个变量来保存奇数的和 sum=0

​ 2.找出1-100的奇数,保存到另一个变量里 i=遍历出来的奇数

​ 3.从1-100中找出奇数后,再相加,然后将和赋值给变量 循环变量 for

​ 4.遍历完毕后,将sum的值打印出来

②落地实现(条条大路通罗马)

#!/bin/env bash
# 计算1-100的奇数和
# 定义变量来保存奇数和
sum=0

# for循环遍历1-100的奇数,并且相加,把结果重新赋值给sum

for i in {1..100..2}
do
	let sum=$sum+$i
done

# 打印所有奇数和
echo "1-100的奇数和是:$sum"
判断所输入整数是否为质数

①思路

​ 1.让用户输入一个数,保存到一个变量里

​ 2.如果能被其数整除就不是质数–> n u m num% numi 是否等于0 $i=2 到num-1

​ 3.如果输入的数是1或者2取模根据上面判断又不符合。所以先排除1和2

​ 4.测试序列从2开始,输入的数是4–>得出结果 n u m 不能和 num不能和 num不能和i相等,并且$num不能小于$1

②落地实现

#!/bin/bash
read -p "请输入一个正整数字:" number

[ $number -eq 1 ] && echo "$number不是质数" && exit
[ $number -eq 2 ] && echo "$number是质数" && exit

#循环判断用户所输入的数字是否为质数
for i in `seq 2 $[$number-1]`
	do
	[ $[number%i] -eq 0 ] && echo "$number不是质数" && exit
	done
echo "$number是质数" && exit

批量创建用户

需求:批量加5个用户,以u1到u5命名,并同一加一个新组,组名为class,统一改密码为123

①思路

​ 1.添加用户命令 useradd -G class

​ 2.判断class组是否存在 grep -w ^class /etc/group 或者groupadd calss

​ 3.根据题意,判断该脚本循环5次来添加用户 for

4. 给用户设置密码 应该放到循环体里面

②落地实现

#!/bin/env bash
#判断class组是否存在
grep -w ^class /etc/group &>/dev/null
test $? -ne 0&& groupadd class

#循环创建用户
for ((i=1;i<=5;i++))
do
	useradd -G calss u$i
done


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

送个祝福给小豪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值