一、Shell脚本基础
1.1 shell的作用
Shell(壳) 是一类程序的总称,用于将人类使用的高级语言转换成机器能看懂的二进制语言,为用户和内核之间的交互提供接口。
1.2 shell脚本简介
1.2.1 什么是shell脚本?
Shell脚本是一种用于编写和执行命令序列的脚本语言
Shell脚本可以通过文本文件的形式保存,并使用shell解释器来执行。
Shell脚本可以包含命令、条件判断、循环、函数等,可以使用变量、数组、字符串处理、文件操作等功能。
1.2.2 应用场景
- 将简单的命令组合完成复杂的工作,自动化执行命令,提高工作效率
- 减少手工命令的重复输入,一定程度上避免人为错误
- 将软件或应用的安装及配置实现标准化
- 用于实现日常性的,重复性的运维工作,如:文件打包压缩备份,监控系统运行状态并实现告警等
1.3 Shell脚本构成
以一个简单的shell脚本为例
#!/bin/bash
# 打印当前日期和时间
echo "当前日期和时间:"
date
# 创建一个目录
mkdir test
# 进入该目录
cd test
# 创建一个文件并写入内容
echo "Hello, World!" > t1.txt
# 显示文件内容
cat t1.txt
#!/bin/bash
使用Bash解释器执行脚本。
echo "当前日期和时间:"
使用echo命令打印一段文本,即"当前日期和时间:"。
date
输出当前的日期和时间。
mkdir mydirectory
创建一个名为test的目录。
cd test
进入test目录。
echo "Hello, World!" > myfile.txt
将"Hello, World!"写入到t1.txt文件中
cat myfile.txt
显示t1.txt文件的内容。
1.4 Shell脚本执行方式
以/test/t1.sh为例
想要用tab键补全脚本名,需要做软链接,将目标脚本链接到$PATH的目录下。
1.4.1 路径方式 (需要赋予执行权限)
绝对路径
/test/t1.sh
相对路径
cd /test
./t1.sh
1.4.2 指定shell解释器去执行(不需要权限)
bash /test/t1.sh
1.4.3 source 和 . (不需要权限)
source命令会直接在当前shell中执行脚本文件的内容,会直接影响当前shell的环境,所以不推荐用这种方式
#执行方式三#
source 脚本名(绝对路径)
source /test/t1.sh
或者
. /test/t1.sh
1.5 Shell脚本错误调试
-
语法错误
会导致后续的命令不继续执行,可以用bash -n 检查错误,提示的出错行数不一定是准确的。 -
命令错误
默认后续的命令还会继续执行,用bash -n 无法检查出来 ,可以使用 bash -x 进行观察。 -
逻辑错误
只能使用 bash -x 进行排错。
bash -x #模拟执行,可以逐条排错
bash -n #检查语法错误
二、重定向与管道符
2.1 重定向
- 交互式硬件设备
类型 | 设备文件 | 文件描述编号 | 默认设备 |
---|---|---|---|
标准输入 | /dev/stdin | 0 | 键盘 |
标准输出 | /dev/stdout | 1 | 显示器 |
标准错误输出 | /dev/stderr | 2 | 显示器 |
标准输入:通过输入设备(键盘 鼠标 扫描仪等)将数据输入到电脑中。
标准输出:输出正确的运算结果 。
标准错误输出:输出不正确的结果。
- 重定向操作
类型 | 操作符 | 用途 |
---|---|---|
重定向输入 | < | 从指定的文件读取数据,而不是从键盘输入 |
重定向输出 | 1> | 将输出结果保存到指定的文件(覆盖原有内容) |
>> | 将输出结果追加到指定的文件尾部 | |
标准错误输出 | 2> | 将错误信息保存到指定的文件(覆盖原有内容) |
2>> | 标准错误输出结果追加到指定的文件尾部 | |
混合输出 | &> | 将标准输出、标准错误的内容保存到同一个文件中,无论对错都可以重定向 |
2.2 管道符
管道符 命令1 | 命令2
将管道符号“|"左侧的命令输出的结果,作为右侧命令的输入(处理对象),同一行命令中可以使用多个管道。
#举例#
ifconfig ens33 | grep -w inet | tr -s ''| awk '{print $2}'t`
#显示当前主机的IP地址
三、Shell脚本变量
3.1 变量简介
3.1.1 作用
Shell 变量用来存放系统和用户需要使用的特定参数(值),而且这些参数可以根据用户的设定或系统环境的变化而相应变化。
3.1.2 变量类型
-
自定义变量:由用户自己定义,修改和使用。
-
特殊变量:环境变量、只读变量、位置变量、预定义变量。
3.2 自定义变量
3.2.1 定义新变量
变量名=变量值
#=号前后不能有空格
name=111 #定义一个新变量,变量名为name,变量值为111
3.2.2 查看自定义的变量
echo $变量名 #查看变量值
echo $name
3.2.3 赋值时的特殊符号
特殊符号 | 功能 |
---|---|
{ } | 确定变量范围 |
’ ’ | 不识别变量,当成字符 |
" " | 识别变量 |
$( ) 或者 `` | 直接调用命令 |
3.2.4 read -p
read -p
是一个常用的Bash命令,用于从用户输入中读取值并将其存储在变量中。
-p 选项用于显示提示信息,提示用户输入。
#以简单的shell脚本为例
#!/bin/bash
read -p "请输入你的名字: " name
echo "你好,$name!"
3.2.5 将局部变量变为全局变量
局部变量:新定义的变量只在当前的shell环境中有效,当进入子程序或新的shell环境中,局部变量将无法再起作用。
全局变量:在新的shell环境中可以继续使用。
通过内部命令export将局部变量为全局变量。
格式1:export 变量名
格式2:export 变量名=变量值
#可以使用pstree 查看shell的环境
#输入bash进入子shell
#ctrl+D组合exit 退出子shell
3.3 环境变量
环境变量由系统提前创建,用来设置用户的工作环境。
env #可以看到当前所有的环境变量
3.3.1 常用的环境变量
-
$USER 表示用户名称
-
$HOME 表示用户的家目录
-
$LANG 表示语言和字符集
-
$PWD 表示当前所在工作目录
-
$PATH 表示可执行用户程序的默认路径
3.3.2 环境变量的全局配置文件
#配置文件位置
/etc/profile
##修改此文件,全局生效,可用于长期变更或设置环境变量
3.4 只读变量
将变量声明为只读(read-only)后,不能再修改变量的值。
readonly 变量名 #将变量声明为只读变量
3.5 位置变量
$1, $2, $3, … $n 表示命令行参数的位置值
$1 表示第一个参数,$2 表示第二个参数,以此类推。
当n大于9时,需要加上{ },比如第十个位置,要用 ${10}表示
#以shell脚本为例
#!/bin/bash
echo "$1" #位置1
echo "$2" #位置2
echo "$3" #位置3
echo "${10}" #位置10
echo "$10" #位置1和0
#将{0..10} 作为一个参数传递给脚本
bash /test/t2.sh {0..10} #运行脚本
由此可见,$10并不表示第十个位置的值 , ${10}才是。
3.6 预定义变量(重要)
状态变量 | 功能 |
---|---|
$* | 表示所有位置参数的内容看成一个整体返回 |
$@ | 表示所有位置参数的内容分割成n份,每份作为一个独立的个体返回 返回所有 |
$? | 表示前一条命令执行后的返回状态,返回值为 0 表示执行正确,返回任何非 0值均表示执行出现异常 |
$# | 表示命令行中位置参数的总个数 |
$0 | 表示当前执行的脚本或程序的名称即程序本身 |
$$ | 当前进程id |
$! | 后台任务最后一个id |
3.7 整数运算
#运算符
+ 加法
- 减法
* 乘法
/ 除法
% 取余
#运算法则
加法:num1 + num2
减法:num1 - num2
乘法:num1 \ * num2
整除:num1 / num2
取余(求模):num1 % num2 (求 num1 除以 num2 的余数)
变量和运算符之间要用空格隔开
#expr只能进行整数的运算
#格式
expr 变量1 运算符 变量2 [运算符 变量3]
示例一:expr 加法运算
expr 1 + 2 #简单的加法运算
3 #运算结果
示例二:expr 乘法运算,乘法需要用\转译
expr 1 \* 2 #简单的乘法运算,乘法需要用\转译
2 #运算结果
示例三:expr取余运算
#方法一
expr 3 % 2
1
#方法二:定义变量,使用反撇号
yu=`expr 3 % 3` #定义变量
echo $yu
0
示例四: 随机取余
expr $RANDOM % 33
6
expr $[RANDOM % 10 + 1]
7
echo $[RANDOM % 10 + 1]
10
示例五:i++和++i
i=1;j=1;let j=i++;echo $i $j
2 1
i=1;j=1;let j=++i;echo $i $j
2 2
四、几个简单的Shell脚本
4.1 使用shell脚本查看系统信息
#脚本内容#
##文件名 sys.sh##
#!/bin/bash
ip=`ifconfig ens33 | grep -w inet | tr -s ''| awk '{print $2}'t`
totalmem=`free -h | grep Mem | awk '{print $2}'` hostname=`hostname`
disk=`lsblk -l | grep disk | awk '{print $1 $4}'`
cpu1=`lscpu |grep 型号名称`
cpu2=`lscpu |grep Core | awk '{print $4}'`
kernel=`uname -r`
echo "当前主机的IP地址: $ip "
echo "当前主机的总内存: $totalmem "
echo "当前主机的主机名: $hostname "
echo "当前主机所有磁盘及大小: $disk "
echo " $cpu1 "
echo "当前主机的CPU的核数: $cpu2 "
echo "当前主机的内核版本: $kernel "
. /test/sys.sh #执行shell脚本
#不在目录下,需要用绝对路径
#.=source 加权限执行
4.2 使用shell脚本搭建本地yum仓库
#脚本名称 lyum.sh
#脚本内容#
#!/bin/bash
mount /dev/sr0 /mnt
cd /etc/yum.repos.d
mkdir backup
mv *.repo backup
echo "
[local]
name=local
baseurl=file:///mnt
grpcheck=0
" > local.repo
. lyum.sh #执行脚本
yum install tree #安装tree命令来测试