玖叶教程网

前端编程开发入门

shell 脚本编程(shell 脚本编程 书籍推荐)


为什么学习shell编程

Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。每一位合格的Linux 系统管理员或运维工程师,都需要能够熟练地编写 Shell脚本,并能够阅读Linux系统自带的系统脚本内容,只有这样才能提升运维人员的工作效率,适合日益复杂的工作环境,减少不必要的重复性工作,从而为个人的职场发展尊定较好的基础。

学习 Shell 编程需要掌握的基础

1)、熟练使用 vim 文本编辑工具,熟悉SSH 及 .vimrc 配置等

2)、要掌握基础Linux 命令,文本的 增删改查、环境变量的配置使用。

3)、掌握Linux正则表达式及三剑客: grep sed awk的基本使用

4)、熟悉常见的 Linux 网络服务的部署、优化、日志分析及排错

学习shell 脚本的目的在于对公工作中系统及服务等进行自动化的管理,因此如果不熟悉工作中的网络服务,就会很难使用shell 编程处理这些服务;不掌握网络服务等知识,就会让Shell开发者的能力打折扣,甚至只是掌握了 shell 编程的基本语法,并不能真正的学好shell编程。

什么是 Shell

Shell 是一个命令解释器,它的作用是解释执行用户输入的命令及程序等,用户没输入一条命令,Shell 解释器就会执行一天命令,从键盘输入的命令,就会立即得到执行结果的对话方式,我们称之为 交互式shell。

Shell 存在于系统之上用户之下,介于用户系统之间,用来负责于用户和系统直接对话。

什么是 Shell 脚本

使用shell命令编写的文件可执行,我们称之为脚本。脚本一般是一个可执行文件。

脚本语言的种类

  • Bourne Shell(/usr/bin/sh或/bin/sh)
  • Bourne Again Shell(/bin/bash)
  • C Shell(/usr/bin/csh)
  • K Shell(/usr/bin/ksh)
  • Shell for Root(/sbin/sh

注意:查看当前系统支持的shell类型

[root@localhost ~]# cat /etc/shells
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash

其他类型的语言

Php:网页程序语言,动态脚本语言。

Perl:perl脚本语言功能比shell脚本语言强大的多,2010年以前非常流行,目前已在淘汰的边缘。

Python:Python脚本语言近几年非常火的语言,人工智能,web 开发,数据分析,运维脚本开发等都非常好用,入门门槛低

Shell 脚本语言的有点

Shell 脚本语言的优势在于处理偏操作系统底层的业务,如Linux系统内部的很多应用都是使用shell脚本语言开发的,对于一下常规业务操作,使用shell更符合Linux运维 简单、易用、高效的三大原则。

操作系统默认shell

Centos RedHat rockylinux 默认使用shell都是Bourne Again shell(bash)

通过以下两种方法查看系统默认shell类型:

[root@ym ~]# echo $SHELL
/bin/bash
[root@ym ~]# grep ^root /etc/passwd
root:x:0:0:root:/root:/bin/bash

Shell 脚本的创建与执行

  • 打开一个系统脚本文件,我们可以查看脚本的格式
  • 脚本的命名:脚本的拓展名.sh结尾
  • 系统加载shell初始化文件:
/etc/profile # 系统初始化shell环境配置文件
/etc/profile.d/ # 目录存放系统初始化加载的sh脚本文件
~/.bash_profile # 环境变量设置文件
~/.bashrc # 当前登录用户的环境变量配置文件(可能不存在)
  • Shell脚本执行:



通常情况下,在执行shell脚本是,会向系统内核请求启动一个新的进程,在该进程中执行脚本命令及子进程脚本

shell 脚本通常采用一下集中方式执行 实例: bash test.sh 或 sh test.sh ./test.sh 这种方式需要test.sh有可执行权限 source test.sh 或 . test.sh 这种方式一般是读入脚本内容

  • shell脚本的第一行是指定脚本解释器,通常为: #!/bin/bash 或 #!/bin/sh
  • 代码规范实例:
1、#! /bin/bash 
# : 代表注释 #!代表特例  /bin/bash 命令解释器的绝对路径
2、 需要描述脚本的功能、作者、时间、用法、版本的信息
# Name:脚本的名字
# Desc:功能描述 Describe
# Path:存放路径
# Usage:脚本的使用方法
# Update:更新时间
# Author: 作者
# Relase:	版本

什么是Shell变量

1)、什么是变量

简单来说变量就是用一个固定的字符串代替更多的的内容,变量是一个可变化的量一个不固定的量

2)、变量的命名规则

变量名的命名须遵循如下规则:

  • 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
  • 中间不能有空格,可以使用下划线(_)。
  • 不能使用标点符号。
  • 不能使用bash里的关键字(可用help命令查看保留关键字)。

3)、变量的类型

运行shell时,会同时存在三种变量:

  1. 局部变量 局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。
  2. 环境变量 所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
  3. shell变量 shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行

4)、变量的作用域(作用范围)

  • 局部变量只针对于当前shell 生效
  • 全局变量只针对于整个操作系统生效

5)、查看系统的环境变量

  • set 输出所有变量,包括全局变量、局部变量
  • env 只显示全局变量
  • declare 输出所有变量,如同 set
  • export 只显示和设置环境变量
  • 系统中已经存在一些环境变量如:HOME PATH SHELL UID USER MAIL 等,在用户登录之前就已经备/bin/longin 程序设置好。

6)、自定义环境变量

首先按照变量的命名规则使用指定字符,写在等号的左边作为变量的名称(标记),在写一个字符作为值赋值给变量名。

[root@ym ~]# ym_123=hello # 定义一个变量名称叫 ym_123
[root@ym ~]# echo $ym_123 # 使用echo 输出变量所对应的值
hello
  • 单引号:调用变量事不管里面有什么都要原样输出,但引号的内容;
  • 双引号:调用变量时可以调用变量所赋的值,显示变量的内容呢;
  • 反引号:可以调用命令并把命令所输出的结果复制给变量;
  • 无引号:可以复制一个连续的字母或数字给变量,中间不能有空格;
  • export variname=value
  • declare [-aixr] variable 参数: -a :将后面名为 variable 的变量定义成为数组 (array) 类型 -i :将后面名为 variable 的变量定义成为整数数字 (integer) 类型 -x :用法与 export 一样,就是将后面的 variable 变成环境变量; -r :将变量设定成为 readonly 类型,该变量不可被更改内容,也不能 unset

7)、环境变量的配置

  • 用户环境变量配置 .bashrc .bash_profile
  • 全局环境变量配置 /etc/profile /etc/bashrc /etc/profile.d/
[root@ym ~]# echo $PATH # 查看当前系统的环境变量
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@ym ~]# export PATH=$PATH:/usr/local/bin # 添加路径到系统的环境变量中(临时设置系统环境变量,重启操作系统丢失,需要写在配置文件中)

Shell 中特殊的变量

变量

描述

$0

当前脚本的文件名

$n

传递给脚本或函数的参数

$#

传递给脚本或函数的参数个数

$*

传递给脚本或函数的所有参数

$@

传递给脚本或函数的所有参数。被双引号(" ")包含时,与 $* 稍有不同,下面将会讲到。

$?

上个命令的退出状态,或函数的返回值

$

当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID

set -- " I an hostname"
echo $#   # 参数个数
#测试 $* $@ 不带引号
[root@localhost ~]# echo $2
handsone
[root@localhost ~]# echo $*
i am handsone tdlinux
[root@localhost ~]# echo $@
i am handsone tdlinux
[root@localhost ~]# for i in $*;do echo $i;done
i
am
handsone
tdlinux
[root@localhost ~]# for i in $@;do echo $i;done
i
am
handsone
tdlinux
#测试 $* $@ 带双引号
[root@localhost ~]# for i in "$*";do echo $i;done
i am handsone tdlinux
#"$@":把变量分割成:$1,$2,$3
[root@localhost ~]# for i in "$@";do echo $i;done
i am
handsone
tdlinux

实例:$_ 和 himBH

$- 记录的是当前配置打开的shell选项, 而 himBH 是默认值

himBH 每个字母代表着一个shell选项,具体如下:

h - hashall         # bash 的 hash 功能,可以实现让某些 command 和 具体路径 绑定在一起。
i - interactive-comments	# 配置在交互 shell 模式下,是否允许注释。
m - monitor        	 # 配置是否打开控制 Job control 功能。
B - braceexpand    	 # 关于括号使用的flag,打开后可以快捷地实现某些效果
H-  history   		 #是否允許用 “感叹号 !+ history number ” 来执行历史命令

可以通过 set -o 查看来确认打开状态

  • hash 哈希命令参数:

-l 显示哈希表示所有的项目

-r 清除哈希表所有项

-d <名称> 删除哈希表其中的一项

-p <路径> 向哈希表中增加一项内容,添加后就可以使用了

-t <命令> 显示hash表中命令的完整路径,如果没有就会报not found错误

实例:hash

[root@ym ~]# bash   # 进入一个全新的 shell
[root@ym ~]# hash
hash: hash table empty    # 由于是新建 shell,所以hash表为空,符合预期

[root@ym ~]# ls -l

[root@ym ~]# hash
hits    command
   1    /usr/bin/ls
[root@ym ~]# top

[root@ym ~]# hash
hits    command
   1    /usr/bin/ls
   1    /usr/bin/top

[root@ym ~]# uptime
 17:56:40 up 1138 days, 7 min,  1 user,  load average: 0.47, 0.36, 0.28

[root@ym ~]# hash   #  可以看到hash表在不断更新
hits    command
   1    /usr/bin/uptime
   1    /usr/bin/ls
   1    /usr/bin/top

[root@ym ~]# hash -l
builtin hash -p /usr/bin/uptime uptime
builtin hash -p /usr/bin/ls ls
builtin hash -p /usr/bin/top top

[root@ym ~]# hash -p /tmp/mydate  date   # 手动添加hash表

[root@ym ~]# hash -l
builtin hash -p /usr/bin/uptime uptime
builtin hash -p /tmp/mydate date   # 添加成功
builtin hash -p /usr/bin/ls ls
builtin hash -p /usr/bin/top top

[root@ym ~]# date
bash: /tmp/mydate: No such file or directory    # 由于手动添加的hash表指向执行文件不存在,所以报错,这说明新增的hash表确实在work

[root@ym ~]# hash -d  date   # 手动清楚刚加的hash表,使用 -r 则全部清除

[root@ym ~]# hash -l
builtin hash -p /usr/bin/uptime uptime
builtin hash -p /usr/bin/ls ls
builtin hash -p /usr/bin/top top

[root@ym ~]# date   # 恢复
Sun Jan 19 18:02:45 CST 2022
  • i 可以在交互shell 中使用 # 号注释
  • m 任务控制:

Ctrl + z 后台运行

fg 命令将后台任务恢复到前台

  • B 可以使用 {} 来执行命令
  • history 历史命令:

!! : 返回并执行最近的一个历史命令 !n : 返回并执行第 n 个历史命令

8)、bash shell 内置变量命令

bash shell 包含一些内置命令。常用的内部命令有:echo、eval、exec、export、read、shift。下面介绍一些具体的用法

8.1)、echo args 可以使用字符和变量的组合

echo 常用的参数列表

参数

说明

-n

不换行输出

-e

解释转移字符

\n

换行输出

\r

回车

\t

制表符

\b

退格删除前一个字符

\v

纵向制表符

-E

不解析转义字符

\a

发出警告的凤鸣声

8.2)、eval args:当shell 程序执行到eval语句时,shell 读入参数args,并将它们组合成新的可执行命令

[root@ym test]# cat test.sh
#!/bin/sh
echo $0
echo \$#
eval "echo \$#"
[root@ym test]# sh test.sh a b c
test.sh
$3
c


8.3)、exec cmd : exec 命令能够在不创建子shell进程的前提下,在当前shell中执行命令。

#!/bin/sh
seq 1 5 > /tmp/test.log
exec < /tmp/test.log
cat /tmp/test.log
while read line
do
        echo $line

done
echo "ok"
# 执行结果
[root@ym test]# sh 1test.sh
1
2
3
4
5
ok
# 实例2:
[root@ym test]# cat 2test.sh
#!/bin/sh
while read line
do
        echo "##########打印标准输入的内容##########"
        echo "输出读到的一行内容:$line"
        echo "##########重新开始读取标准输入内容####"
        sleep 1
done

[root@ym test]# sh 2test.sh
hello shell
##########打印标准输入的内容##########
输出读到的一行内容:hello shell
##########重新开始读取标准输入内容####
hello world
##########打印标准输入的内容##########
输出读到的一行内容:hello world
##########重新开始读取标准输入内容####
hello python
##########打印标准输入的内容##########
输出读到的一行内容:hello python
##########重新开始读取标准输入内容####

8.4)、read :从标准输入读取字符信息,传给shell程序内部定义的变量

[root@ym ~]# read -p "Plase input your name:" name
Plase input your name:root
[root@ym ~]# echo $name
root

8.5)、shift :shift语句会改变位置参数,即 $1 $2 $3 会变成 $2 $3, 重新排序参数位置。

[root@ym test]# cat test.sh
#!/bin/sh
echo $# # 获取传入的参数个数
shift 
echo $* # 输出传输的所有参数
# 执行结果
[root@ym test]# sh test.sh -c python
2
python

8.6)、exit :退出shell程序,可以在 exit 后面指定一个数字作为状态码 1 - 255 范围

#! /bin/bash
if [ $# -ne 1 ]  #如果传入参数个数等于1,则正常退出;否则非正常退出。
then
	echo "args no!"
	exit 123
else
	echo "args ok!"
	exit 0
fi
[root@ym ~]# sh test.sh
args no!
[root@ym ~]# echo $?
123

shell ( ) (( )) [ ] [[ ]] 用法

  • 小括号()
    • 命令组。括号中的命令将会新开一个子shell顺序执行,所以括号中的变量不能够被脚本余下的部分使用。括号中多个命令之间用分号隔开,最后一个命令可以没有分号,各命令和括号之间不必有空格。
    • 命令替换。等同于cmd,shell扫描一遍命令行,发现了$(cmd)结构,便将$(cmd)中的cmd执行一次,得到其标准输出,再将此输出放到原来命令。
    • 用于初始化数组。如∶array=(a b c d)
  • 双小括号 (())
    • 整数扩展。这种扩展计算是整数型的计算,不支持浮点型。
    • 只要括号中的运算符、表达式符合C语言运算规则.都可用在$((exp))中,甚至是三目运算符。
    • 单纯用(())也可重定义变量值,比如 a=5;((a++)) 可将 $a 重定义为6
    • 常用于算术运算比较,双括号中的变量可以不使用$符号前缀。括号内支持多个表达式用逗号分开。for((i=0;i<5;i++))
  • 单中括号 [ ] 、 双中括号 [[ ]]
    • test <条件表达式> 等价于 [ <条件表达式> ] 语法结构
    • [[ ]] 是拓展的 test 条件测试,可以使用 通配符等进行模式匹配,这是区别于其他几种的语法格式
      • &&、||、>、< 等操作符可以使用与 双中括号[[ ]],不能用于单中括号[ ],在 [ ] 中一般使用 -a -o -gt lt

替换运算符

变量

描述

${var:-word}

如果var存在且非null,返回它的值;否则返回word

${var:=word}

如果var存在且非null,返回它的值;否则将word赋值给var,并返回var的值

${var:?word}

如果var存在且非null,返回它的值;否则显示var:?word

${var:+word}

如果var存在且非null,返回word;否则返回null

模式匹配

模式

描述

${variable#pattern}

如果模式匹配于变量的开头处,则删除匹配的最短部分,并返回剩下的部分

${variable##pattern}

如果模式匹配于变量的开头处,则删除匹配的最长部分,并返回剩下的部分

${variable%pattern}

如果模式匹配于变量的结尾处,则删除匹配的最短部分,并返回剩下的部分

${variable%%pattern}

如果模式匹配于变量的结尾处,则删除匹配的最长部分,并返回剩下的部分

注意:模式匹配处理字符串截取操作

  • 这四种模式中都不会改变 variable 的值,其中,只有在 pattern 中使用了 * 匹配符号时,%和%%,# 和 ## 才有区别
  • 结构中的 pattern 支持通配符如下:
    • *:表示零个或多个任意字符
    • ?:表示仅与一个任意字符匹配
    • [...]:表示匹配中括号里面的字符
    • [!...]: 表示不匹配中括号里面的字符

实例:${variable#pattern}

[root@ym ~]#  var="/usr/share/doc/mysql-common/COPYING.Google"
[root@ym ~]# echo ${var#*/*n/}
COPYING.Google

实例:${variable##pattern}

[root@ym ~]#  var="/usr/share/doc/mysql-common/COPYING.Google"
[root@ym ~]# echo $var
/usr/share/doc/mysql-common/COPYING.Google
[root@ym ~]# echo ${var##/*/}
COPYING.Google

实例:${variable%pattern}

[root@ym ~]#  var="/usr/share/doc/mysql-common/COPYING.Google"
[root@ym ~]# echo ${var%/sh*}
/usr


实例:${variable%%pattern}

[root@ym ~]#  var="/usr/share/doc/mysql-common/COPYING.Google"
[root@ym ~]# echo ${var%%s*}
/u

字符串操作:

[root@ym ~]# echo ${var%s*e} 从最右边删除最短匹配
testca
[root@ym ~]# echo $var
testcase
[root@ym ~]# echo ${var%%s*e} 从最右边删除最长匹配
te
[root@ym ~]# echo $var  变量没有改变
testcase
[root@ym ~]# echo ${var#?e} 从最左边删除最短匹配
stcase
[root@ym ~]# echo $var
testcase
[root@ym ~]# echo ${var#*e}  从最左边删除最短匹配
stcase
[root@ym ~]# echo $var
testcase
[root@ym ~]# echo ${var##*e} 从最左边删除最长匹配,即删除所有

[root@ym ~]# echo $var
testcase
[root@ym ~]# echo ${var##*s} 从最左边删除最长匹配
e
[root@ym ~]# echo $var
testcase
[root@ym ~]# echo ${var#test} 删除test
case
[root@ym ~]# echo $var
testcase
[root@ym ~]# echo ${var#tests} 没有匹配
testcase

Shell 基本运算符

算术运算符

下表列出了常用的算术运算符,假定变量 a 为 10,变量 b 为 20:

算数

说明

实例

+

加法

expr $a + $b 结果为 30。

-

减法

expr $a - $b 结果为 -10。

*

乘法

expr $a \* $b 结果为 200。

/

除法

expr $b / $a 结果为 2。

%

取余

expr $b % $a 结果为 0。

=

赋值

a=$b 将把变量 b 的值赋给 a。

==

相等。用于比较两个数字,相同则返回 true。

[ $a == $b ] 返回 false。

!=

不相等。用于比较两个数字,不相同则返回 true。

[ $a != $b ] 返回 true。

关系运算符

关系运算符只支持数字,不支持字符串,除非字符串的值是数字。

下表列出了常用的关系运算符,假定变量 a 为 10,变量 b 为 20:

运算符

说明

实例

-eq

检测两个数是否相等,相等返回 true。

[ $a -eq $b ] 返回 false。

-ne

检测两个数是否不相等,不相等返回 true。

[ $a -ne $b ] 返回 true。

-gt

检测左边的数是否大于右边的,如果是,则返回 true。

[ $a -gt $b ] 返回 false。

-lt

检测左边的数是否小于右边的,如果是,则返回 true。

[ $a -lt $b ] 返回 true。

-ge

检测左边的数是否大于等于右边的,如果是,则返回 true。

[ $a -ge $b ]返回 false。

-le

检测左边的数是否小于等于右边的,如果是,则返回 true。

[ $a -le $b ] 返回 true。

布尔运算符

下表列出了常用的布尔运算符,假定变量 a 为 10,变量 b 为 20:

运算符

说明

实例

!

非运算,表达式为 true 则返回 false,否则返回 true。

[ ! false ] 返回 true。

-o

或运算,有一个表达式为 true 则返回 true。

[ $a -lt 20 -o $b -gt 100 ] 返回 true。

-a

与运算,两个表达式都为 true 才返回 true。

[ $a -lt 20 -a $b -gt 100 ] 返回 false。

逻辑运算符

以下介绍 Shell 的逻辑运算符,假定变量 a 为 10,变量 b 为 20:

运算符

说明

实例

&&

逻辑的 AND

[[ $a -lt 100 && $b -gt 100 ]] 返回 false

||

逻辑的 OR

[[ $a -lt 100 || $b -gt 100 ]] 返回 true

字符串运算符

下表列出了常用的字符串运算符,假定变量 a 为 “abc”,变量 b 为 “efg”:

运算符

说明

实例

=

检测两个字符串是否相等,相等返回 true。

[ $a = $b ] 返回 false。

!=

检测两个字符串是否相等,不相等返回 true。

[ $a != $b ] 返回 true。

-z

检测字符串长度是否为0,为0返回 true。

[ -z $a ] 返回 false。

-n

检测字符串长度是否为0,不为0返回 true。

[ -n "$a" ] 返回 true。

$

检测字符串是否为空,不为空返回 true。

[ $a ] 返回 true。

文件测试运算符

文件测试运算符用于检测 Unix 文件的各种属性。

属性检测描述如下:

操作符

说明

实例

-b file

检测文件是否是块设备文件,如果是,则返回 true。

[ -b $file ] 返回 false。

-c file

检测文件是否是字符设备文件,如果是,则返回 true。

[ -c $file ] 返回 false。

-d file

检测文件是否是目录,如果是,则返回 true。

[ -d $file ] 返回 false。

-f file

检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。

[ -f $file ] 返回 true。

-g file

检测文件是否设置了 SGID 位,如果是,则返回 true。

[ -g $file ] 返回 false。

-k file

检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。

[ -k $file ] 返回 false。

-p file

检测文件是否是有名管道,如果是,则返回 true。

[ -p $file ] 返回 false。

-u file

检测文件是否设置了 SUID 位,如果是,则返回 true。

[ -u $file ] 返回 false。

-r file

检测文件是否可读,如果是,则返回 true。

[ -r $file ] 返回 true。

-w file

检测文件是否可写,如果是,则返回 true。

[ -w $file ] 返回 true。

-x file

检测文件是否可执行,如果是,则返回 true。

[ -x $file ] 返回 true。

-s file

检测文件是否为空(文件大小是否大于0),不为空返回 true。

[ -s $file ] 返回 true。

-e file

检测文件(包括目录)是否存在,如果是,则返回 true。

[ -e $file ] 返回 true。

-L file

检测文件是否存在且是一个 链接文件,如果是,则返回true。

[ -L $file ] 返回 true。

-S file

检测文件是否存在且是一个socket文件,如果是,则返回true。

[ -S $file ] 返回 true。

file1 -nt file2

检测file1 是否比file2新,如果是,则返回true

[ file1 -nt file2 ]返回 true。

file1 -ot file2

检测file1 是否比file2 旧,如果是,则返回true

[ file1 -nt file2 ]返回 true。

file1 -ef file 2

检测file1 是否和file2 是同一个文件,如果是,则返回true

[ file1 -nt file2 ]返回 true。

Shell 流控制

if else语句

1)、单分支条件判断

#第一种语法:
		if <条件表达式>
			then
				command 指令
		fi
#第二种语法:
		if <条件表达式>;then
				command 指令
		fi

2)、双分支条件判断

if <条件表达式>
then
	command 1
else
	command 2
fi

3)、多分支条件判断

if <条件表达式>
	then
		command1
elif <条件表达式>
	then
		command2
elif <条件表达式>
	then
		command3
eles
		command4
fi

4)、条件判断嵌套语法

#1、 test 条件表达式
 	if test 表达式
		then
			command
	fi
#2、  []条件表达式
	if [字符集或算术表达式]
		then
			command
	fi
#3、 [[]] 条件表达式
	if [[条件表达式]]
		then
			command
	fi
#4、 (())条件表达式
	if((算术表达式))
		then
			command
	fi
#5、 if 命令
		then
			command
	fi

5)、使用脚本发送电子邮件

通过Linux服务器客户端发送邮件及配置
	需要修改:
		vim /etc/mail.rc
			set [email protected] smtp=smtp.163.com
			set [email protected] smtp-auth-password=1qaz2wc smtp-auth=login
	
	注意:如果是163邮箱,需要设置邮箱的一个授权码,将授权吗写入smtp-auth-password,否则发送不了邮件
	邮件测试
		echo "this is a test" | mail -s "标题" [email protected]

for 有限循环

for训话语法格式:

#for 变量 in 要赋予的值
#do 
#   command1-N
#done

for 循环获取变量值

#for i in 1 2 3 4 5
#for i in I don"'"t know if this"'"ll work
#for i in `ls /tmp`
#for i in `cat file`
#IFS=#39;:'(指定分隔符)
#for i in `head -1 /etc/passwd`
#do
#   echo "word:$i"
#done


for 循环 c 语言的写法
#for (( i=0; i<10; i++))
#   do
#         echo $i
#done

#for (( a=0,b=9;a<10,b>=0;a=a+2,b=b-2 ))
#do
#    echo $a   $b
#done

for 循环获取变量方式
#for i in /tmp/*
#for i in `ls /tmp`
    do
 #      if [ -f /tmp/$i ]
 #          then
 #             echo "$i is file"
 #      else
 #            echo "$i is folder"
 #      fi
#done

for 循环练习

# 使用循环计算1到100之间的和

sum=0
for ((i=0;i<=100;i++))
do
   #let sum+=$i
   #((sum+=$i))
   #sum=$[ $sum + $i ]
   #sum=$(expr $sum + $i )
done
echo $sum

while 循环

语法格式

# 语法格式:

#while [ 条件 ]  条件为真
#do
#    command
#done

# while 常用的方法

#while [ 1 -eq 1 ]
#while true
#while :
#until false
#until :
#do
#  date +%S
# sleep 1
#done 

while 嵌套if条件判断

#while :
#  do
#     A=`date +%S`
#                    if [ $A -gt 55 ]
#                        then
#                            exit
#                     fi
#        echo $A
#          sleep 1
#done

while 嵌套for循环

#while :
#  do
#       A=`date +%S`
#           for i in `seq 10 -1 1`
#              do
#                   expr $A + $i
#                       sleep 1
#            done
#sleep 1
#done

循环自增变量

  • 循环自增变量
  • i=expr $i + 1;
  • let i+=1;
  • ((i++));
  • i=$[$i+1];
  • i=$(( $i + 1 ))
  • 实例
#!/bin/bash
i=0;
while [ $i -lt 4 ];
do
      echo $i;
      i=`expr $i + 1`;
      # let i+=1;
      # ((i++));
      # i=$[$i+1];
      # i=$(( $i + 1 ))
done

until 循环(条件不成立循环)

  • until 循环执行一系列命令直至条件为 true 时停止。
  • until 循环与 while 循环在处理方式上刚好相反。
  • 一般 while 循环优于 until 循环,但在某些时候—也只是极少数情况下,until 循环更加有用。

until 语法格式

until condition
do
    command
done
  • break 命令不执行当前循环体内break下面的语句从当前循环退出.
  • continue 命令是程序在本循体内忽略下面的语句,从循环头开始执行

实例:

for i in `seq 1 10`
   do
        if [ $i -eq 5 ]
            then
#                 break
              continue
         fi
            
    echo $i
done

case语句

case语句的语法格式:

case  $VARAIBLE  in  
	PAT1)
		分支1
		;;
	PAT2)
		分支2
		;;
	...
	*)
		分支n
		;;
	esac

注意: case支持glob风格的通配符: *:任意长度的任意字符; ?:任意单个字符; []:范围内任意单个字符; a|b:a或b;

显示一个脚本服务菜单

cpu) display cpu information
mem) display memory information
disk) display disks information
quit) quit

要求:(1) 提示用户给出自己的选择;
	 (2) 正确的选择则给出相应的信息;否则,则提示重新选择正确的选项;
	   
	#!/bin/bash
	#
	cat << EOF
	cpu) display cpu information
	mem) display memory infomation
	disk) display disks information
	quit) quit
	===============================
	EOF

	read -p "Enter your option: " option

	while [ "$option" != "cpu" -a "$option" != "mem" -a "$option" != "disk" -a "$option" != "quit" ]; do
		echo "cpu, mem, disk, quit"
		read -p "Enter your option again: " option
	done

	if [ "$option" == "cpu" ]; then
		lscpu
	elif [ "$option" == "mem" ]; then
		free -m
	elif [ "$option" == "disk" ]; then
		fdisk -l /dev/[hs]d[a-z]
	else
		echo "quit"
		exit 0
	fi		

Array数组

什么是数组array

  • shell数组就是一个元素的集合,它有限个数的元素(变量和字符内容),用一个名字来命名,用下标进行区分,这个名字就称为数组名,组成数组的变量称之为数组元素
  • 使用数组可以缩短和简化程序开发

array数组的定义

数组的定义 及 增删改查

第一种方法:

array=(value1 value2 value3......)

第二种方法:

array=([1]=one [2]=two [3]=three) # 通过指定下标的方式定义数组
array=(1 2 3)

# 查询数组所有元素
echo ${array[*]}

# 显示数组的第一个元素
echo ${array[1]}

# 动态获取数组
array=($(command))

# 打印数组的所有元素
echo  ${array[*|@]} 
# 获取数组的元素个数
echo ${#array[*|@]}

#数组的赋值
array[3]=four

# 数组的删除
unset array[1]

# 数组内容的截取和替换
array=(1 2 3)
echo ${array[@]:1:3}

echo ${array[@]/1/b}

select 循环菜单

  • select也是循环的一种,它比较适合用在用户选择的情况下。

select 语法格式

select 变量名 [in 菜单取值列表]
do
   命令集
done
#!/bin/bash 

fruits=( 
  "add"
  "del"
  "select"
  "watermelon"
) 
PS3="please select a num from menu:"  # 命令提示符
echo "Please guess which fruit I like :"
select var in ${fruits[@]} # ${fruits} 获取数组值
do
  if [ $var = "add" ]; then
    echo "Congratulations, you are my good firend!"
    break
  else
    echo "Try again!"
  fi
done

Function 函数

函数的定义

  • Shell 函数的本质是一段可以重复使用的脚本代码,这段代码被提前编写好了,放在了指定的位置,使用时直接调取即可。

Shell 函数定义的语法格式如下:

function name() {
    statements
    [return value]
}

对各个部分的说明:

  • function是 Shell 中的关键字,专门用来定义函数;
  • name是函数名;
  • statements是函数要执行的代码,也就是一组语句;
  • return value表示函数的返回值,其中 return 是 Shell 关键字,专门用在函数中返回一个值;这一部分可以写也可以不写。

{ }包围的部分称为函数体,调用一个函数,实际上就是执行函数体中的代码。

name() {
    statements
    [return value]
}

函数调用

调用 Shell 函数时可以给它传递参数,也可以不传递。如果不传递参数,直接给出函数名字即可:

name

如果传递参数,那么多个参数之间以空格分隔:

name param1 param2 param3

不管是哪种形式,函数名字后面都不需要带括号。

和其它编程语言不同的是,Shell 函数在定义时不能指明参数,但是在调用时却可以传递参数,并且给它传递什么参数它就接收什么参数。

Shell 也不限制定义和调用的顺序,你可以将定义放在调用的前面,也可以反过来,将定义放在调用的后面。

函数的返回值 return

函数的执行结果返回值:

(1) 使用echo或printf命令进行输出; (2) 函数体中调用的命令的执行结果; 函数的退出状态码 1 - 255: (1) 默认取决于函数体中执行的最后一条命令的退出状态码; (2) 自定义:return

实例:添加10个用户,添加用户的功能使用函数实现,用户名作为参数传递给函数;

#!/bin/bash
# 5: user exists

addusers() {
	if id $1 &> /dev/null; then
		return 5
	else
		useradd $1
		retval=$?
		return $retval
	fi
}

for i in {1..10}; do
	addusers ${1}${i}
	retval=$?
	if [ $retval -eq 0 ]; then
		echo "Add user ${1}${i} finished."
	elif [ $retval -eq 5 ]; then
		echo "user ${1}${i} exists."
	else
		echo "Unkown Error."
	fi
done

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言