linux运维之shell编程

ops/2024/12/27 6:50:44/

Shell 编程在系统运维中及其重要

1. Shell 编程概述

Shell 是一种命令行解释器,能够执行操作系统的命令。Shell 脚本是一个包含一系列 Shell 命令的文件,它可以被执行,以自动化和批量处理任务。常用的 Shell 类型包括 bash、sh、zsh 等。Shell 编程本质上是利用这些命令和控制结构(如条件判断、循环等)来创建自动化任务。

2. 自动化系统管理任务

运维工程师的工作常常包括重复性高的任务,Shell 编程可以将这些任务自动化,减少手动操作,提高效率和减少错误。

常见的自动化任务包括:

  • 备份:自动定期备份文件、数据库、配置文件等。
  • 日志轮转和清理:定期清理过期的日志文件,防止占满磁盘空间。
  • 安全检查:定期扫描系统中的潜在安全风险(如非法登录、弱密码等)。
  • 监控系统状态:定期检查系统的 CPU、内存、磁盘空间等状态,并在出现异常时发送警报。

示例:自动化备份脚本

#!/bin/bash
# 自动备份脚本
BACKUP_DIR="/data"
DEST_DIR="/backup"
DATE=$(date +%Y%m%d%H%M)
TAR_FILE="${DEST_DIR}/backup_${DATE}.tar.gz"

# 创建备份
tar -czf $TAR_FILE $BACKUP_DIR

# 输出备份日志
echo "Backup completed: $TAR_FILE"

这个脚本会自动备份指定的 /data 目录,并将备份文件保存到 /backup 目录下,文件名包含当前日期时间,便于管理。

3. 批量操作与配置管理

在大型系统中,可能有大量的服务器需要统一配置、更新、安装软件等。使用 Shell 脚本可以在多个服务器上批量执行命令,从而避免逐台操作。

示例:批量安装软件

#!/bin/bash
# 批量安装软件包
SERVERS=("server1" "server2" "server3")
PACKAGE="nginx"

for SERVER in "${SERVERS[@]}"
do
  echo "Installing $PACKAGE on $SERVER..."
  ssh $SERVER "sudo apt-get install -y $PACKAGE"
done

该脚本通过 SSH 远程连接到多个服务器,批量安装指定的软件包。

4. 系统健康监控与报警

Shell 编程非常适合于实现基础的系统监控和报警机制。例如,运维人员可以编写脚本定期检查系统的磁盘使用情况、内存状态等,并在发现异常时触发邮件或短信报警。

示例:磁盘空间监控脚本

#!/bin/bash
# 磁盘空间监控
THRESHOLD=90
DISK_USAGE=$(df / | grep / | awk '{ print $5 }' | sed 's/%//g')

if [ $DISK_USAGE -gt $THRESHOLD ]; then
  echo "Warning: Disk usage is over ${THRESHOLD}%!" | mail -s "Disk Space Alert" admin@example.com
fi

这个脚本会定期检查根目录(/)的磁盘使用情况,如果超过设定的阈值(如 90%),则通过邮件提醒管理员。

5. 定时任务与调度

在运维工作中,定时任务非常常见,Shell 脚本与 Linux 的定时任务工具 cron 配合使用,可以自动定期执行脚本。

示例:使用 cron 定时执行备份脚本

假设你已经写好了一个备份脚本 /home/admin/backup.sh,并希望它每天凌晨 1 点执行一次。可以通过以下步骤设置 cron 任务:

crontab -e

在 crontab 文件中添加以下内容:

0 1 * * * /bin/bash /home/admin/backup.sh

这行表示每天凌晨 1 点运行 /home/admin/backup.sh 脚本。

6. 日志分析与处理

运维工程师经常需要分析大量的日志文件(如 Apache/Nginx 日志、系统日志、应用程序日志等),Shell 脚本提供了强大的文本处理能力,能够提取关键信息并生成报告或发送警报。

示例:分析 Apache 日志中的错误
# 检查 Apache 错误日志
LOG_FILE="/var/log/apache2/error.log"
ERROR_LOG="/var/log/apache2/error_report.txt"

# 查找错误日志中包含 "error" 的行,并输出到报告文件
grep "error" $LOG_FILE > $ERROR_LOG

# 发送报告邮件
mail -s "Apache Error Log Report" admin@example.com < $ERROR_LOG

这个脚本会分析 Apache 错误日志,提取包含“error”关键字的行,并将结果保存到报告文件中,再将报告通过邮件发送给管理员。

7. 故障排除与修复

Shell 脚本在故障排除中同样发挥重要作用。在系统出现故障时,运维工程师可以编写脚本自动检测系统状态、排除常见问题,甚至在某些情况下直接执行修复操作。

示例:检查并重启 Apache 服务
# 检查 Apache 服务状态,如果未运行,则重启
SERVICE="apache2"
STATUS=$(systemctl is-active $SERVICE)

if [ "$STATUS" != "active" ]; then
  echo "$SERVICE is down. Restarting..."
  systemctl restart $SERVICE
  echo "$SERVICE has been restarted." | mail -s "$SERVICE restart notification" admin@example.com
else
  echo "$SERVICE is running normally."
fi

这个脚本会检查 Apache 服务是否处于运行状态,如果没有运行则尝试重启,并通过邮件通知管理员。

8. 安全运维

运维工程师需要确保系统的安全,Shell 脚本可以用于检测和修复系统中的安全问题。例如,检查不安全的用户配置、密码策略、权限问题等。

示例:检查弱密码用户

#!/bin/bash
# 检查系统中是否存在弱密码用户(如空密码)
for user in $(cut -d: -f1 /etc/passwd); do
  PASSWORD=$(sudo grep "^$user" /etc/shadow | cut -d: -f2)
  if [ -z "$PASSWORD" ]; then
    echo "User $user has no password set!" | mail -s "Weak password detected" admin@example.com
  fi
done

这个脚本会检查系统中所有用户的密码,发现空密码用户时会发送警报。

总结:Shell 编程在系统运维中的核心作用

Shell 编程对系统运维工程师来说是一项非常重要的技能,它能够帮助你:

  • 自动化重复性工作,提高工作效率。
  • 处理和分析系统日志,快速识别问题。
  • 批量管理和配置服务器,节省时间并减少人为错误。
  • 定期监控系统健康状态,及时发现潜在问题。
  • 故障排除与修复,自动化恢复系统服务。
  • 增强系统安全性,通过脚本自动化检查和修复安全漏洞。

一,变量

变量是存储数据的容器,用于在脚本中传递信息、操作数据等。根据其作用范围和使用场景,Shell 中的变量可以分为 两种主要类型

1. 环境变量(Environment Variables)

环境变量是影响系统或程序行为的全局变量。它们通常用于存储操作系统、应用程序、或者 Shell 的配置信息。环境变量不仅在当前 Shell 中有效,而且在启动该 Shell 的所有子进程中都有效。

环境变量的特点:

  • 环境变量是全局有效的。
  • 通常由操作系统或程序自动设置,用户也可以自定义。
  • 它们通常用于配置系统或用户的行为,如 $PATH、$HOME、$USER 等。

常见的环境变量:

  • $HOME:当前用户的家目录路径。
  • $USER:当前用户的用户名。
  • $PATH:系统查找可执行文件的路径列表。
  • $SHELL:当前 Shell 的路径,例如 /bin/bash。

设置和查看环境变量:

  • 设置环境变量
    export VAR_NAME="value"
    例如,设置环境变量 MY_VAR:
    export MY_VAR="Hello, World!"
  • 查看环境变量
    echo $MY_VAR
  • 查看所有环境变量
    printenv

环境变量的作用:

环境变量对系统或应用程序的行为至关重要。例如,$PATH 变量决定了 Shell 如何查找可执行文件,当你在命令行输入一个命令时,系统会按照 $PATH 中的目录顺序查找该命令对应的文件。

2. 局部变量(Local Variables)

局部变量是仅在当前 Shell 或脚本的作用域内有效的变量。它们的生命周期仅限于脚本执行期间,脚本执行结束后,这些变量会被销毁。局部变量通常用于存储脚本中的临时数据或计算结果。

局部变量的特点:

  • 局部变量只能在当前 Shell 会话或者脚本中访问。
  • 它们不会影响到其他 Shell 进程或脚本的执行。
  • 局部变量不需要使用 export 来设置。

设置局部变量:

  • 设置局部变量
    VAR_NAME="value"
    例如,设置局部变量 MY_VAR:
    MY_VAR="Hello, World!"
  • 查看局部变量
    echo $MY_VAR

局部变量的作用:

局部变量通常用于保存临时数据、脚本参数、计算结果等。例如,在一个脚本中,你可能需要将某些计算结果存储在变量中,并在脚本结束后释放这些变量。

局部变量与环境变量的区别

特点

环境变量

局部变量

作用范围

全局有效,影响子进程。

仅在当前 Shell 或脚本中有效。

设置方式

使用 export 命令导出,例如 export VAR=value。

直接设置变量名和值,例如 VAR=value。

常见用途

配置系统、应用程序或 Shell 行为。

存储脚本中的临时数据或计算结果。

生命周期

直到 Shell 会话结束,或者被显式修改或删除。

仅在当前脚本或命令会话中有效,执行结束后失效。

影响范围

可以影响所有子进程及 Shell 会话。

只在当前 Shell 会话或脚本内部有效。

实例说明:

1. 环境变量示例

#!/bin/bash
# 设置环境变量
export MY_PATH="/usr/local/bin"

# 查看环境变量
echo "The PATH is: $MY_PATH"

这个脚本中,MY_PATH 是一个环境变量,export 使得它在当前 Shell 会话和任何子进程中都有效。

2. 局部变量示例

#!/bin/bash
# 设置局部变量
MY_VAR="Hello, Shell!"

# 查看局部变量
echo "Message: $MY_VAR"

在这个脚本中,MY_VAR 是一个局部变量,只有在当前脚本运行时有效,脚本执行结束后它就会消失。

3. 环境变量与局部变量的混合使用

#!/bin/bash
# 设置环境变量
export HOME_DIR="/home/user"

# 设置局部变量
FILE_PATH="$HOME_DIR/data/file.txt"

echo "Home Directory: $HOME_DIR"
echo "File Path: $FILE_PATH"

这个脚本中,HOME_DIR 是环境变量,可以在其他 Shell 会话或脚本中使用。而 FILE_PATH 是局部变量,仅在当前脚本中有效。

总结

  • 环境变量:全局有效,影响当前 Shell 会话及其子进程,通常用于系统配置和用户信息。
  • 局部变量:仅在当前 Shell 会话或脚本中有效,适用于存储脚本中的临时数据。

二,变量应用实例

1,将系统时间输入到变量

2,将/etc/passwd文件进行备份,存储在/tmp下并且以当前时间作为后缀名

cp /etc/passwd /tmp/passwd_$(date +%F_%R)

ls /tmp/

案例一,利用脚本创建文件和文件夹

1,编写脚本 vim file.sh

#!/bin/bash

#touch mkdir

touch 1.txt

mkdir /root/test1

ls /root

2,给脚本赋予执行权限,然后执行

file.sh文件属主读写执行权限,属组执行权限,其他人读执行权限

案例二,编写shell脚本用于创建user1用户,并且设置密码123456

1,编写脚本 vim user.sh

#!/bin/bash

useradd user1 

echo "user1:123456" | chpasswd

#echo 123456 | passwd --stdin user1 &> /dev/null

echo "用户 user1 创建成功,密码已设置为 123456"

2,给执行权限再执行

3,验证实验效果

三,引用与转义

单引号(引用)

单引号用于将字符串中的所有字符都作为普通字符处理,不会解析其中的特殊字符。例如:

array=10
echo '$array' 
# 输出: $array

在上面的例子中,$array 被单引号括起来,因此 $ 符号不会被解释为变量的前缀,而是作为普通的字符输出

双引号(弱引用)

双引号允许字符串中的大多数字符被解释为普通字符,但会解析一些特殊字符,如 $、反引号和转义符。例如:

array=10
echo "$array" 
# 输出: 10

在这个例子中,双引号内的 $array 被解析为变量 array 的值,即 10

转义

转义是指使用转义符(通常是反斜杠 \)来改变紧随其后的字符的含义。在Shell中,转义符可以使特殊字符失去其特殊含义,而仅作为普通字符处理。例如:

echo \$Dollar  # 输出: $Dollar

在这个例子中,$ 符号前面有一个反斜杠 \,因此 $ 符号被当作普通字符输出,而不是被解释为变量的前缀

四,shell脚本实现四则运算

1,编写脚本 vim  calc.sh

#!/bin/bash

#test1

read -p "please input two numbers:" x y

echo $x + $y = $(expr $x + $y)

echo $x - $y = $(expr $x - $y)

echo $x \* $y = $(expr $x \* $y)

echo $x / $y = $(expr $x / $y)

2,给权限执行 chmod u+x calc.sh

五,无执行权限脚本执行

使用bash执行脚本(使用bash -x 显示脚本执行过程)

bash 1.sh

使用source执行脚本

source 1.sh

六,条件测试概述

在Shell编程中,条件测试用于判断某个条件是否为真。条件测试的结果通常用于控制程序的流程,例如决定是否执行某个命令或代码块。Shell提供了多种条件测试方式,包括文件测试、字符串比较、数值比较等。

文件测试

文件测试用于检查文件或目录的属性。常用的文件测试操作符包括:

  • -e FILE:检查文件是否存在。
  • -f FILE:检查文件是否存在且为普通文件。
  • -d DIR:检查目录是否存在。
  • -r FILE:检查文件是否可读。
  • -w FILE:检查文件是否可写。
  • -x FILE:检查文件是否可执行。
  • -s FILE:检查文件是否存在且大小大于0。

示例:

if [ -e "#测试文件的正确路径" ]; then
    echo "File exists."
else
    echo "File does not exist."
fi

数值比较

数值比较用于比较两个数值的大小。常用的数值比较操作符包括:

  • -eq:检查两个数值是否相等。
  • -ne:检查两个数值是否不相等。
  • -lt:检查第一个数值是否小于第二个数值。
  • -le:检查第一个数值是否小于或等于第二个数值。
  • -gt:检查第一个数值是否大于第二个数值。
  • -ge:检查第一个数值是否大于或等于第二个数值。

示例:

read -p "Please enter your num1: " num1

read -p "Please enter your num2: " num2
if [ "$num1" -lt "$num2" ]; then
    echo "num1 is less than num2."
else
    echo "num1 is not less than num2."
fi

代码示例

以下是一个简单的Shell脚本示例,展示了如何根据分数判断ABCD四个等级:

#!/bin/bash
# 获取用户输入的分数
read -p "请输入分数: " score
 

# 根据分数判断等级
if (( score >= 90 )); then
    echo "等级: A"
elif (( score >= 80 )); then
    echo "等级: B"
elif (( score >= 70 )); then
    echo "等级: C"
elif (( score >= 60 )); then
    echo "等级: D"
else
    echo "等级: F"
fi

解释

  1. 获取用户输入:使用read命令获取用户输入的分数。
  2. 条件判断
    • 如果分数大于等于90,输出“等级: A”。
    • 如果分数大于等于80且小于90,输出“等级: B”。
    • 如果分数大于等于70且小于80,输出“等级: C”。
    • 如果分数大于等于60且小于70,输出“等级: D”。
    • 如果分数小于60,输出“等级: F”。
  3. 输出结果:根据条件判断的结果,输出对应的等级。

实例练习

单分支:

1、编写一个 Shell 脚本,如果系统中安装了 httpd 软件,则输出 “httpd 已安装”。

#!/bin/bash

# 检查 httpd 是否安装

if command -v httpd &> /dev/null; then

    echo "httpd 已安装"

else

    echo "httpd 未安装"

fi

2、编写一个 Shell 脚本,判断当前系统时间是否在 9 点到 18 点之间,如果在则输出 “当前处于工作时间”。

#!/bin/bash

# 获取当前小时

current_hour=$(date +"%H")

# 判断当前时间是否在 9 点到 18 点之间

if [ "$current_hour" -ge 9 ] && [ "$current_hour" -lt 18 ]; then

    echo "当前处于工作时间"

else

    echo "当前不处于工作时间"

fi

双分支

1、编写一个 Shell 脚本,提示用户输入一个数字,然后判断该数字是正数还是负数,并分别输出相应的结果。

#!/bin/bash

# 提示用户输入一个数字

echo "请输入一个数字:"

read number

# 判断数字是正数还是负数

if [ $number -gt 0 ]; then

    echo "该数字是正数"

elif [ $number -lt 0 ]; then

    echo "该数字是负数"

else

    echo "该数字是零"

fi

2,编写一个 Shell 脚本,接受一个文件路径作为参数,判断该文件是否具有可执行权限,如果有则输出 “该文件具有可执行权限”,否则输出 “该文件没有可执行权限”。

#!/bin/bash

# 检查参数数量

if [ "$#" -ne 1 ]; then

    echo "使用方法: $0 <文件路径>"

    exit 1

fi

# 获取文件路径

FILE_PATH=$1

# 检查文件是否存在

if [ ! -e "$FILE_PATH" ]; then

    echo "错误: 文件 $FILE_PATH 不存在"

    exit 1

fi

# 检查文件是否具有可执行权限

if [ -x "$FILE_PATH" ]; then

    echo "该文件具有可执行权限"

else

    echo "该文件没有可执行权限"

fi

3、编写一个 Shell 脚本,接受两个整数作为参数,判断第一个数是否大于第二个数,如果是则输出 “第一个数大于第二个数”,否则输出 “第一个数小于等于第二个数”。

#!/bin/bash

# 检查参数数量是否正确

if [ "$#" -ne 2 ]; then

    echo "用法: $0 <整数1> <整数2>"

    exit 1

fi

# 获取两个参数

num1=$1

num2=$2

# 判断第一个数是否大于第二个数

if [ "$num1" -gt "$num2" ]; then

    echo "第一个数大于第二个数"

else

    echo "第一个数小于等于第二个数"

fi

多分支

1、编写一个 Shell 脚本,接受一个月份数字作为参数,根据月份判断所属季节并输出(3、4、5 月为春季,6、7、8 月为夏季,9、10、11 月为秋季,12、1、2 月为冬季)。

#!/bin/bash

# 检查参数数量

if [ "$#" -ne 1 ]; then

    echo "Usage: $0 <month_number>"

    exit 1

fi

# 获取月份参数

month=$1

# 根据月份判断季节

case $month in

    3|4|5)

        echo "春季"

        ;;

    6|7|8)

        echo "夏季"

        ;;

    9|10|11)

        echo "秋季"

        ;;

    12|1|2)

        echo "冬季"

        ;;

    *)

        echo "无效的月份数字"

        exit 1

        ;;

esac


http://www.ppmy.cn/ops/139345.html

相关文章

【已解决】如何在vscode对项目路径以外的文件打断点

问题描述 项目需要对环境安装的包中的源码进行debug&#xff0c;但是发现打上的断点是灰色的 解决方案 在launch.json文件中加一行 "justMyCode": false // 允许调试外部代码文件

win32 解析、显示webp图片,及位图透明

win32 解析、显示webp图片&#xff0c;及位图透明 CImage img;#include <webp/decode.h> #include <fstream> #include <wingdi.h>void parse(CDC* dc) {std::ifstream ifs("None-1.webp", std::ios::binary);ifs.seekg(0, std::ios::end);auto s…

自然语言处理期末试题汇总

建议自己做&#xff0c;写完再来对答案。答案可能存在极小部分错误&#xff0c;不保证一定正确。 一、选择题 1-10、C A D B D B C D A A 11-20、A A A C A B D B B A 21-30、B C C D D A C A C B 31-40、B B B C D A B B A A 41-50、B D B C A B B B B C 51-60、A D D …

蓝桥杯准备训练(lesson1,c++方向)

前言 报名参加了蓝桥杯&#xff08;c&#xff09;方向的宝子们&#xff0c;今天我将与大家一起努力参赛&#xff0c;后序会与大家分享我的学习情况&#xff0c;我将从最基础的内容开始学习&#xff0c;带大家打好基础&#xff0c;在每节课后都会有练习题&#xff0c;刚开始的练…

composer简单入门

1、composer是什么 php包依赖管理工具 包&#xff1a;组件&#xff0c;一组相关的类&#xff0c;接口&#xff0c;trait的结合体 依赖&#xff1a;A->B->C->D composer就是用php语言开发的 下载地址&#xff1a;中文网 www.phpcomposer.com 2、组件放在哪里 查询平…

提升分布式系统响应速度:分布式系统远程调用性能提升之道

目录 一、远程调用直接案例分析 二、并行调用 &#xff08;一&#xff09;核心思想 &#xff08;二&#xff09;并行调用的实现方式 1. 基本思路 2. 代码示例 3. 关键点说明 4.线程池配置建议 三、数据异构 &#xff08;一&#xff09;场景重提 &#xff08;二&…

替代FTP最佳跨网文件传输解决方案——FileLink

在传统的企业文件传输中&#xff0c;FTP&#xff08;文件传输协议&#xff09;曾因其便捷性和高效性被广泛应用。然而&#xff0c;其固有的安全漏洞、对大文件传输支持的局限性、易受网络攻击等问题&#xff0c;已逐渐暴露出FTP在现代企业环境下的不足。针对这一问题&#xff0…

Kafka AdminClient API 来获取特定 Kafka 消费组的消费延迟

文章目录 代码流程详解1. Kafka 配置与创建 AdminClient2. 获取 Topic 的所有分区3. 获取消费者组的偏移量4. 获取每个分区的 log-end-offset5. 获取消费者组成员信息6. 计算 Lag 并输出信息7. 关闭 AdminClient8. 完整代码 代码功能总结&#xff1a; 这段代码的目标是通过 Kaf…