目录
一、Shell 介绍
前言:
计算机只能认识(识别)机器语言(0和1),如 (10111010101这种)。但是,我们的"程序猿"们不能直接去写01这样的代码,所以,要想将"程序猿"所编写的代码在计算机上运行,就必须找"人”(工具)来翻译成机器语言,这个"人"(工具)就是我们常常所说的编译器或者解释器。
1. 编程语言分类
· 编译型语言:
程序在执行之前需要一个专门的编译过程,把程序编译成为机器语言文件,运行时不需要重新翻译,直接使用编译的结果就行了。程序执行效率高,依赖编译器,跨平台性差些。如C、C++ 。
· 解释型语言:
程序不需要编译,程序在运行时由解释器翻译成机器语言,每执行一次都要翻译一次。因此效率比较低。比如:Python / JavaScript / Shell 等都是解释型语言。
· 总结:
编译型语言比解释型语言速度较快,但是不如解释型语言跨平台性好。如果做底层开发或者大型应用程序或者操作系开发一般都用编译型语言;如果是一些服务器脚本及一些辅助的接口,对速度要求不高、对各个平台的兼容性有要求的话则一般都用解释型语言。
2. Shell简介
Shell 介于内核与用户之间,负责命令的解释。
· 总结:
Shell 本质上就是人机交互的一个桥梁, 负责解释用户输入的执行。
3. Shell 的种类
既然Shell是一个沟通的“桥梁” , 那么桥梁应该会有很多种。我们可以看下Linux 下有哪些解释器。(主:)
# 查看Linux 操作系统版本信息
[root@TR ~]# cat /proc/version
Linux version 4.18.0-305.3.1.el8.x86_64 (mockbuild@kbuilder.bsys.centos.org) (gcc version 8.4.1 20200928 (Red Hat 8.4.1-1) (GCC)) #1 SMP Tue Jun 1 16:14:33 UTC 2021
# 查询 shells 有哪些类型
[root@TR ~]# cat /etc/shells
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
- /bin/sh # 是bash的一种快捷方式
- /bin/bash # bash是大多数Linux默认的shell,包含的功能几乎可以涵盖shell所有的功能(常用)
- /usr/bin/sh
- /usr/bin/bash
4. 什么是Shell脚本?
一句话来概括就是:将需要执行的命令保存到文本中,按照顺序执行。他是解释型的,意味着不需要编译。
5. Shell 脚本的基本写法
5.1、脚本第一行,必须执行解释器【必写】
#!/bin/hash 表示以下内容使用bash解释器解析。
注意:
如果直接将解释器路径写死在脚本里,可能在某些系统就存在找不到解释器的兼容性问题,所以可以使用:#!/bin/env bash 解释器
5.2、脚本第二部分,对shell脚本的描述【非必写】
这一部分不是必写的, 不过都建议写上,方便后期维护等问题。
#:表示注释的意思
# 以下内容是对脚本基本信息的描述
# Name:名字
# Desc:对脚本的描述
# Path: 存放路径
# Author: 创建人
# UpdateTime: 更新时间
5.3、脚本第三部分,脚本要实现的具体内容
这个部分就是正式开始编写脚本了。这里就不赘述了, 后续会讲解脚本的基本语法。
6. Shell脚本的执行方法
6.1 、标准脚本执行的方法(建议)
# 该目录下有个 Demo.sh 的脚本文件
[root@TR shells]# ll
total 4
-rw-r--r-- 1 root root 25 Dec 6 10:29 Demo.sh
# 1.授权(必须要授权)
[root@TR shells]# chmod +x Demo.sh
# 2.执行脚本
[root@TR shells]# ./Demo.sh
胖太乙
[root@TR shells]#
# 2.执行脚本(方式2)
[root@TR shells]# pwd
/root/shells
[root@TR shells]# /root/shells/Demo.sh
胖太乙
[root@TR shells]#
6.2 、非标准的执行方法(不建议)
[root@TR ~]# cd /root/shells
[root@TR shells]# bash Demo.sh
胖太乙
[root@TR shells]# sh Demo.sh
胖太乙
[root@TR shells]# source Demo.sh
胖太乙
[root@TR shells]# bash -x Demo.sh
+ echo 胖太乙
胖太乙
[root@TR shells]#
-x:一般用于排错,查看脚本的执行过程
-n:用来查看脚本的语法是否有问题
二、变量的定义
1. 变量是什么?
变量:变量就是用来临时保存数据的,并且是可以变化的数据。
2. 什么时候需要使用变量
-
如果脚本需要多次使用,并且在代码中重复出现,那么可以用变量代表该内容。这样在修改内容的时候,仅仅需要修改变量的值。
-
在脚本运作的过程中,可能会把某些命令的执行结果保存起来,后续代码需要使用这些结果,就可以直接使用这个变量。
3. 如何定义变量?
变量名=变量值
[root@TR shells]# name='胖太乙' # 定义变量名 name
[root@TR shells]# echo $name # 读取变量名 name 中的值
胖太乙
[root@TR shells]# echo ${name} # 读取变量名 name 中的值
胖太乙
[root@TR shells]# unset name # 取消变量
[root@TR shells]# echo $name
[root@TR shells]#
4. 变量的定义规则
4.1、变量名区分大小写
[root@TR shells]# name='胖太乙'
[root@TR shells]# Name='Big胖太乙'
[root@TR shells]# echo $name
胖太乙
[root@TR shells]# echo $Name
Big胖太乙
[root@TR shells]#
4.2、变量名不能有特殊符号
[root@TR shells]# *name='胖太乙'
-bash: *name=胖太乙: command not found
[root@TR shells]# &name='胖太乙'
-bash: syntax error near unexpected token `&'
4.3、变量名不能以数字开头
[root@TR shells]# 1name='胖太乙'
-bash: 1name=胖太乙: command not found
[root@TR shells]#
4.4、等号两边不能有任何空格
[root@TR shells]# name = '胖太乙'
-bash: name: command not found
5. 变量的自定义方式有那些?
5.1、基本方式
$变量名 和 ${变量名} 的区别:
相同点: 都可以调用变量
不同点:${变量名} 可以只截取变量值的某一部分, 而$变量名不行。
[root@TR shells]# name='胖太乙'
[root@TR shells]# echo $name
胖太乙
[root@TR shells]# echo ${name:1:2}
太乙
[root@TR shells]#
5.2、命令执行结果赋值给变量
# 获取当前系统的时间
[root@TR shells]# time=`date +%F`
[root@TR shells]# echo $time
2021-12-10
# 获取系统版本信息
[root@TR shells]# version=$(uname -r)
[root@TR shells]# echo $version
4.18.0-305.3.1.el8.x86_64
[root@TR shells]#
5.3、交互式定义变量(read)
目的:让用户自己给变量赋值,比较灵活。
语法:read [选项] 变量名
常见选项:
选项 | 释义 |
---|---|
-p | 定义提示用户的信息 |
-n | 定义字符数(限制变量值的长度) |
-s | 不显示(不显示用户输入的内容) |
-t | 定义超时时间,默认单位为秒(限制用户输入变量值的超时时间) |
# 1.普通用法
[root@TR shells]# read name
胖太乙
[root@TR shells]# echo $name
胖太乙
# 2.带有提示信息的用法
[root@TR shells]# read -p '你的博客名称叫什么?' name
你的博客名称叫什么?胖太乙
[root@TR shells]# echo $name
胖太乙
[root@TR shells]#
2. 变量值来自于某个文件
[root@TR shells]# cat user.txt
张三 15岁
李四 30岁
胖太乙 1000岁
[root@TR shells]# read name age < user.txt
[root@TR shells]# echo $name
张三
[root@TR shells]# echo $age
15岁
[root@TR shells]#
5.4、定义有类型的变量(declare)
目的: 给变量做一些限制,固定变量的类型,比如:整型、只读
用法:declare 选项 变量名=变量值
常用选项:
选项 | 释义 | 举例 |
---|---|---|
-i | 将变量看成整数 | declare -i A=123 |
-r | 定义只读变量 | declare -r B=hello |
-a | 定义普通数组;查看普通数组 | |
-A | 定义关联数组;查看关联数组 | |
-x | 将变量通过环境导出 | declare -x AAA=123456 等于 export AAA=123456 |
6. 变量的分类
6.1、本地变量
- 当前用户自定义的变量。当前进程中有效,其他进程及当前进程的子进程无效。
6.2、环境变量
-
环境变量:当前进程有效,并且能够被子进程调用。
-
env:查看当前用户的环境变量
-
set:
查询当前用户的所有变量(临时变量与环境变量) -
export:变量名=变量值 或者 变量名=变量值;export 变量名
-
[root@TR shells]# export name='胖太乙' # 临时将一个本地变量(临时变量)变成环境变量
[root@TR shells]# env | grep ^name
name=胖太乙
[root@TR shells]#
6.3、全局变量
-
全局变量:全局所有的用户和程序都能调用,且继承,新建的用户也默认能调用.
-
解读相关配置文件
文件名 | 说明 | 备注 |
---|---|---|
$HOME/.bashrc | 当前用户的bash信息,用户登录时读取 | 定义别名、umask、函数等 |
$HOME/.bash_profile | 当前用户的环境变量,用户登录时读取 | |
$HOME/.bash_logout | 当前用户退出当前shell时最后读取 | 定义用户退出时执行的程序等 |
/etc/bashrc | 全局的bash信息,所有用户都生效 | |
/etc/profile | 全局环境变量信息 | 系统和所有用户都生效 |
$HOME/.bash_history | 用户的历史命令 | history -w 保存历史记录 history -c 清空历史记录 |
6.4、系统变量
系统变量(内置bash中变量): shell本身已经固定好了它的名字和作用
内置变量 | 含义 |
---|---|
$? | 上一条命令执行后返回的状态;状态值为0表示执行正常,非0表示执行异常或错误(※ 常用) |
$0 | 当前执行的程序或脚本名 |
$# | 脚本后面接的参数的个数 |
$* | 脚本后面所有参数,参数当成一个整体输出,每一个变量参数之间以空格隔开 |
$@ | 脚本后面所有参数,参数是独立的,也是全部输出 |
$1~$9 | 脚本后面的位置参数,$1表示第1个位置参数,依次类推 |
${10}~${n} | 扩展位置参数,第10个位置变量必须用{}大括号括起来(2位数字以上扩起来) |
$$ | 当前所在进程的进程号,如echo $$ |
$! | 后台运行的最后一个进程号 (当前终端) |
!$ | 调用最后一条命令历史中的参数 |
测试:
# 有一个Demo.sh 的脚本文件, 脚本内容如下
[root@TR shells]# cat Demo.sh
#!/bin/bash
echo "\$0 = $0"
echo "\$# = $#"
echo "\$* = $*"
echo "\$@ = $@"
echo "\$1 = $1"
echo "\$2 = $2"
echo "\$3 = $3"
echo "\$11 = ${11}"
# 无参执行
[root@TR shells]# ./Demo.sh
$0 = ./Demo.sh
$# = 0
$* =
$@ =
$1 =
$2 =
$3 =
$11 =
# 带1个参数执行脚本
[root@TR shells]# ./Demo.sh 1
$0 = ./Demo.sh
$# = 1
$* = 1
$@ = 1
$1 = 1
$2 =
$3 =
$11 =
# 带2个参数执行脚本
[root@TR shells]# ./Demo.sh 1 2
$0 = ./Demo.sh
$# = 2
$* = 1 2
$@ = 1 2
$1 = 1
$2 = 2
$3 =
$11 =
# 带3个参数执行脚本
[root@TR shells]# ./Demo.sh 1 2 3
$0 = ./Demo.sh
$# = 3
$* = 1 2 3
$@ = 1 2 3
$1 = 1
$2 = 2
$3 = 3
$11 =
# 带12个参数执行脚本
[root@TR shells]# ./Demo.sh 1 2 3 4 5 6 7 8 9 10 11 12
$0 = ./Demo.sh
$# = 12
$* = 1 2 3 4 5 6 7 8 9 10 11 12
$@ = 1 2 3 4 5 6 7 8 9 10 11 12
$1 = 1
$2 = 2
$3 = 3
$11 = 11
[root@TR shells]#
三、数组的定义
1. 定义
1.1、一次赋一个值
# 语法
数组名[索引下标]=值
# 案例
array[0]='张三'
array[1]='李四'
array[2]='王五'
array[3]='胖太乙'
1.2、一次赋多个值
# 语法
数组名=(值1 值2 值3 ...)
# 举例1
array1=('张三' '李四' '王五' '赵六' '胖太乙' )
# 举例2
# 也可以将一个文件的内容赋值给数组
# 1. 查看文件内容
[root@TR shells]# cat fun.sh
#!/bin/env bash
hello(){
echo '这是一个hello方法'
}
getName(){
echo '我的名字叫胖太乙'
}
# 开始赋值
[root@TR shells]# array2=(`cat /root/shells/fun.sh`)
# 打印数组全部内容
[root@TR shells]# echo ${array2[*]}
#!/bin/env bash hello(){ echo '这是一个hello方法' } getName(){ echo '我的名字叫胖太乙' }
[root@TR shells]#
2. 读取
# 语法
${数组名[元素下标]}
echo ${array[0]} # 获取数组里第一个元素
echo ${array[*]} # 获取数组里的所有元素
echo ${#array[*]} # 获取数组里所有元素个数
echo ${!array[@]} # 获取数组元素的索引下标
echo ${array[@]:1:2} # 访问指定的元素;1代表从下标为1的元素开始获取;2代表获取后面几个元素
# 举例
[root@TR shells]# echo ${array[0]}
张三
[root@TR shells]# echo ${array[1]}
李四
[root@TR shells]# echo ${array[2]}
王五
[root@TR shells]# echo ${array[3]}
胖太乙
[root@TR shells]# echo ${array[*]}
张三 李四 王五 胖太乙
[root@TR shells]# echo ${#array[*]}
4
[root@TR shells]# echo ${!array[@]}
0 1 2 3
[root@TR shells]# echo ${array[@]:1:2}
李四 王五
[root@TR shells]#
四、四则远算
1. 四则运算符号
表达式 | 举例 |
---|---|
$(( )) | echo $((1+1)) |
$[ ] | echo $[10-5] |
expr | expr 10 / 5 |
let | n=1;let n+=1 等价于 let n=n+1 |
五、条件判断
1. 条件判断语法格式
-
格式1: test 条件表达式
-
格式2: [ 条件表达式 ]
-
格式3: [[ 条件表达式 ]]
注意:
- [ 条件表达式与两边的中括号之间有空格 ]
- [[ 条件表达式与两边的双中括号之间有空格 ]]
2. 条件判断相关参数
判断参数 | 含义 |
---|---|
-e | 判断文件是否存在(任何类型文件) |
-f | 判断文件是否存在并且是一个普通文件 |
-d | 判断文件是否存在并且是一个目录 |
-L | 判断文件是否存在并且是一个软连接文件 |
-b | 判断文件是否存在并且是一个块设备文件 |
-S | 判断文件是否存在并且是一个套接字文件 |
-c | 判断文件是否存在并且是一个字符设备文件 |
-p | 判断文件是否存在并且是一个命名管道文件 |
-s | 判断文件是否存在并且是一个非空文件(有内容) |
test -e Demo.sh # 只要文件存在条件为真
[ -d /shell01/dir1 ] # 判断目录是否存在,存在条件为真
[ ! -d /shell01/dir1 ] # 判断目录是否存在,不存在条件为真
[[ -f /shell01/Demo.sh ]] # 判断文件是否存在,并且是一个普通的文件
3. 判断文件权限
判断参数 | 含义 |
---|---|
-r | 当前用户对其是否可读 |
-w | 当前用户对其是否可写 |
-x | 当前用户对其是否可执行 |
-u | 是否有suid,高级权限冒险位 |
-g | 是否sgid,高级权限强制位 |
-k | 是否有t位,高级权限粘滞位 |
4. 判断文件新旧
判断参数 | 含义 |
---|---|
file1 -nt file2 | 比较file1是否比file2新 |
file1 -ot file2 | 比较file1是否比file2旧 |
file1 -ef file2 | 比较是否为同一个文件 |
5. 判断整数
判断参数 | 含义 |
---|---|
-eq | 相等 |
-ne | 不等 |
-gt | 大于 |
-lt | 小于 |
-ge | 大于等于 |
-le | 小于等于 |
6. 判断字符串
判断参数 | 含义 |
---|---|
-z | 判断是否为空字符串,字符串长度为0则成立 |
-n | 判断是否为非空字符串,字符串长度不为0则成立 |
string1 = string2 | 判断字符串是否相等 |
string1 != string2 | 判断字符串是否相不等 |
六、流程控制
1. 条件判断语法结构
1.1、if 判断
# 语法
if [ condition ];then
command
command
elif [ condition2 ];then
command
command
else
command
command
fi
# 举例:
[root@TR shells]# if [ '胖太乙' == '太乙假人' ];then echo '胖太乙不是太乙假人' ; elif [ '胖太乙' == '玉皇大帝' ] ; then echo '胖太乙不是玉皇大帝'; else echo '胖太乙是太乙真人' ; fi;
胖太乙是太乙真人
[root@TR shells]#
1.2、case 判断
# 语法格式
说明:pattern表示需要匹配的模式
case var in 定义变量;var代表是变量名
pattern 1) 模式1;用 | 分割多个模式,相当于or
command1 需要执行的语句
;; 两个分号代表命令结束
pattern 2)
command2
;;
pattern 3)
command3
;;
*) default,不满足以上模式,默认执行*)下面的语句
command4
;;
esac esac表示case语句结束
# 举例说明
#!/bin/bash
read -p '请输入姓名:' text
case $text in
'张三')
echo '张三是个狂徒,离她远一些'
;;
'马云')
echo '这是中国首富,可以跟他混'
;;
'胖太乙')
echo '这是一个菜鸡,不要看他的文章~~~~~~'
;;
*)
echo '查无此人'
;;
esac
2. 循环语法结构
2.1、for 循环
# 语法1
for variable in {list}
do
command
command
…
done
# 语法2
for variable in a b c
do
command
command
done
# 举例说明
[root@TR shells]# for item in 1 2 3 4;do echo $item ;done
1
2
3
4
[root@TR shells]#
2.2、for 循环不带循环列表
# 语法格式
for variable
do
command
command
…
done
# 举例说明
# 脚本内容如下
[root@TR shells]# cat Demo.sh
#!/bin/bash
for var
do
echo $var
done
# 执行脚本
[root@TR shells]# ./Demo.sh 1 3 5 7 9
1
3
5
7
9
[root@TR shells]#
可以看到, 虽然for 循环没有循环体, 但是确将我们执行执行脚本的参数作为循环体去遍历,如果不传递参数, 默认什么都不输出。
2.3、类C 风格的循环(本人更喜欢这种风格,和C#很像)
# 举例说明
for (( i=1;i<=5;i++))
do
echo $i
done
# 输出结果
[root@TR shells]# cat Demo.sh
#!/bin/bash
for (( i=1;i<=5;i++))
do
echo $i
done
[root@TR shells]# ./Demo.sh
1
2
3
4
5
[root@TR shells]#
2.4、while 循环
while循环的条件是“条件为真”
# 语法
while 条件为真
do
执行命令
done
2.5、until 循环
until循环的条件是“条件为假”
# 语法
until 条件为真
do
执行命令
done
七、随机数
系统变量:RANDOM,默认会产生0~32767的随机整数
# 打印一个随机数
echo $RANDOM
# 查看系统上一次生成的随机数
# set|grep RANDOM
RANDOM=352
# 产生0~1之间的随机数
echo $[$RANDOM%2]
# 产生0~2之间的随机数
echo $[$RANDOM%3]
# 产生0~3之间的随机数
echo $[$RANDOM%4]
# 产生0~9内的随机数
echo $[$RANDOM%10]
# 产生0~100内的随机数
echo $[$RANDOM%101]
# 产生50-100之内的随机数
echo $[$RANDOM%51+50]
# 产生三位数的随机数
echo $[$RANDOM%900+100]
八、正则表达式
1. 正则表达式是什么?
正则表达式(Regular Expression、regex或regexp,缩写为RE),也译为正规表示法、常规表示法,是一种字符模式,用于在查找过程中匹配指定的字符。许多程序设计语言都支持利用正则表达式进行字符串操作。例如,在Perl中就内建了一个功能强大的正则表达式引擎。正则表达式这个概念最初是由Unix中的工具软件(例如:sed和grep)普及开的。支持正则表达式的程序如:locate |find| vim| grep| sed |awk
2. 正则表达式当中的元字符
2.1、正则中普通常用的元字符
元字符 | 功能 | 备注 |
---|---|---|
. | 匹配除了换行符以外的任意单个字符 | |
* | 前导字符出现0次或连续多次 | |
.* | 任意长度字符 | ab.* |
^ | 行首(以...开头) | ^root |
$ | 行尾(以...结尾) | bash$ |
^$ | 空行 | |
[] | 匹配括号里任意单个字符或一组单个字符 | [abc] |
[^] | 匹配不包含括号里任一单个字符或一组单个字符 | [^abc] |
^[] | 匹配以括号里任意单个字符或一组单个字符开头 | ^[abc] |
\^[\^] | 匹配不以括号里任意单个字符或一组单个字符开头 | \^[^abc] |
2.2、正则中其他常用元字符
元字符 | 功能 | 备注 |
---|---|---|
\< | 取单词的头 | |
\> | 取单词的尾 | |
\< \> | 精确匹配 | |
\{n\} | 匹配前导字符连续出现n次 | |
\{n,\} | 匹配前导字符至少出现n次 | |
\{n,m\} | 匹配前导字符出现n次与m次之间 | |
\( \) | 保存被匹配的字符 | |
\d | 匹配数字(grep -P) | [0-9] |
\w | 匹配字母数字下划线(grep -P) | [a-zA-Z0-9_] |
\s | 匹配空格、制表符、换页符(grep -P) | [\t\r\n] |
2.3、扩展类正则常用元字符
扩展元字符 | 功能 | 备注 |
---|---|---|
+ | 匹配一个或多个前导字符 | bo+ 匹配boo、 bo |
? | 匹配零个或一个前导字符 | bo? 匹配b、 bo |
| | 或 | 匹配a或b |
() | 组字符(看成整体) | (my|your)self:表示匹配myself或匹配yourself |
{n} | 前导字符重复n次 | |
{n,} | 前导字符重复至少n次 | |
{n,m} | 前导字符重复n到m次 |
3. 正则元字符一栏表
元字符:在正则中,具有特殊意义的专用字符,如: 星号(*)、加号(+)等
前导字符:元字符前面的字符叫前导字符
元字符 | 功能 | 示例 |
---|---|---|
* | 前导字符出现0次或者连续多次 | ab* abbbb |
. | 除了换行符以外,任意单个字符 | ab. ab8 abu |
.* | 任意长度的字符 | ab.* adfdfdf |
[] | 括号里的任意单个字符或一组单个字符 | [abc][0-9][a-z] |
[^] | 不匹配括号里的任意单个字符或一组单个字符 | [^abc] |
^[] | 匹配以括号里的任意单个字符开头 | ^[abc] |
\^[^] | 不匹配以括号里的任意单个字符开头 | |
^ | 行的开头 | ^root |
$ | 行的结尾 | bash$ |
^$ | 空行 | |
\{n\}和{n} | 前导字符连续出现n次 | [0-9]\{3\} |
\{n,\}和{n,} | 前导字符至少出现n次 | [a-z]{4,} |
\{n,m\}和{n,m} | 前导字符连续出现n-m次 | go{2,4} |
\<\> | 精确匹配单词 | \<hello\> |
\(\) | 保留匹配到的字符 | \(hello\) |
+ | 前导字符出现1次或者多次 | [0-9]+ |
? | 前导字符出现0次或者1次 | go? |
| | 或 | \^root|\^ftp |
() | 组字符 | (hello|world)123 |
\d | perl内置正则 | grep -P \d+ |
\w | 匹配字母数字下划线 |
九、函数
1. 什么是函数?
-
shell中允许将一组命令集合或语句形成一段可用代码,这些代码块称为shell函数
-
给这段代码起个名字称为函数名,后续可以直接调用该段代码的功能
2.如何定义函数?
# 方式1
函数名()
{
函数体(一堆命令的集合,来实现某个功能)
}
# 方式2
function 函数名()
{
函数体(一堆命令的集合,来实现某个功能)
}
3. 如何调用函数?
3.1、命令行调用
# 1.创建了一个“fun.sh”的脚本,脚本内容如下
[root@TR shells]# cat fun.sh
#!/bin/env bash
hello(){
echo '这是一个hello方法'
}
getName(){
echo '我的名字叫胖太乙'
}
# 2. 首选需要 调用一下脚本
[root@TR shells]# source fun.sh
# 3. 然后调用对应的方法
[root@TR shells]# hello
这是一个hello方法
[root@TR shells]# getName
我的名字叫胖太乙
[root@TR shells]#
3.2、环境变量调用
在上面的“变量的分类”中讲到, 文件 ‘$HOME/.bashrc’ 文件会在当前用户登录时读取。所以我们只需要将函数定义到‘.bashrc’ 中就可以全局访问。
# 1.在环境变量中定义了一个 fun 函数
[root@TR shells]# vim ~/.bashrc
# .bashrc
# User specific aliases and functions
fun(){
echo '这是在用户环境变量中的方法!'
}
# 2. 由于我已经是登录的状态, 所以需要重新登录
[root@TR shells]# sudo su
# 3. 调用
[root@TR shells]# fun
这是在用户环境变量中的方法!
[root@TR shells]#
4. 函数传参
函数传参只需要在调用函数的时候, 将参数带上即可,函数内部通过 "$1 $2 $3 $4....."来获取参数
案例:
# 函数获取参数的案例
[root@TR shells]# cat fun.sh
#!/bin/env bash
printInfo(){
echo '我的名字叫' $1
echo '年龄:' $2
echo '家庭住址:'$3
}
[root@TR shells]# source fun.sh
[root@TR shells]# printInfo 胖太乙 1000 乾元山金光洞
我的名字叫 胖太乙
年龄: 1000
家庭住址:乾元山金光洞
[root@TR shells]#
5. return 返回值
- return可以结束一个函数。类似于循环控制语句break(结束当前循环,执行循环体后面的代码)。
- return默认返回函数中最后一个命令状态值,也可以给定参数值,范围是0-256之间。
- 如果没有return命令,函数将返回最后一个指令的退出状态值。
十、expect
1. 什么是expect?
expect是一个自动化交互套件,主要应用于执行命令和程序时,系统以交互形式要求输入指定字符串,实现交互通信。
2. 安装expect
# 安装 expect
yum -y install expect
3. 使用expect
以下是expect常用命令:
spawn # 交互程序开始后面跟命令或者指定程序
expect # 获取匹配信息匹配成功则执行expect后面的程序动作
send exp_send # 用于发送指定的字符串信息
exp_continue # 在expect中多次匹配就需要用到
send_user # 用来打印输出 相当于shell中的echo
exit # 退出expect脚本
eof # expect执行结束 退出
set # 定义变量
puts # 输出变量
set timeout # 设置超时时间
下面我通过几个案例来带大家深入了解expect 的使用。
3.1、【案例1】A服务器通过脚本连接B服务器
- 环境:有两台服务器, 分别是 106.14.157.48 和 101.34.253.57
- 需求:在101.34.253.57服务器上通过脚本连接 106.14.157.48服务器
#!/usr/bin/expect
# 开启一个程序
spawn ssh -p 5000 root@49.232.112.117
# 捕获相关内容
expect {
"(yes/no)?" { send "yes\r";exp_continue }
"password:" { send "*********\r" }
}
interact #交互
通过执行上面的脚本, 可以很方便的实现“免密”登录 。
3.2、【案例2】A服务器通过脚本连接B服务器,并创建文件
#!/usr/bin/expect
# 开启一个程序
spawn ssh -p 5000 root@49.232.112.117
# 捕获相关内容
expect {
"(yes/no)?" { send "yes\r";exp_continue }
"password:" { send "*********\r" }
}
expect "#"
send "rm -rf /tmp/*\r" # 移除文件下所有文件
send "touch file{1..3}\r" # 创建三个文件
send "exit\r" # 退出远程服务器
expect eof # 执行结束 退出
执行上面的脚本, 可以得到如下结果
[root@TR ~]# ll
total 1060
-rw-r--r-- 1 root root 0 Dec 14 21:51 file1
-rw-r--r-- 1 root root 0 Dec 14 21:51 file2
-rw-r--r-- 1 root root 0 Dec 14 21:51 file3