每个工程师都应知道的 10 个 Bash 脚本结构【转】

news/2025/1/7 19:58:52/文章来源:https://www.cnblogs.com/paul8339/p/18655692

每个工程师都应知道的 10 个 Bash 脚本结构

工程师掌握 Bash:10 个结构统治一切

Bash 脚本是工程师的超能力。无论是自动化重复任务、连接工具还是管理系统,Bash 总是简单而强大。

但就像任何力量一样,它需要掌握。让我通过一个可能的场景,带您了解 10 个关键的 Bash 结构。

场景

您需要分析来自多个文件的服务器日志,提取失败的登录尝试,并生成报告。这是一个常规问题,但通过 Bash,我们将使其优雅且可重用。

1. 用脚本设置舞台

我们通过编写脚本框架开始我们的旅程:

#!/bin/bash

set -e # 遇到错误时退出
trap 'echo "错误在第 $LINENO 行"; exit 1' ERR

为什么?:

  • set -e 确保脚本在遇到第一个问题时停止。
  • trap 捕获错误,为我们提供有用的调试信息。

2. 使用函数模块化

好的脚本是模块化的。让我们定义一个函数来解析日志文件:

parse_logs() {

local file="$1"
local output="$2"

whileread -r line; do
    if [[ "$line" == *"FAILED LOGIN"* ]]; then
        echo"$line" >> "$output"
    fi

done < "$file"
}

为什么?:

  • 函数使脚本可重用且易于维护。
  • local变量防止意外覆盖。

3. 数组:管理多个日志

我们需要处理来自多个服务器的日志:

log_files=("server1.log" "server2.log" "server3.log")
results=()

for file in "${log_files[@]}"; do
    output="${file%.log}_failed.log"
    parse_logs "$file" "$output"
    results+=("$output")
done

为什么?:

  • 数组帮助高效管理项目列表。
  • 我们将处理后的结果附加到数组中以供后续步骤使用。

4. 命令替换:添加时间戳

让我们使用date 为输出文件添加时间戳:

timestamp=$(date "+%Y-%m-%d")
final_report="failed_logins_$timestamp.txt"

为什么?:

  • 命令替换无缝地将动态值集成到脚本中。

5. 字符串操作

在合并日志之前,我们清理输出文件名:

for file in "${results[@]}"; do
    sanitized_name="${file// /_}"  # 将空格替换为下划线
    mv "$file" "$sanitized_name"
done

为什么?:

  • Bash 的参数扩展简化了字符串转换,无需外部工具。

6. 进程替换:合并文件

高效合并日志:

cat "${results[@]}" > "$final_report"

为什么?:

  • 进程替换和数组扩展使处理多个文件简洁高效。

7. 条件逻辑:定制报告

根据内容定制最终报告:

if [[ -s "$final_report" ]]; then
    echo "报告已生成: $final_report"
else
    echo "未找到失败的登录。"
    rm "$final_report"
fi

为什么?:

  • if 确保操作依赖于上下文,例如报告是否为空。

8. 案例语句:默认端口

假设我们需要根据服务器类型识别默认的 SSH 和 HTTPS 端口:

get_port() {
    local server="$1"
    case "$server" in
        "prod"*) echo 22 ;;
        "staging"*) echo 2222 ;;
        *) echo 80 ;;
    esac
}

为什么?:

  • case 优雅地处理多个特定模式。

9. 使用set -x 调试

在部署脚本之前,让我们调试它:

set -x # 启用调试
# 在此运行主脚本
set +x # 禁用调试

为什么?:

  • 调试工具如set -x 使跟踪和修复错误变得容易。

10. 文件描述符用于高级 I/O

假设我们从特殊输入流读取和处理日志:

exec 3<"$final_report"

while read -u3 line; do
    echo "已处理: $line"
done

exec 3<&-

为什么?:

  • 文件描述符提供对输入输出的精确控制,支持并行处理。

最终脚本

以下是打磨后的脚本可能的样子:

#!/bin/bash

set -e
trap'echo "错误在第 $LINENO 行"; exit 1' ERR
parse_logs() {
    local file="$1"
    local output="$2"
    whileread -r line; do
        if [[ "$line" == *"FAILED LOGIN"* ]]; then
            echo"$line" >> "$output"
        fi
    done < "$file"
}
log_files=("server1.log""server2.log""server3.log")
results=()
for file in"${log_files[@]}"; do
    output="${file%.log}_failed.log"
    parse_logs "$file""$output"
    results+=("$output")
done
timestamp=$(date "+%Y-%m-%d")
final_report="failed_logins_$timestamp.txt"
cat "${results[@]}" > "$final_report"
if [[ -s "$final_report" ]]; then
    echo"报告已生成: $final_report"
else
    echo"未找到失败的登录。"
    rm "$final_report"
fi

收获

这个脚本结合了工程师在专业 Bash 脚本中几乎需要的所有内容:模块化、错误处理、高效数据处理和调试工具。

通过掌握这些结构,您不仅会编写更好的脚本,还会将平凡的任务转化为优雅的解决方案。

但是,还有一件事(也许是 5 件)。我现在太兴奋了,我会再包含 5 个我经常使用的额外内容:

每个工程师都应知道的 5 个额外 Bash 结构

以下是五个额外的结构:

1. 关联数组

它们是什么: 关联数组是 Bash 中的键值对,从 Bash 4 开始可用。它们允许高效查找和数据组织。

示例: 假设您正在将服务器名称映射到其 IP 地址:

declare -A servers

servers=( ["web"]="192.168.1.10" ["db"]="192.168.1.20" ["cache"]="192.168.1.30" )

# 访问值
echo "Web 服务器 IP: ${servers[web]}"
# 遍历键
for key in "${!servers[@]}"; do
    echo "$key -> ${servers[$key]}"
done

为什么使用它们:

  • 关联数组提供了一种自然的方式来处理结构化数据,无需依赖外部工具如awk 或sed
  • 适用于配置、查找和在脚本中动态组织数据。

2. 使用 Heredocs 进行多行输入

它们是什么: Heredocs 允许在脚本中直接输入多行字符串或数据,提高处理模板或批量数据时的可读性。

示例: 动态生成电子邮件模板:

email_body=$(cat <<EOF
Hello Team,

This is a reminder for the upcoming deployment at midnight.

Regards,
DevOps
EOF)

echo "$email_body" | mail -s "Deployment Reminder" team@example.com

为什么使用它们:

  • 它们消除了复杂字符串连接或外部文件的需求。
  • Heredocs 简化了直接在脚本中处理多行内容,如日志、模板或命令。

3. 使用eval 进行动态命令执行

它是什么:eval 命令允许您将动态构造的字符串作为 Bash 命令执行。

示例: 假设您需要执行存储在变量中的命令:

cmd="ls -l"
eval "$cmd"

或动态设置变量:

var_name="greeting"
eval "$var_name='Hello, World!'"
echo "$greeting"

为什么使用它:

  • eval 提供了处理动态生成命令或输入的灵活性。
  • ⚠ 谨慎使用:虽然强大,但不当使用eval 可能会带来安全风险,尤其是在处理不受信任的输入时。

4. 子 shell 用于隔离执行

它们是什么: 子 shell 是执行命令而不影响父 shell 的子进程。

示例: 假设您想临时更改目录并执行命令:

(current_dir=$(pwd)
cd /tmp
echo "Now in $(pwd)"
)
echo "Back in $current_dir"

为什么使用它们:

  • 子 shell 允许临时更改变量、环境或目录,而不会影响主 shell。
  • 适用于运行不会污染或修改父环境的隔离操作。

5. 命名管道(FIFOs)

它们是什么: 命名管道(或 FIFOs)是特殊文件,通过充当命令之间的缓冲区来促进进程间通信。

示例: 让我们创建一个命名管道在进程之间传输数据:

mkfifo my_pipe

# 在一个终端:写入管道
echo "Hello from process 1" > my_pipe

# 在另一个终端:从管道读取
cat < my_pipe

# 清理
rm my_pipe

为什么使用它们:

  • 命名管道支持进程之间的异步通信,无需临时文件。
  • 适用于实时处理场景,如在命令之间传输日志或流数据。

结论

这些额外的结构——关联数组、Heredocs、eval、子 shell 和命名管道——扩展了您的 Bash 脚本工具包,以应对更复杂的任务。

通过掌握这些结构,您将编写更优雅、高效且易于维护的脚本,以应对实际的工程挑战。

祝您编写愉快!🖥️

转自

每个工程师都应知道的 10 个 Bash 脚本结构
https://mp.weixin.qq.com/s/wdKifwG-cfPc1LAkZiSgBw

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/865005.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PhpStorm 2024.3.1.1 安装激活教程(激活至2026,实际上永久,亲测!)以及常见问题处理

申明:本教程 PhpStorm 补丁、激活码均收集于网络,请勿商用,仅供个人学习使用,如有侵权,请联系作者删除。若条件允许,希望大家购买正版 !卸载老版本 PhpStorm 首先,如果小伙伴的电脑上有安装老版本的 PhpStorm , 需要将其彻底卸载掉,如下所示(没有安装则不用管,直…

以太网物理层IOP测试设备TESTBASE-EIOP

OPEN联盟(OPEN Alliance)是一个由OEM、Tier1和Tier2共同组建的非盈利开放性的行业联盟,旨在将以太网技术在汽车环境中应用及推广,TESTBASE-EIOP是经纬恒润自主研发的车载以太网物理层IOP(交互性)自动化测试设备,可完整覆盖OPEN TC8 IOP测试标准。背景OPEN联盟(OPEN All…

Linux命令行连接蓝牙设备

Linux命令行连接蓝牙设备 查看Bluetooth设备: hciconfig启动一个Bluetooth设备,例如:hci0: hciconfig hci0 up相关指令查看特定的Bluetooth设备(例如,设备名为hci0): hciconfig hci0关闭一个Bluetooth设备(例如,设备名为hci0): hciconfig hci0 down修改一个Bluetoot…

华为云专家说:开源的商业化之路与开发者技术服务

开源在大量在云技术以及业务中应用,从开源与云的增长模式看,开源与云具有相当程度的相似性。本文来源:《华为云DTSE》第五期开源专刊,作者:华为云开发者支持首席布道师汪盛 开源、云的增长模式与 Product Led Growth具有较大相似性,两者增长立足于产品质量与使用的开发者…

JAVA-Day 06:if语句的三种形式

if语句的三种形式if(表达式){语句体}如果小括号里的表达式结果为真,则执行大括号中的语句体,如下图例子所示:2.if(表达式){语句体}else{语句体} 如果小括号里的表达式为真,则执行else前的大括号中的语句体,如果小括号里的表达式为假,则执行else后的大括号中的语句体。如下图…

Redis可视化工具 Another Redis Desktop Manager工具使用详细教程(附下载链接)

Redis 可视化工具推荐:Another Redis Desktop Manager Redis 是一种高性能的键值数据库,广泛应用于缓存和消息队列等场景。对于开发者来说,命令行工具固然强大,但操作繁琐。而一款高效易用的可视化工具可以极大地提升使用效率。本篇将为大家推荐一款开源、跨平台且功能强大…

跟狂神学习第一天,了解Markdown语法

Markdown学习 一个#+空格+标题名字=大标题/一级标题 二级标题 两个#+空格+标题 = 二级标题 三个#+空格+标题 = 三级标题 .......(以此类推) 一直到六级标题 字体 hello! 粗体:文字两边同时加两个* hello! 斜体:文字两边同时加一个* hello! 斜体加粗:文字两边同时加三个…

Ubuntu换源自用备用

Ubuntu换源(本地) 作者 原文链接:https://blog.csdn.net/MacWx/article/details/137689898 查询系统版本 lsb_release -a系统版本是 Ubuntu 20.04.6 LTS,注意这个开发代号Codename,Ubuntu每一个版本都有一个代号,这个一定要跟国内源对应,否则会出问题。 阿里云Ubuntu镜像…

大规模高性能云网络技术思路

控制面基础架构采用微服务架构模型,服务独立可扩展,可以根据每个服务的规模来部署满足需求的实例。具体网络控制面技术方案如图本文分享自天翼云开发者社区《大规模高性能云网络技术思路》,作者:程****超 控制面基础架构采用微服务架构模型,服务独立可扩展,可以根据每个服…

Python开发环境部署教程

本教程将详细介绍如何在 Windows 系统上配置 Python 开发环境,包括安装 Python、配置虚拟环境以及使用 VS Code 进行开发,适合新手和需要精细配置的开发者。本教程将详细介绍如何在 Windows 系统上配置 Python 开发环境,包括安装 Python、配置虚拟环境以及使用 VS Code 进行…

基于云效 Windows 构建环境和 Nuget 制品仓库进行 .Net 应用开发

本文将基于云效 Flow 流水线 Windows 构建环境和云效 Packages Nuget 制品仓库手把手教你如何开发并部署一个 .NET 应用,从环境搭建到实战应用发布的详细教程,帮助你掌握 .NET 开发的核心技能。作者:陆冬澄、周静 在现代软件研发体系中,.NET 平台由于其强大的功能、灵活性和…

初创团队如何借助看板工具简化任务管理

在初创企业的构建过程中,团队管理和项目推进常常面临诸多挑战。由于资金、人员和时间的限制,如何高效地组织和管理项目成为了每个初创团队需要面对的重要课题。幸运的是,借助现代化的看板文档工具,初创团队可以大幅提升其工作效率和协作效果,确保在快速变化的市场环境中保…