实战篇!Linux shell 脚本详解(非常详细)零基础入门到精通 ...

2025-12-26 07:53:32 · 作者: AI Assistant · 浏览: 7

在Linux系统中,Shell脚本是一种强大的工具,能够简化重复性任务、自动化运维流程并提升开发效率。本文将系统地介绍Shell脚本的基础知识、变量处理、流程控制及实战案例,帮助零基础读者掌握Shell脚本的核心技巧,逐步走向精通。

Shell脚本作为Linux系统中不可或缺的一部分,为开发者和系统管理员提供了极大的便利。从简单的命令执行到复杂的自动化任务,掌握Shell脚本的编写和使用是Linux编程中极为关键的一环。本文将从Shell脚本入门、变量处理、流程控制到实战案例,一步步夯实技术基础,让读者能够灵活运用Shell脚本提升效率。

1. Shell脚本基础

1.1 什么是Shell?

Shell本质上是Linux命令解释器,它负责接收用户的命令并将其传递给内核执行。Shell脚本则是将多个命令按照逻辑顺序组合在一起,形成一个可执行的自动化流程。对于熟悉Linux命令的开发者来说,编写Shell脚本是一件相对简单的事情,因为它只是将命令串行化

1.2 Shell编程注意事项

Shell脚本的命名需遵循一定规范,名称应为英文以.sh结尾不能使用特殊符号或空格。脚本的第一行通常为#!/bin/bash,它是指定解释器的必要信息。在定义变量时,变量名不能以数字开头,也不能有破折号(-),可以使用下划线(_)。

1.3 第一个Shell脚本:Hello World

编写第一个Shell脚本是入门的第一步。通过简单的echo命令,我们即可输出“hello world”。脚本的创建过程包括:

  1. 创建文件touch Helloword.sh
  2. 编辑文件vim Helloword.sh
  3. 写入内容bash #!/bin/bash echo "hello world"
  4. 赋予执行权限chmod o+x Helloword.sh
  5. 运行脚本./Helloword.sh

该脚本的输出为:

hello world

通过这一基础案例如何体现Shell脚本的实用性?它展示了如何构建一个最小可运行的脚本,并执行简单的任务。在实际操作中,这类脚本可能是更复杂脚本的基础模块。

2. Shell变量详解

2.1 Shell变量的分类

Shell变量分为三种类型:系统变量、环境变量和用户变量。其中,系统变量用于脚本内部的参数处理,环境变量用于运行时配置,而用户变量则是局部变量,仅用于当前脚本。

2.2 系统变量

系统变量是Shell脚本中常用的变量,主要用于存储命令执行状态、脚本名、参数等信息。常见的系统变量包括:

  • $0:当前脚本的名称
  • $n:当前脚本的第n个参数(n从1到9)
  • $*:当前脚本的所有参数
  • $#:当前脚本的参数数量
  • $?:上一条命令的退出状态
  • $$:当前脚本的进程ID

这些变量在脚本中可以用于参数判断、条件控制和调试,是编写脚本时非常重要的工具。

2.3 环境变量

环境变量用于存储系统配置信息,例如PATH用于定义命令搜索路径,HOME表示用户的家目录,USER表示当前用户,PWD表示当前路径等。环境变量可以通过export进行输出,让用户在其他进程或脚本中使用。例如:

export PATH=/usr/local/bin:$PATH

该命令将/usr/local/bin添加到PATH的开头,使得系统可以优先查找该路径下的命令

2.4 用户自定义变量

用户变量是仅在当前Shell脚本中有效的变量,它们通常用于存储临时数据或脚本内部逻辑。例如:

a=rivers
b=10
c="This is a string"

这些变量在脚本中可以被任意使用,但需要注意变量名的格式:不能以数字或特殊符号开头,并且不能包含空格

2.5 使用echo进行彩色输出

在Shell脚本中,可以使用echo -e来实现彩色输出,这在调试和信息展示中非常实用。例如:

for i in {31..37}; do
    echo -e "\033[$i;40mHello world!\033[0m"
done

这段脚本将依次以不同的字体颜色输出“Hello world!”,其中\033是一个转义字符,用于控制终端的输出样式。通过这种方式,可以增强脚本的可读性和用户体验。

3. Shell流程控制语句

Shell脚本的流程控制语句包括if、for、while、case等,它们是实现复杂逻辑的基础。

3.1 if 条件语句

3.1.1 基本结构

if语句用于条件判断,其基本结构如下:

  • 单分支语句bash if [ 条件 ]; then 命令 fi

  • 双分支语句bash if [ 条件 ]; then 命令1 else 命令2 fi

  • 多条件分支bash if [ 条件1 ]; then 命令1 elif [ 条件2 ]; then 命令2 else 命令3 fi

3.1.2 常见判断逻辑运算符

Shell中的if语句使用逻辑运算符来判断条件。常见的运算符包括:

  • -f:判断文件是否存在
  • -d:判断目录是否存在
  • -eq/-ne/-lt/-gt/-le/-ge:整型比较(等于、不等于、小于、大于、小于等于、大于等于)
  • -a:逻辑“与”(and)
  • -o:逻辑“或”(or)
  • -z:判断字符串是否为空
  • -x:判断文件是否具有可执行权限

这些运算符可以帮助开发者对文件、目录、数值和字符串进行判断,从而实现复杂的逻辑分支。

3.1.3 案例:判断crond服务是否运行

下面是一个判断crond进程是否运行的脚本案例:

#!/bin/bash
# this is check crond
# by author rivers on 2021-9-23

name=crond
num=$(ps -ef | grep $name | grep -vc grep)

if [ $num -eq 1 ]; then
    echo "$num running!"
else
    echo "$num is not running!"
fi

通过该脚本,可以检测crond进程是否正在运行。ps -ef用于列出所有进程,grep用于筛选出crond进程,grep -vc grep用于排除grep自身的进程。最终,通过比较num与1的值,判断crond是否运行。

3.1.4 案例:判断系统目录是否存在

该脚本用于判断系统目录是否存在,如果有不存在的目录,就创建:

#!/bin/bash
# this is check directory
# by author rivers on 2021-9-27

if [ ! -d /data/rivers -a ! -d /tmp/rivers ]; then
    mkdir -p /data/rivers /tmp/rivers
fi

-d用于判断目录是否存在,-a表示逻辑“与”,即两个目录都不存在时才执行创建操作。

3.1.5 案例:判断学生成绩等级

该脚本根据输入的分数,判断学生的成绩等级:

#!/bin/bash
# this check grade shell
# by author rivers on 2021-09-27

grade=$1

if [ $grade -gt 90 ]; then
    echo "Is's very good!"
elif [ $grade -gt 70 ]; then
    echo "Is's is good!"
elif [ $grade -ge 60 ]; then
    echo "pass"
else
    echo "no pass"
fi

通过ifelif语句,可以实现多分支条件判断。此外,$1表示脚本的第一个参数,即学生的分数。

3.2 for循环语句

for循环用于依次处理一组元素,常用于遍历文件或目录。基本格式为:

for 变量名 in 取值列表; do
    命令
done

3.2.1 检查同一局域网内多台主机是否存活

下面是一个检查局域网内多台主机是否存活的脚本案例:

#!/bin/bash
# check hosts is on/Off
# by rivers on 20219-23

Network=$1

for Host in $(seq 1 254); do
    ping -c 1 $Network.$Host > /dev/null && result=0 || result=1

    if [ "$result" == 0 ]; then
        echo -e "\033[32;1m$Network.$Host is up \033[0m"
        echo "$Network.$Host" >> /tmp/up.txt
    else
        echo -e "\033[;31m$Network.$Host is down \033[0m"
        echo "$Network.$Host" >> /tmp/down.txt
    fi
done

该脚本通过ping命令检测254台主机是否在线,并将结果分别保存到up.txtdown.txt中。seq 1 254用于生成从1到254的数字,ping -c 1用于发送一次请求并立即返回结果。> /dev/null表示忽略输出内容,&&||用于控制执行流程。

3.3 while循环语句

while循环用于持续执行某个操作,直到条件不满足为止。其基本格式为:

while (表达式); do
    命令
done

3.3.1 案例:求1-100的总和

下面是一个使用while循环求1到100的总和的脚本:

#!/bin/bash
# by author rivers on 2021-9-27

j=0
i=1

while ((i <= 100)); do
    j=$((j + i))
    ((i++))
done

echo $j

该脚本通过while ((i <= 100))实现循环,j=$((j + i))用于累加,((i++))用于递增。最终输出为1到100的总和。

3.3.2 案例:每10秒判断用户是否登录

下面是一个每隔10秒检测用户是否登录的脚本:

[root@web-server01~/script]# vim login.sh
#!/bin/bash
#Check File to change.
#By author rivers 2021-9-27

USERS="hbs"
while true
do
    echo "The Time is `date +%F-%T`"
    sleep 10
    NUM=`who | grep "$USERS" | wc -l`

    if [[ $NUM -ge 1 ]]; then
        echo "The $USERS is login in system."
    fi
done

该脚本使用who命令查看当前登录的用户,并通过grepwc -l统计匹配的用户数量。如果数量大于等于1,则表示用户已登录。

3.4 case选择语句

case语句常用于多条件选择,其基本结构为:

case 模式名 in
    模式1)
        命令
        ;;
    模式2)
        命令
        ;;
    *)
        命令
        ;;
esac

3.4.1 案例:编写HTTPD服务控制脚本

下面是一个通过case语句控制httpd服务状态的脚本:

[root@web-server01~/script]# vim httpd_start.sh
# check http server start|stop|starus
# by author rivers on 2021-9-27

while true
do
    echo -e "       \033[31m start \033[0m       \033[32m stop \033[0m        \033[33m status \033[0m       \033[34m quit \033[0m    "
    read -p "请输入你的选择start|stop|quit:" char

    case $char in
        start)
            systemctl start httpd && echo "httpd服务已经开启" || echo "开启失败"
            ;;
        stop)
            systemctl stop httpd && echo "httpd服务已经关闭" || echo "关闭失败"
            ;;
        status)
            systemctl status httpd && echo -e "           httpd 的服务状态        "
            ;;
        quit)
            break
            ;;
    esac
done

该脚本提供了一个交互式菜单,用户可以选择启动、停止、查看状态或退出服务。通过case语句实现不同的功能分支,极大地提升了脚本的灵活性和可读性。

3.5 select选择语句

select语句类似于for循环,但主要用于菜单选择。其基本结构为:

select i in (表达式); do
    命令
done

例如:

select option in "start" "stop" "status" "quit"; do
    case $option in
        start)
            systemctl start httpd
            ;;
        stop)
            systemctl stop httpd
            ;;
        status)
            systemctl status httpd
            ;;
        quit)
            break
            ;;
    esac
done

select语句通过PS3变量定义菜单提示,用户只需输入对应的选项即可执行相应的操作。这种方式在交互式脚本中非常常见,尤其适用于需要用户输入的场景。

4. 实战技巧与最佳实践

4.1 使用read进行用户输入

在交互式脚本中,read命令用于获取用户输入。例如:

read -p "请输入你的选择:" option

该命令在read前添加-p表示提示用户输入,输入的内容会被保存到变量option中。

4.2 使用trap处理异常

为了增强脚本的健壮性,可以使用trap命令来捕获脚本的异常。例如:

trap 'echo "脚本异常退出" >&2; exit 1' EXIT

该命令在脚本退出时会输出异常信息,并终止脚本。

4.3 使用set -e确保命令失败时脚本终止

set -e是一个行为控制选项,它表示如果脚本中的任何命令失败,则立即终止脚本。例如:

set -e

该命令在脚本开头添加,可以防止脚本因中间命令失败而继续执行,从而避免潜在的错误。

4.4 脚本调试技巧

调试是Shell脚本开发的重要环节。可以通过以下方式实现调试:

  • 在脚本开头添加set -x,表示输出执行过程
  • 使用echo语句打印关键信息。
  • 通过grepawk分析日志文件。

例如:

set -x
echo "脚本开始执行"

该脚本将输出所有执行的命令及其参数,便于开发者跟踪脚本执行情况

5. Shell脚本与运维工具

5.1 使用Docker运行Shell脚本

Docker是现代运维中非常重要的工具,可以将Shell脚本封装为容器。例如:

docker run -d --name my_script -v /path/to/script:/script.sh my_image /script.sh

该命令将脚本文件挂载到Docker容器中并运行。通过Docker,可以实现脚本的快速部署和版本管理

5.2 使用监控工具进行日志分析

监控工具如PrometheusGrafanaELK Stack可以帮助分析Shell脚本的日志输出。例如:

  • 使用logrotate管理日志文件
  • 使用tail -f实时查看日志
  • 使用grep分析特定日志内容

这些工具可以帮助开发者监控脚本执行状态,并自动处理日志数据

6. 总结与展望

Shell脚本是Linux开发与运维中不可或缺的工具。通过掌握变量、流程控制、循环结构等基本语法,开发者可以实现从简单的命令执行到复杂的自动化流程。随着云原生DevOps的普及,Shell脚本在容器化部署、持续集成与自动化运维中的作用越来越重要。

未来,Shell脚本将与高级语言结合使用,例如Python、Go等,实现更复杂的逻辑和功能。同时,Shell脚本的可读性、可维护性也将成为开发者关注的重点。通过不断学习和实践,Shell脚本将成为Linux编程的基石,为系统管理提供强大的支持。

关键字

shell脚本, 变量, 流程控制, 循环, if语句, for循环, while循环, case语句, Docker, 日志分析, Linux编程