目录
一、前言
1、程序编程风格
面向过程编程语言是一种以过程为中心的编程范式
- 在面向过程编程中,程序被划分为一系列的函数或过程,每个函数执行特定的任务
- 数据在函数之间传递,通过参数和返回值来进行交互
- 面向过程编程注重解决问题的步骤和过程,强调程序的顺序和流程控制
- 问题规模小,可以步骤化,按部就班处理
- 以指令为中心,数据服务于指令
- 常见的面向过程编程语言有C和shell
面向对象编程语言是一种以对象为中心的编程范式
- 在面向对象编程中,程序被组织成一系列的对象,每个对象都有自己的状态和行为
- 对象可以相互交互,通过消息传递来进行通信
- 面向对象编程注重抽象和封装,通过类和对象的概念来描述问题领域和解决方案
- 问题规模大,复杂系统
- 以数据为中心,指令服务于数据
- 常见的面向对象编程语言有Java、C++和Python
2、编程语言
- Python(Python):Python是一种高级、通用、解释型的编程语言。它具有简洁的语法和强大的功能,适用于多种应用场景,包括Web开发、数据分析、人工智能等
- Java(Java):Java是一种面向对象的编程语言,广泛用于企业级应用开发。它的特点是跨平台性和强大的生态系统,被广泛应用于服务器端开发、Android应用开发等领域
- JavaScript(JavaScript):JavaScript是一种用于网页前端开发的脚本语言。它可以为网页增加交互性和动态效果,现在也可以用于服务器端开发
- C++(C++):C++是一种通用的编程语言,继承了C语言的特点并添加了面向对象的功能。它被广泛应用于系统级开发、游戏开发和性能要求较高的应用程序开发
- Ruby(Ruby):Ruby是一种简洁、灵活的动态编程语言,注重开发人员的幸福感。它的语法简单易懂,适用于Web开发和快速原型开发
- Go(Go):Go是一种由Google开发的编程语言,注重简洁性和效率。它的特点是高并发性能和简单的语法,适用于网络编程和分布式系统开发
- Shell(shell):Shell是一种脚本语言,用于在操作系统的命令行界面上执行操作和自动化任务。它是一种解释性语言,常用于管理和操作Unix/Linux系统,但也可以在其他操作系统上使用
接下来将详细介绍shell脚本语言
3、编程的三种处理逻辑
- 顺序逻辑(Sequence Logic):顺序逻辑是指按照代码的编写顺序依次执行的逻辑。代码会从上到下依次执行,每一行代码都会在前一行代码执行完毕之后执行。这种逻辑适用于需要按照特定的顺序执行一系列操作的情况
- 选择逻辑(Selection Logic):选择逻辑是根据条件来确定执行哪段代码的逻辑。根据条件的真假,程序会选择执行不同的代码块。常见的选择逻辑结构包括
if
语句、switch
语句等 - 循环逻辑(Iteration Logic):循环逻辑是重复执行一段代码的逻辑。循环可以根据条件来决定是否继续执行代码块,直到条件不满足为止。常见的循环结构包括
for
循环和while
循环
二、shell脚本
1、shell脚本基础
1.1 什么是shell
1.1.1 shell的概念
Linux 系统中的 Shell 是一个特殊的应用程序,它介于操作系统内核与用户之间,充当 了一个“命令解释器”的角色,负责接收用户输入的操作指令(命令)并进行解释,将需要执 行的操作传递给内核执行,并输出执行结果。
常见的 Shell 解释器程序有很多种,使用不同的 Shell 时,其内部指令、命令行提示符等方面会存在一些区别。
通过/etc/shells 文件可以了解当前系统所支持的 Shell 脚本种类
[root@localhost ~]#cat /etc/shells #查看Linux系统中的shell类型及信息
1.1.2 linux中常见的shell类型及信息
- bash:Bash是Linux中最常用的shell,也是默认的shell。它是Bourne shell的扩展版本,提供了强大的命令行解释器和脚本编程功能
- csh:Csh是一种基于C语言语法的shell,它具有类似于C语言的语法结构和特性。Csh提供了一些独特的功能,如命令别名和历史记录扩展等
- tcsh:Tcsh是Csh的改进版本,提供了更多的特性和改进。它包括了对命令行编辑、命令别名、历史记录和作业控制等方面的增强
- sh:sh是一种功能较为简单的shell,已经被bash等替换
nologin:nologin
是一种特殊的shell,它用于禁止用户登录。当用户的登录shell设置为/usr/sbin/nologin
时,用户将无法通过登录界面或远程登录(如SSH)进行登录
1.1.3 shell脚本的功能
- 自动化任务:Shell脚本可以用于自动执行一系列的命令,从而实现自动化任务。例如,你可以编写一个Shell脚本来定期备份文件、清理临时文件或更新软件
- 系统管理:Shell脚本可以用于系统管理任务,如用户管理、文件管理和进程管理。你可以编写一个Shell脚本来创建用户、修改文件权限或监控系统资源使用情况
- 批量处理:如果你需要对大量文件或数据进行相同的操作,Shell脚本可以帮助你批量处理。例如,你可以编写一个Shell脚本来批量重命名文件、转换文件格式或提取特定信息
- 系统配置:Shell脚本可以用于系统配置任务,如安装软件、配置环境变量或修改配置文件。你可以编写一个Shell脚本来自动化系统配置过程,减少手动操作的时间和错误
- 监控和日志分析:Shell脚本可以用于监控系统状态和分析日志文件。你可以编写一个Shell脚本来定期检查系统的健康状态、监控网络连接或分析日志文件以查找特定的事件或错误
1.2 shell脚本及构成
-
shell脚本就是将命令按顺序一一列出,最后自动执行
-
执行需要权限,也可以直接使用路径
-
脚本其实不复杂,通用脚本环境改变后依然可以使用的脚本
shell脚本内容的基本构成:
①声明解释器:脚本的第一行通常是#!/bin/sh或#!/bin/bash,用于指定脚本使用的解释器。这告诉操作系统要使用哪个Shell来执行脚本
②注释:可以在脚本中添加注释,以便其他人理解脚本的目的和功能。注释以#开头,可以单行或多行
③执行语句:脚本可以调用系统命令、外部程序或其他脚本来执行特定的任务。命令可以直接在脚本中使用,也可以存储在变量中后再执行
示例:
①打开文本编辑器(可以使用 vi/vim 命令来创建文件),新建一个文件 text.sh,扩展名为 sh(sh代表shell)
② 输入一些简单的代码,格式一般为下图所示:第一行必须声明指定的shell脚本解释器,下面正常输入执行语句即可
1.3 shell脚本执行方式
方式一:指定路径(相对路径或绝对路径)去执行文件(需要有执行权限)
方式二:指定shell解释器去执行(不需要权限)
方式三:source和 . 执行
三种方式对当前bash环境的影响:
①编辑脚本来测试几种执行方式对进程的影响
②使用bash解释器执行脚本,查看当前进程的变化
③使用source或 . 执行脚本,查看当前进程的变化
注:
使用前两种方式(指定路径和指定shell解释器)执行脚本实际上是开启bash子进程去执行,不影响当前bash环境。
而使用方式三:source和 . 执行脚本是使用当前的bash去运行,会影响当前的bash环境,不推荐使用
1.4 脚本错误调试
1.4.1 命令错误
Shell脚本中某条命令执行失败导致整个脚本无法继续执行的情况。这种错误通常是由于执行的命令不存在、无法访问、或者命令的参数不正确等原因导致的
注:
当前命令出错无法执行,但不会影响接下来的命令继续执行
1.4.2 语法错误
当Shell脚本中存在语法错误时,Shell解释器无法理解脚本的含义,会提示语法错误信息
1.4.3 逻辑错误
当Shell脚本的逻辑不正确时,可能会导致脚本无法达到预期的结果。例如,脚本中的条件语句或循环可能会出现逻辑错误
1.4.4 检测脚本错误
bash -n 脚本名称 #检查语法错误、命令错误
bash -x 脚本名称 #检查逻辑错误、命令错误,实际上该命令是将脚本的所有语句执行一遍
set -e
是一种Shell脚本的选项,也称为"exit on error"模式。启用该选项后,当Shell脚本中任何一条命令执行失败时,整个脚本都会立即停止执行,即使后续命令可能不会导致错误。这种模式可以帮助及早发现错误,并防止错误导致更严重的问题
shell脚本内容前输入set -e即一旦出错立即停止
set -u
是一种Shell脚本的选项,也称为"uninitialized variables"模式。启用该选项后,如果Shell脚本中使用了未定义的变量,会立即停止执行并显示错误信息。这种模式可以帮助及早发现变量使用错误,并防止错误导致更严重的问题
shell脚本内容前输入set -u ,即内容中的变量不存在不让执行
2、重定向与管道符
2.1 重定向
重定向是一种Shell命令的操作,用于将命令的输入输出从标准位置(通常是终端或控制台)转移到其他位置。在Shell脚本中,可以使用重定向来控制命令的输入、输出和错误输出的位置,以便更好地管理和处理命令的执行结果
类型 | 设备文件 | 文件描述编号 | 默认设备 |
---|---|---|---|
标准输入 | /dev/stdin | 0 | 键盘 |
标准输出 | /dev/stdout | 1 | 显示器 |
标准错误输出 | /dev/stderr | 2 | 显示器 |
交互式硬件设备
-
标准输入:从该设备接收用户输入的数据
-
标准输出:通过该设备向用户输出数据
-
标准错误:通过该设备报告执行出错信息
类型 | 操作符 | 用途 |
---|---|---|
重定向输入 | < | 从指定的文件读取数据,而不是从键盘输入 |
重定向输出 | 1> | 将输出结果保存到指定的文件(覆盖原有内容) |
>> | 将输出结果追加到指定的文件尾部 | |
标准错误输出 | 2> | 将错误信息保存到指定的文件(覆盖原有内容) |
2>> | 标准错误输出结果追加到指定的文件尾部 | |
混合输出 | &>无论对错都可以重定向 | 将标准输出、标准错误的内容保存到同一个文件中 |
拓展:
以下哪个选项不能把成功和错误一起显示到/data/all.log文件中
A ls /data /xxx 1> /data/all.log 2>&1
B ls /data /xxx 2> /data/all.log 1>&2
C ls /data /xxx &> /data/all.log
D ls /data /xxx >& /data/all.logE ls /data /xxx 2>&1 1> /data/all.log
答:E选项不能把成功和错误一起显示到/data/all.log文件中
2.2 多行重定向
多行重定向是指将多行文本输出到文件或命令的操作
在Shell脚本中,可以使用重定向符号<<
来实现多行重定向
2.3 /dev/null 文件
/dev/null
文件,它是一个特殊的设备文件,用于丢弃输入或将输出重定向到空设备。在Linux系统中,一切皆文件,/dev/null
被认为是一个黑洞,任何写入它的内容都会被丢弃,任何从它读取的操作都会立即返回文件结尾
将输出重定向到/dev/null
可以实现静默操作,不显示任何输出
$ command > /dev/null
如:
echo "grep "root" /etc/passwd" &> /dev/null
#执行grep "root" /etc/passwd命令,但不会在终端上显示输出结果。这通常被用来检查某个命令是否产生了期望的结果,而不关心具体的输出内容
2.4 管道符
- 管道符
|
是一种Shell命令操作符,用于将一个命令的输出作为另一个命令的输入。在Shell脚本中,管道符可以用于将多个命令组合起来,以便更好地处理和管理命令的执行结果 - 管道符可以将多个命令组合起来,形成一个命令链,以便更好地处理和管理命令的执行结果
- 需要注意的是,管道符左边的命令一定支持标准输出,右边的命令一定要接受标准输入
如:
echo "321" | passwd --stdin dh #通过管道符,免交互修改dh用户的密码
ifconfig ens33 | grep netmask | tr -s " " | cut -d " " -f3 #通过管道符,得到本机的IP地址
3、自定义变量
3.1 命名的要求
- 变量名只能包含字母(a-z或A-Z)、数字(0-9)和下划线(_)
- 变量名不能以数字开头
- 变量名区分大小写,例如
myVariable
和myvariable
是不同的变量 - 避免使用shell保留关键字作为变量名,例如
if
、for
、while
等 - 变量名最好具有描述性,以便于理解和维护代码
- 建议使用小写字母来命名变量,以避免与环境变量混淆
- 使用下划线来分隔多个单词,例如
my_variable
定义变量: name='value' 变量名=变量值
引用变量: $name 或 ${name}
调用变量: echo $name 或 echo ${name}
取消变量: unset name
双引号" " 如 "$name" 弱引用,其中的变量引用会被替换为变量值
单引号' ' 如 '$name' 强引用,其中的变量引用不会被替换为变量值,而保持原字符串
反撇号 ` ` 或 $( ) 调用命令执行的结果
大括号{ } 定义变量名的范围
3.2 变量追加值
变量追加值:是指将新的值添加到已存在的变量值的末尾。这通常用于连接字符串或在数组中添加元素
变量名+=追加的内容
3.3 read -p
read -p
是一个用于读取用户输入的命令。它通常与echo
一起使用,以提示用户提供输入
read -p
命令会显示一个提示消息,并等待用户输入。一旦用户输入完成并按下回车键,输入的值将被存储到指定的变量中
案例一:
案例二:
4、变量作用范围
默认情况下,新定义的变量只在当前的shell环境中有效,因此称为局部变量,当进入子程序或新的shell环境中,局部变量将无法再起作用
可以通过内部命令export将指定的变量为全局变量,使用户定义的变量在所子shell环境中可以继续使用
格式1:export 变量名 声明已定义过的变量为全局变量
格式2:export 变量名=变量值 在定义变量时声明指定的变量为全局变量
5、整数的运算
5.1 expr命令
expr
是一个用于数学计算和字符串操作的命令行工具,常用于Shell脚本中
expr只能进行整数的运算
expr 变量1 运算符 变量2 [运算符 变量3]……
算术运算符 | 说明 | 举例 |
---|---|---|
+ | 加法 | `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 |
5.2 其他运算方法
方式一:
let 变量名=算术表达式
方式二:
((变量名 = 算术表达式))
方式三:
变量名=$[算术表达式]
5.3 随机数生成器变量
$RANDOM
是一个特殊的环境变量,用于生成一个随机整数
每次访问$RANDOM
时,它会返回一个0到32767(2^15-1)之间的随机整数。这个值是通过使用伪随机数生成器来生成的,其种子是由系统时间设置的,因此每次脚本执行时,$RANDOM
的值都会不同
拓展:
echo -e "\E[1;31mhello\E[0m" #指定颜色
echo -e "\E[1;$[RANDOM%7+31]mhello\E[0m" #随机颜色
6、环境变量
6.1 环境变量的概念
环境变量是一种特殊类型的变量,用于存储系统和用户级别的配置信息。这些变量对于操作系统和应用程序的正常运行非常重要
注:
- 可以使子进程(包括孙子进程)继承父进程的变量,但是无法让父进程使用子进程的变量
- 一旦子进程修改从父进程继承的变量,将会新的值传递给孙子进程
- 一般只在系统配置文件中使用,在脚本中较少使用
环境变量具有以下特点:
- 全局访问:环境变量在整个系统范围内可见和访问,可以由所有正在运行的进程使用
- 持久性:环境变量在系统启动时被设置,并且在系统关闭之前一直存在。它们通常通过配置文件或系统脚本进行设置,以确保在每次会话中都可用
- 动态性:环境变量的值可以根据需要进行更改,而无需重新编译代码或重新启动系统
- 用途广泛:环境变量可用于各种目的,如定义系统路径、设置语言环境、指定默认编辑器等
[root@localhost ~]#env #查看系统所有的环境变量
常用的环境变量 | 说明 |
---|---|
$USER | 表示当前登录用户的用户名 |
$HOME | 指定当前用户的主目录路径 |
$LANG | 设置默认的语言环境 |
$PWD | 表示当前所在工作目录 |
$PATH | 定义了系统查找可执行文件的路径 |
SHELL | 指定当前用户所使用的shell程序 |
6.2 环境变量的配置文件
/etc/profile 或 ~/.bash_profile 可用来长期变更或设置环境变量
/etc/profile #如果修改此文件会作用于所有用户
~/.bash_profile #用户独立的配置文件,修改这个文件只作用于当前用户
7、只读变量
只读变量是一种特殊类型的变量,其值不能被修改或重写。一旦将变量声明为只读,就无法再对其进行赋值操作
使用只读变量有以下几个优点:
- 防止意外修改:通过将关键变量声明为只读,可以防止在脚本或程序中意外地修改其值,确保数据的完整性和一致性
- 安全性增强:只读变量可用于存储敏感信息,如密码或密钥,以防止被恶意修改
- 可读性提高:将常量或配置参数定义为只读变量,可以提高代码的可读性和维护性
可使用readonly
命令来将变量声明为只读
readonly 变量名 #将该变量声明为只读
注:使用unset 变量名 也无法取消只读,必须通过reboot重启后才能修改变量
8、位置变量
位置变量(Positional Variables)是一组特定的变量,用于存储命令行参数(Command Line Arguments)。当我们在命令行上运行一个脚本或执行一个程序时,可以通过位置变量来访问传递给该脚本或程序的参数
在Bash脚本中,位置变量被表示为$1
、$2
、$3
等。其中,$1
表示第一个参数,$2
表示第二个参数,以此类推。 $0
表示当前脚本的名称
9、预定义(状态)变量
存在一些预定义变量(也称为状态变量),它们提供了有关系统和正在发生的操作的信息。这些变量不需要事先声明,而是由操作系统自动提供
预定义变量 | 说明 |
---|---|
$* | 表示所有位置参数的内容看成一个整体返回,即返回所有 |
$@ | 表示所有位置参数的内容分割成n份,每份作为一个独立的个体返回,即返回所有 |
$? | 表示前一条命令执行后的返回状态,返回值为 0 表示执行正确,返回任何非 0 值均表示执行出现异常 |
$# | 表示命令行中位置参数的总个数 |
$0 | 表示当前执行的脚本或程序的名称 当前脚本的名字 |
$$ | 当前bash的进程id |
$! | 后台任务最后一个id |
注:
当使用“$0”预定义变量时,如果执行的是软链接文件,则输出的是当前执行的软链接文件名
三、编写简单的shell脚本
1、提取系统信息
#!/bin/bash
name=`hostname`
ip=`ifconfig ens33 | grep netmask | tr -s " " | cut -d " " -f3`
cpu=`lscpu | grep 型号名称 | tr -s " " | cut -d" " -f2-8`
kernel=`uname -r`
os=`cat /etc/redhat-release`
disk=`lsblk | grep disk | awk '{print $4}'`
mem=`free -h | grep Mem | awk '{print $2}'`
echo -e "\E[1;35m----------------system info--------------------\E[0m"
echo "主机名: $name"
echo "IP地址: $ip"
echo "CPU型号: $cpu"
echo "内核版本:$kernel"
echo "系统类型:$os"
echo "磁盘大小:$disk"
echo "内存大小:$mem"
echo -e "\E[1;35m---------------- end --------------------\E[0m"
2、 查看内存资源是否充足
#!/bin/bash
FreeCC=$(free -m | grep "Mem: " |tr -s " "|cut -d " " -f7)
[ $FreeCC -lt 1200 ] && echo "${FreeCC}MB"
mem_size=$(free -m | grep "Mem: " |tr -s " "|cut -d " " -f4)
[ $mem_size -ge 10000 ] && echo "由于服务器系统内存资源不足,请尽快处理故障!"