linux shell

关注公众号 jb51net

关闭
首页 > 脚本专栏 > linux shell > Linux shell脚本

Linux运维必备之shell脚本编写规范与执行方式详解

作者:着迷不白

这篇实战文章将带你系统学习Shell脚本,从编写规范、变量参数到条件判断和循环,还有一键部署Nginx等案例,掌握这些Shell脚本技能,轻松实现批量操作和自动化运维,减轻管理员工作量

一、Shell脚本概述

1.1 什么是Shell脚本

1.2 学习Shell脚本的前提

  1. 熟悉Linux常用命令
  2. 熟悉常用服务的部署与配置(如Apache、Nginx、DNS等)
  3. 熟练文本处理工具:grepawksed
  4. 熟悉Vim编辑器

二、Shell脚本编写规范

2.1 基本规范

#!/bin/bash
# Author: 作者名
# Mail: 联系方式
# Date: 日期
# Describe: 脚本描述
# Warning: 警告信息
# Version: 版本号
# Modify: 修改记录

2.2 快速生成注释模板(.vimrc配置)

~/.vimrc中添加以下内容,新建.sh文件时自动生成头部注释:

autocmd BufNewFile *.py,*.cc,*.sh,*.java exec ":call SetTitle()"
func SetTitle()
    if expand("%:e") == 'sh'
        call setline(1,"#!/bin/bash")
        call setline(2,"##############################################################")
        call setline(3, "# File Name: ".expand("%"))
        call setline(4, "# Version: V1.0")
        call setline(5, "# Author: yourname")
        call setline(6, "# Email: your@email.com")
        call setline(7, "# Created Time : ".strftime("%F %T"))
        call setline(8, "# Description:")
        call setline(9,"##############################################################")
        call setline(10, "")
    endif
endfunc

2.3 注释方式

<<EOF
这是多行注释
不会被执行
EOF

三、Shell脚本的执行方式

3.1 四种执行方式

方式语法是否需要x权限执行环境
相对路径./script.sh需要子Shell
绝对路径/root/script.sh需要子Shell
source或点source script.sh. script.sh不需要(需要r权限)当前Shell
bash/shbash script.shsh script.sh不需要(需要r权限)子Shell

3.2 注意事项

四、变量与参数

4.1 位置化变量(位置参数)

用于在执行脚本时传入参数:

变量含义
$0脚本文件本身的名字
$1第一个参数
$2第二个参数
......
${10}第十个及以上参数需用花括号

示例:创建用户并设置密码的脚本

#!/bin/bash
# useradd.sh
useradd $1
echo $2 | passwd --stdin $1

执行:./useradd.sh zhangsan redhat

4.2 预定义变量

变量含义
$?上一条命令的退出状态码(0成功,非0失败)
$#传递给脚本的参数个数
$*所有参数(作为一个字符串)
$@所有参数(每个作为独立字符串)
$$当前Shell进程的PID

4.3 read命令 – 从键盘读取输入

语法read [选项] [变量名]

选项说明
-p "提示信息"输出提示信息
-s隐藏输入(常用于密码)
-t 秒数超时自动跳过
不指定变量名数据存入环境变量REPLY

示例

#!/bin/bash
read -p "请输入用户名: " username
read -s -p "请输入密码: " password
useradd $username
echo $password | passwd --stdin $username
echo "$username 创建成功,密码已设置"

4.4 exit命令

示例:检查密码中是否包含连续数字12345,若包含则退出

#!/bin/bash
read -p "请输入密码: " pass
echo $pass | grep 12345 -q
if [ $? -eq 0 ]; then
    echo "密码不能包含12345"
    exit 1
fi
echo "密码合法"

五、逻辑运算符与复合指令

5.1 逻辑运算符

运算符含义规则
&&逻辑与前一条命令成功(返回0)才执行后一条
``
!逻辑非对返回状态取反

示例

# 创建用户并设置密码
useradd luojiyu && echo 1 | passwd --stdin luojiyu

# 如果用户存在则修改密码,否则创建
useradd devops || echo 1 | passwd --stdin devops

# 判断IP是否通,根据结果写入不同文件
ping -c4 10.10.10.1 &>/dev/null && echo 10.10.10.1 > /opt/ip-ok.txt || echo 10.10.10.1 > /opt/ip-error.txt

5.2 复合指令

; :顺序执行多条命令,无条件执行所有命令

command1; command2; command3

(命令;命令) :在子Shell中执行,括号开头不需要空格,最后命令不用分号

(cd /tmp; pwd)   

{ 命令;命令; } :在当前Shell中执行,花括号开头必须有空格,每条命令以分号结尾

{ cd /tmp; pwd; }   

六、条件测试语句

条件测试用于判断表达式的真假,返回值为0表示真,非0表示假。

6.1 三种测试语法

语法说明
test 条件表达式常用在终端临时测试
[ 条件表达式 ]脚本中常用,注意空格
[[ 条件表达式 ]]支持正则和通配符,更强大

示例

test root = 123 ; echo $?     # 返回1
[ 1 -eq 1 ]; echo $?          # 返回0
[[ "abc" == a* ]]; echo $?    # 支持通配符,返回0

6.2 文件属性运算符

运算符含义
-e 文件文件存在
-f 文件是普通文件
-d 文件是目录
-s 文件文件非空
-r 文件可读
-w 文件可写
-x 文件可执行
-L 文件是链接文件

示例

# 如果/tmp/passwd不存在则拷贝
[ -e /tmp/passwd ] || cp /etc/passwd /tmp/passwd

# 如果useradd有执行权限则拷贝并修改所有者
[ -x /usr/sbin/useradd ] && cp /usr/sbin/useradd /tmp && chown devops /tmp/useradd

# 如果文件没有读权限则添加
[ -r /tmp/passwd ] || chmod a+r /tmp/passwd

6.3 数字比较运算符

运算符含义
-eq等于
-ne不等于
-gt大于
-ge大于等于
-lt小于
-le小于等于

注意:不要使用数学符号><等在条件测试中,它们会被解释为重定向

示例:判断根分区使用率是否超过10%

disk_num=$(df | grep -w / | awk '{print $5}' | tr -d %)
if [ $disk_num -ge 10 ]; then
    rm -rf /tmp/*
    echo "tmp目录已清空"
else
    echo "disk free,使用率: ${disk_num}%"
fi

6.4 字符串比较运算符

运算符含义
===相等
!=不等
-z 字符串字符串为空(长度0)
-n 字符串字符串非空

示例

# 判断输入是否为root
read -p "输入用户名: " name
[ "$name" = "root" ] && echo "UID: $(id -u root)" || exit

# 检查参数是否为空
[ -z $1 ] && echo "请传入参数" || echo "参数是: $1"

6.5 布尔运算符(用于[ ]中)

运算符含义
-a逻辑与(AND)
-o逻辑或(OR)
!逻辑非

[[ ]]中可使用&&||!更直观。

示例

# 用户名是zhangsan 且 UID>=1000
[ "$username" = "zhangsan" -a $useruid -ge 1000 ] && echo ok || echo error

# 使用[[ ]]
[[ "$username" = "zhangsan" && $useruid -ge 1000 ]] && echo ok

七、判断语句

7.1 if单分支

语法

if 条件表达式; then
    执行语句
fi


# 第二种写法
if 条件表达式
then
    执行语句
fi

示例:用户已存在则退出

#!/bin/bash
read -p "输入用户名: " name
if id $name &>/dev/null; then
    echo "$name 已存在,不能创建"
    exit
fi
useradd $name

7.2 if双分支

语法

if 条件表达式; then
    语句1
else
    语句2
fi

示例:用户存在则重置密码,否则创建

#!/bin/bash
read -p "输入用户名: " name
if id $name &>/dev/null; then
    read -p "重置密码: " pass
    echo $pass | passwd --stdin $name
else
    useradd $name
    echo 1 | passwd --stdin $name
fi

示例:备份脚本(判断目录是否存在)

#!/bin/bash
read -p "要备份的文件路径: " src
read -p "备份目录路径: " dst
if [ -d "$dst" ]; then
    chmod 777 $dst
else
    mkdir $dst
fi
cp -a $src $dst/$(basename $src)-$(date +%F).bak

7.3 if多分支

语法

if 条件1; then
    语句1
elif 条件2; then
    语句2
else
    语句3
fi

示例:成绩等级判断

read -p "请输入成绩(0-100): " score
if [ $score -ge 85 ]; then
    echo "优秀 - A"
elif [ $score -ge 70 ]; then
    echo "良好 - B"
elif [ $score -ge 60 ]; then
    echo "合格 - C"
else
    echo "不合格 - D"
fi

7.4 case多分支

用于多值匹配,比多个elif更清晰。

语法

case 变量 in
    模式1)
        命令
        ;;
    模式2)
        命令
        ;;
    *)
        默认命令
        ;;
esac

示例:成绩等级(case版本)

read -p "请输入成绩(0-100): " score
case $score in
    8[5-9]|9[0-9]|100)
        echo "优秀 - A"
        ;;
    7[0-9]|8[0-4])
        echo "良好 - B"
        ;;
    6[0-9])
        echo "合格 - C"
        ;;
    *)
        echo "不合格 - D"
        ;;
esac

模式支持

八、循环语句

8.1 for循环

语法

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

四种列表生成方式

# 1. 直接列出
for i in 1 2 3 4 5; do echo $i; done

# 2. 大括号(支持数字和字母)
for i in {1..5}; do echo $i; done
for c in {a..z}; do echo $c; done

# 3. seq命令
for i in $(seq 1 5); do echo $i; done

# 4. 命令执行结果
for file in $(ls *.sh); do echo $file; done

C语言风格for循环

for ((i=1; i<=10; i++)); do
    echo $i
done

示例1:批量创建用户(从文件读取)

for user in $(cat userlist.txt); do
    useradd $user
    echo 123456 | passwd --stdin $user
done

示例2:扫描局域网在线主机

for i in {1..254}; do
    ip="192.168.1.$i"
    ping -c2 -W1 $ip &>/dev/null
    if [ $? -eq 0 ]; then
        echo "$ip is up"
    else
        echo "$ip is down"
    fi
done

8.2 while循环

当条件为真时循环,条件为假时退出。

语法

while 条件表达式; do
    命令
done

示例:读取文件每一行(三种方式)

# 方式1:exec重定向
exec < file.txt
while read line; do
    echo $line
done

# 方式2:管道
cat file.txt | while read line; do
    echo $line
done

# 方式3:重定向结尾(推荐)
while read line; do
    echo $line
done < file.txt

示例:从iplist文件读取IP和端口

# iplist内容:
# 192.168.1.101 22
# 192.168.1.102 80
while read line; do
    IP=$(echo $line | awk '{print $1}')
    PORT=$(echo $line | awk '{print $2}')
    echo "IP: $IP, PORT: $PORT"
done < iplist

8.3 until循环

与while相反:条件为时进入循环,为时退出。

语法

until 条件表达式; do
    命令
done

示例:等待某个文件出现

until [ -f /tmp/ready ]; do
    echo "等待文件..."
    sleep 2
done
echo "文件已出现"

8.4 break和continue

示例

# break: 当i=4时跳出
for i in {1..10}; do
    if [ $i -eq 4 ]; then
        break
    fi
    echo $i
done
# 输出: 1 2 3

# continue: 当i=4时跳过
for i in {1..10}; do
    if [ $i -eq 4 ]; then
        continue
    fi
    echo $i
done
# 输出: 1 2 3 5 6 7 8 9 10

九、综合实践案例

9.1 一键部署Nginx脚本框架

#!/bin/bash
# 检查是否root用户
if [ $EUID -ne 0 ]; then
    echo "请使用root用户执行"
    exit 1
fi

# 安装依赖
yum install -y gcc make pcre-devel zlib-devel

# 下载并编译安装Nginx
cd /usr/local/src
wget http://nginx.org/download/nginx-1.24.0.tar.gz
tar xf nginx-1.24.0.tar.gz
cd nginx-1.24.0
./configure --prefix=/usr/local/nginx
make && make install

# 启动
/usr/local/nginx/sbin/nginx
echo "Nginx部署完成"

9.2 安全创建用户脚本

#!/bin/bash
read -p "请输入用户名: " username
if id $username &>/dev/null; then
    echo "用户已存在"
    exit 1
fi
read -s -p "请输入密码: " password
read -s -p "确认密码: " password2
echo
if [ "$password" != "$password2" ]; then
    echo "两次密码不一致"
    exit 1
fi
useradd $username
echo $password | passwd --stdin $username &>/dev/null
echo "用户 $username 创建成功"

9.3 系统监控脚本

#!/bin/bash
# 监控CPU、内存、磁盘使用率
cpu=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1)
mem=$(free | grep Mem | awk '{printf "%.2f", $3/$2 * 100}')
disk=$(df -h / | awk 'NR==2 {print $5}' | tr -d '%')

echo "CPU使用率: $cpu%"
echo "内存使用率: $mem%"
echo "根分区使用率: $disk%"

if [ $disk -gt 80 ]; then
    echo "警告:磁盘空间不足"
fi

十、总结

知识点核心要点
编写规范#!/bin/bash, 注释, .sh后缀
执行方式路径需x权限;source在当前shell;其他在子shell
read-p提示,-s隐藏,-t超时
条件测试[ ],文件 -f/-d,数字 -eq/-gt,字符串 =/-z
逻辑符&&(成功则执行),||(失败则执行)
判断if单/双/多分支,case多值匹配
循环for(列表/C风格),while(条件真循环),until(条件假循环)
控制break跳出,continue跳过本次

掌握以上内容,即可编写大部分日常运维所需的Shell脚本。实践中多动手、多调试,利用set -x调试模式查看执行过程。

以上就是Linux运维必备之shell脚本编写规范与执行方式详解的详细内容,更多关于Linux shell脚本的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文