linux Shell脚本指南(条件判断、expr执行运算、流程控制、使用函数处理文件、cut、awk、sort、邮件发送) 删除文件脚本 读可用内存发送邮件脚本

本文详细介绍了Shell脚本的基础知识,包括脚本格式、执行方式、变量、字符串、运算符、条件判断、流程控制、函数、Shell工具的使用以及正则表达式。此外,还讲解了如何利用Shell发送邮件,以及两个实用的工作脚本示例,分别是删除文件和监控服务器内存。文章旨在帮助读者掌握Shell脚本的基本操作和常见应用。
摘要由CSDN通过智能技术生成

前言

  Shell 是一个用 C 语言编写的程序,是用户使用 Linux 的桥梁,既是一种命令语言,又是一种程序设计语言。Shell 是Linux系统的用户界面,提供用户与内核的一种交互方式,接收用户输入的命令,并把它送入内核去执行

Linux提供的Shell解析器

/bin/sh
/bin/bash
/sbin/nologin
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
/bin/tcsh
/bin/csh

在这里插入图片描述
Centos默认的解析器是bash:

在这里插入图片描述


1. 脚本格式和执行方式

1.1 脚本格式

  脚本以#!/bin/bash开头(指定解析器)

1.2 第一个Shell脚本

编写脚本,文件后缀为.sh,输出当前时间:

#!/bin/bash
echo "当前时间:"
date "+%Y-%m-%d %H:%M:%S"

1.3 常用执行方式

(1)采用bash/sh加脚本的相对路径或绝对路径(不用赋予脚本执行权限即可)
 sh var.sh  

在这里插入图片描述

bash var.sh 

在这里插入图片描述

(2)采用输入脚本的绝对路径或相对路径执行脚本(必须具有可执行权限)

  若脚本没有指定路径,linux 系统会遍历$PATH 即环境变量寻找脚本
(a)赋予脚本执行权限

chmod u+x var.sh

(b)执行脚本
相对路径执行:

./var.sh

在这里插入图片描述

注:
  方法一,本质是使用bash解析器执行脚本,所以脚本不需要执行权限
  方法二,本质是脚本需要自己执行,所以需要执行权限
  


2. 变量

2.1 系统预定义变量

常用系统变量$HOME、$PWD、$SHELL、$USER

注:

显示当前Shell中所有变量:

set

如:

(a)查看环境变量:

set |grep path

在这里插入图片描述
(b)查看自定义变量

set |grep tomcat

在这里插入图片描述

2.2 自定义变量

(1)语法
  定义变量:变量=值
  撤销变量:unset 变量
  声明静态变量:readonly 变量 (不能unset)

如:
(a)给变量A重新赋值

#!/bin/bash
A=5
A=8
echo $A

在这里插入图片描述

(b)撤销变量A

#!/bin/bash
A=5
unset A
echo $A

在这里插入图片描述

(c)声明静态的变量B=2,unset

#!/bin/bash
readonly B=5
echo $B
unset B=6
echo $B
B=9

在这里插入图片描述
(d)用语句给变量赋值

A=$(ls /etc/profile.d)
B=`ls /etc/profile.d/`

在这里插入图片描述

#!/bin/bash
#for file in $(ls /etc/profile.d)
for file in `ls /etc/profile.d/`
do
echo $file
done

在这里插入图片描述

(2)变量定义规则
  变量名称可以由字母、数字和下划线组成,但是不能以数字开头,环境变量名建议大写
  等号两侧不能有空格
  在bash中,变量默认类型都是字符串类型,无法直接进行数值运算
  变量的值如果有空格,需要使用双引号或单引号括起来

如:

(a)变量是字符串类型,无法直接进行数值运算

#!/bin/bash
A=5
B=6
C=$A+$B
echo $C
D=`expr $A + $B`
echo $D

在这里插入图片描述

(b)变量的值如果有空格,需要使用双引号或单引号括起来

#!/bin/bash
A=i love you
B="i love you"
echo $A
echo $B

在这里插入图片描述

(3)使用变量

${变量名}

  变量名外面的花括号可选,加不加都行,加花括号是为了帮助解释器识别变量的边界

如:

(a)定义变量A,按照变量A拼接s cz输出

#!/bin/bash
A=5
echo ${A}s cz

在这里插入图片描述

(b)可把变量提升为全局环境变量,可供其他Shell程序使用

export 变量名

在这里插入图片描述

2.3 特殊变量

2.3.1 $n
  n为数字,$0代表该脚本名称,$1-$9代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如${10}

在这里插入图片描述

2.3.2 $#
  获取所有输入参数个数,常用于循环
在这里插入图片描述

2.3.3 $*、$@
  代表命令行中所有的参数,$*把所有的参数看成一个整体,而$@把每个参数区分对待

在这里插入图片描述
注:

$*、$@都表示传递给函数或脚本的所有参数,不被双引号包含时,都以$1 $2 …$n的形式输出所有参数
当被双引号包含时,$*会将所有的参数作为一个整体,以"$1 $2 …$n"的形式输出所有参数;$@会将各个参数分开,以"$1" "$2"…"$n"的形式输出所有参数

2.3.4 $?
  最后执行的命令的返回状态。如果返回的值为0,证明上一个命令正确执行;如果值为非0(具体数字取决于命令),则证明上一个命令执行不正确
在这里插入图片描述

2.3.5 数组
  用括号( )来表示数组,不支持多维数组,数组元素之间用空格来分隔;获取数组元素的值,使用${数组名[下标]}; 使用@或*可以获取数组中的所有元素${数组名[*]} ${数组名[@]},下标由 0 开始编号

(1)定义数组

数组名=(值1 值2 ... 值n)

单独定义数组的元素:

数组名[下标]=

如:
定义一个数组,修改下标0值为10:

arr=(5 10 20 30)
echo ${arr[*]}
arr[0]=10
echo ${arr[*]}

在这里插入图片描述
(2)读取数组

${数组名[下标]}

如:

遍历一个数组:

在这里插入图片描述
(3)获取数组的长度

length=${#数组名[@]}

length=${#数组名[*]}

如:
获取数组arr的长度:

arr=(10 2 5 78)
echo ${#arr[*]}
echo ${#arr[@]}

在这里插入图片描述


3. 字符串、运算符、注释

3.1 字符串

(1) 单引号

规则:
  单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的
  单引号字串中不能出现单独一个的单引号(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用

如:

单引号内变量无效:
在这里插入图片描述
一个单引号不能单独出现:

在这里插入图片描述

(2) 双引号

规则:
  双引号里可以有变量
  双引号里可以出现转义字符

获取字符串长度

echo ${#字符串变量}

提取子字符串(第一个字符的索引值为 0)

echo ${字符串变量:1:4}

查找字符出现的位置 (子字符串为fd则查找字符 f 或 d的位置(哪个字母先出现就计算哪个))

echo `expr index $字符串变量 子字符串`

如:
在这里插入图片描述

3.2 运算符

(1)原生bash不支持简单的数学运算,但是可以通过其他命令来实现。expr 是一款表达式计算工具,使用它能完成表达式的求值操作

如:
计算 2 + 2:

#!/bin/bash
var=`expr 2 + 2`
echo ${var}

注: expr 表达式和运算符之间要有空格,如 2+2 是不对的,必须写成 2 + 2;
在这里插入图片描述

计算10*2:

var=`expr 10 \* 2`
echo $var

注:乘号*前边必须加反斜杠(\)才能实现乘法运算
在这里插入图片描述

(2)算术运算符

$((运算式))

$[运算式]

如:
计算(2+3)乘以50

 A=$[(2+3)*50]
 echo $A

在这里插入图片描述

unset A
A=$(((2+3)*50))
echo $A

在这里插入图片描述

3.3 注释

  以 # 开头的行就是注释,会被解释器忽略;多行注释:<<EOF 注释内容 EOF

#!/bin/bash
#注释
:<<EOF 
注释
注释
EOF

在这里插入图片描述


4. 条件判断

4.1 语法

test condition

[ condition ]

(注意condition前后要有空格)

注:条件非空即为true,[ rng ]返回true,[] 返回false
在这里插入图片描述
在这里插入图片描述

4.2 常用判断条件

(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)

(4)字符串比较
  假定变量 a 为 “A”,变量 b 为 “a”:

运算符说明
=检测两个字符串是否相等,相等返回 true
!=检测两个字符串是否不相等,不相等返回 true

如:

(1)-1和-5大小比较


[ -5 -ge -1 ]
echo $?

test -1 -ge -5
echo $?

在这里插入图片描述

(2)var.sh是否具有写权限

test -w var.sh
echo $?

在这里插入图片描述

(3)/root/a.txt 目录中的文件是否存在

[ -e /root/a.txt ]
echo $?

在这里插入图片描述

(4)多条件判断(&& 表示前一条命令执行成功时,才执行后一条命令,|| 表示上一条命令执行失败后,才执行下一条命令)

[ 5 -eq 5 ] && echo $USER || echo no

在这里插入图片描述
(5)比较字符串A和a

在这里插入图片描述

在这里插入图片描述

5. 流程控制

5.1 if判断

if [ 条件判断式 ]
then 
  程序 
fi 

或者

if  [ 条件判断式 ] 
then 
    程序 
elif [ 条件判断式 ]
then
	程序
else
	程序
fi

注:
[ 条件判断式 ] 中括号和条件判断式之前必须有空格 ; if后有空格

如:
输入参数为1,则输出中国

#!/bin/bash
echo $0
if [ $1 -eq 1  ]
 then
echo "中国"
fi

在这里插入图片描述

输入参数为1,则输出中国;输入2为美国;其余为英国

#!/bin/bash
echo $0
if [ $1 -eq 1  ]
 then
echo "中国"
elif [ $1 -eq 2 ]
then
echo "美国"
else 
echo "英国"
fi

在这里插入图片描述

5.2 case语句

case ${变量名} in 
  "值1") 
    程序1 
    ;; 
  "值2") 
    程序2 
    ;; 
  *) 
   默认则执行此程序 
    ;; 
esac

注:
case行尾必须为单词 in,每一个模式匹配必须以右括号结束
双分号;;表示命令序列结束,相当于java中的break
最后的*)表示默认模式,相当于java中的default

如:

输入参数为1,则输出中国;输入2为美国;其余为英国

#!/bin/bash
echo $0
case $1 in

"1")
echo 中国
;;

"2")
echo 美国
;;

*)
echo 英国
;;

esac

在这里插入图片描述

5.3 for循环

语法1:

for (( 初始值;循环控制条件;变量变化 )) 
  do 
    程序 
  done

语法2:

for 变量 in 值1 值2 值n
  do 
    程序 
  done

如:
(1)从1加到100

#!/bin/bash
for((i=1;i<=100;i++))
do
s=$[$s+$i]
done
echo $s

在这里插入图片描述

(2)打印所有输入参数

#!/bin/bash
echo $0
for i in "$@"
do
echo $i
done

在这里插入图片描述
在这里插入图片描述

5.4 while循环

while [ 条件判断式 ] 
  do 
    程序
  done

如:
从1加到100

#!/bin/bash
i=1
s=0
while [ $i -le 100 ]
do
s=$[$s+$i]
i=$[$i+1]
done
echo $s

在这里插入图片描述


6. read读取控制台输入

read (选项) (参数)

选项:

-p:指定读取值时的提示符;
-t:指定读取值时等待的时间(秒)

参数

变量:指定读取值赋予的变量

如:
提示7秒内,读取控制台输入的名称

#!/bin/bash
read -p "7秒内输入密码:" -t 7 passwd
echo $passwd

在这里插入图片描述


7. 函数

7.1 系统函数

(1)basename 获取文件名

  basename命令会删掉所有的前缀包括最后一个/字符,然后将字符串显示出来;suffix为后缀,如果被指定,basename会将path的后缀去掉

basename [path] [suffix] 

如:
截取输入参数 /root/var.sh 的文件名称

#!/bin/bash
basename $1 .sh

在这里插入图片描述

(2)dirname 获取目录

  从给定的包含绝对路径的文件名中去除文件名(非目录的部分),然后返回剩下的路径(目录的部分)

dirname 文件绝对路径

如:
截取输入参数 /root/var.sh 的文件目录

#!/bin/bash
dirname $1 

在这里插入图片描述

(3)提取文件后缀
m=`basename ./MySQL5.7/libaio-0.3.109-13.el7.x86_64.rpm`
echo ${m##*.}

在这里插入图片描述

7.2 自定义函数

定义函数

 function  方法名()
{
	逻辑脚本
	[return 整数值]
}

调用函数

方法名 [参数列表]

  必须在调用函数之前,先声明函数,shell脚本是逐行运行,不会像其它语言一样先编译
  函数返回值,只能通过$?系统变量获得,可以显示加:return返回,如果不加,将以最后一条命令运行结果,作为返回值。return后跟数值n(0-255)

如:
计算两个输入参数的和

#!/bin/bash
function sum()
{
total=$(($1+$2))
echo $total
}

read -p "10s内输入参数1:" -t 10 num1
read -p "10s内输入参数2:" -t 10 num2
sum $num1 $num2

在这里插入图片描述

#!/bin/bash
function sum()
{
return $[$1+$2]
}

read -p "10s内输入参数1:" -t 10 num1
read -p "10s内输入参数2:" -t 10 num2
sum $num1 $num2

在这里插入图片描述


8. Shell工具

8.1 cut

  cut是在文件中负责剪切数据。cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段输出

语法: (默认分隔符是制表符,分隔符必须是单个字符)

cut [选项参数]  filename
选项参数功能
-f列号,提取第几列
-d分隔符,按照指定分隔符分割列
-c指定具体的字符

如:
(1)数据准备 a.txt

第一个参数为 1 !
第二个参数为 2 !
第十个参数为 10 !
第十个参数为 34 !
第十一个参数为 73 !
参数总数有 11!
作为一个字符串输出所有参数 1 2 3 4 5 6 7 8 9 34 73 !

(2)切割第一列

cut -f 1 -d " " a.txt

在这里插入图片描述

(3)切割第二、三列

cut -f 2,3 -d " " a.txt

在这里插入图片描述
(4)切割第二列以后所有

cut -f 2- -d " " a.txt 

在这里插入图片描述

(5)在文件中切割出"参数总数"所在列(grep搜索pattern匹配的行)

cat a.txt |grep "参数总数"

在这里插入图片描述

cat a.txt | grep "参数总数" | cut -d " " -f 1 

在这里插入图片描述

(6)选取系统PATH变量值,第2个":"开始后的所有路径:

echo $PATH

在这里插入图片描述

echo $PATH|cut -d ":" -f 2-

在这里插入图片描述

(7)切割ifconfig 后打印的IP地址

ifconfig ens33|grep netmask|cut  -d "t" -f 2|cut -d " " -f 2

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

8.2 awk

  一个强大的文本分析工具,把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理

awk [选项参数] 'pattern1{action1}  pattern2{action2} pattern3{action3}' 文件名

  pattern:表示AWK在数据中查找的内容,就是匹配模式
  action:在找到匹配内容时所执行的一系列命令

选项参数功能
-F指定输入文件折分隔符
-v给一个用户定义变量 赋值

awk的内置变量

变量说明
FILENAME文件名
NR已读的记录数(行数)
NF浏览记录的域的个数(切割后,列的个数)

如:
(1)数据准备

cp /etc/passwd ./

(2)搜索passwd文件以root关键字开头的所有行,并以:分隔输出该行的第7列

awk  -F ":" '/^root/{print $7}' passwd

在这里插入图片描述

(3)搜索passwd文件以root关键字开头的所有行,并以:分隔输出该行的第1列和第7列,结果以,号分割

awk -F ":" '/^root/{print $1","$7}' passwd

在这里插入图片描述

(4)以:分隔输出/etc/passwd以root关键字开头的行的第一列和第七列,结果以逗号分割,且在所有行前面添加列名user,shell在最后一行添加 no

awk -F ":" 'BEGIN{print "user"} /^root/{print $1","$7} END{print "no"}' passwd

在这里插入图片描述

注:BEGIN 在所有数据读取行之前执行;END 在所有数据执行之后执行
(5)将passwd文件中的用户id增加数值1并输出

awk -F ":" -v a=1 '{print $3+a}' passwd

在这里插入图片描述
(6)统计以:分隔的passwd文件名,每行的行号,每行的列数

awk -F ":" '{print "文件名:" FILENAME " 行号:" NR "当前行列数:" NF }' passwd

在这里插入图片描述
(7)切割IP

ifconfig ens33 |awk -F "t" '/netmask/{print $2}'|awk -F " " '{print $1}'

在这里插入图片描述

8.3 sort

  sort命令将文件进行排序,并将排序结果标准输出。

sort	(选项)	(参数)
选项说明
-n依照数值的大小排序
-r以相反的顺序来排序
-t设置排序时所用的分隔字符
-k指定需要排序的列

参数:指定待排序的文件列表

如:

以:分隔的passwd倒序排序

sort -n -r -t : -k 3 passwd

在这里插入图片描述


9. 正则表达式

9.1 概念

  正则表达式使用单个字符串来描述、匹配一系列符合某个规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本。在Linux中 grep,sed,awk等命令都支持通过正则表达式进行模式匹配

9.2 常规匹配

  一串不包含特殊字符的正则表达式匹配它自己

cat /etc/passwd | grep rng

在这里插入图片描述

9.3 常用特殊字符

(1)^ 匹配一行的开头
如:

 cat /etc/passwd | grep ^root

在这里插入图片描述

匹配出所有以root开头的行
(2)$ 匹配一行的结束
如:

 cat /etc/passwd | grep t$

在这里插入图片描述

会匹配出所有以t结尾的行

注:^$ 匹配空行
在这里插入图片描述

(3). 匹配一个任意的字符
如:

cat /etc/passwd | grep r..t

在这里插入图片描述
(4)* 不单独使用,它和左边第一个字符连用,表示匹配上一个字符0次或多次
如:

 cat /etc/passwd | grep ro*t

在这里插入图片描述

(5)[ ] 表示匹配某个范围内的一个字符

[6,8]------匹配6或者8
[a-z]------匹配一个a-z之间的字符
[a-z]*-----匹配任意字母字符串
[a-c, e-f]-匹配a-c或者e-f之间的任意字符

如:

cat /etc/passwd | grep r[a,b,c]*t

在这里插入图片描述

(6)\ 表示转义,并不会单独使用,转义字符和特殊字符连用,来表示特殊字符本身


10. 邮件发送(以163邮箱为例)

10.1 163邮箱启用smtp服务

开启SMTP服务
在这里插入图片描述
获取授权码和服务器地址
在这里插入图片描述

10.2 linux服务器发送邮件

(1)查看mail (无此命令则yum安装)

mail

在这里插入图片描述
(2)配置发送邮箱

set from=邮箱@163.com
set smtp=smtp.163.com
set smtp-auth-user=邮箱@163.com
set smtp-auth-password=授权码
set smtp-auth=login

(3)发送邮件

如:

在这里插入图片描述
接收邮件成功:
在这里插入图片描述

工作中常用脚本(使用crontab定时调度)

1. 删除文件脚本

#!/bin/bash
#输入参数1为文件的目录 输入参数2为目录大小达到多少进行删除
A=`du -sm ./|cut  -f 1`
echo "$1大小为$A"
test $A -ge $2
echo $?
if [ $A -ge $2 ]
then

for i in  `find $1 -type f`
do
m=`basename $i`
echo "-------"
echo $m
echo ${m##*.}
rm -rf $i
done

fi

2. 读取服务器可用内存数量,发送邮件

#!/bin/bash
FreeMem=`free -m |awk 'NR==2 {print $NF}'`

if [ $FreeMem  -lt $1 ]
then
echo "内存(M):$FreeMem " | tee /tmp/mes.txt
mail -s  "`date '+%Y-%m-%d %H:%M:%S'` $FreeMem" 地址@163.com < /tmp/mes.txt

fi
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

但行益事莫问前程

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

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

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

打赏作者

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

抵扣说明:

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

余额充值