shell编程基础

脚本调试方法

调试方式
 -n 检查脚本中的语法错误
 -v 先显示脚本所有内容,然后执行脚本,结果输出,如果执行遇到错误,将错误输出。
 -x 将执行的每一条命令和执行结果都打印出来

脚本开发规范

1、脚本命名要有意义,文件后缀是.sh
2、脚本文件首行是而且必须是脚本解释器
#!/bin/bash
3、脚本文件解释器后面要有脚本的基本信息等内容
脚本文件中尽量不用中文注释;
尽量用英文注释,防止本机或切换系统环境后中文乱码的困扰
常见的注释信息:脚本名称、脚本功能描述、脚本版本、脚本作者、联系方式等
4、脚本文件常见执行方式:bash 脚本名
5、脚本内容执行:从上到下,依次执行
6、代码书写优秀习惯;
  1)成对内容的一次性写出来,防止遗漏。
    如:()、{}、[]、''、``、""
  2)[]中括号两端要有空格,书写时即可留出空格[   ],然后再退格书写内容。
  3)流程控制语句一次性书写完,再添加内容
7、通过缩进让代码易读;(即该有空格的地方就要有空格)

变量定义

基本格式
    变量名=变量值
注意:
    = 两侧不允许有空格
declare语法定义变量
命令语法
    declare 参数 变量名=变量值
参数解析:
  -i 将变量看成整数
  -r 使变量只读  readonly,==**该变量的值无法改变,并且不能为unset**==
  -x 标记变量为全局变量,类似于export
  -a 指定为索引数组(普通数组);查看普通数组
  -A 指定为关联数组;查看关联数组
注意:
    在生产场景中,这种方法比较鸡肋
变量移除
    unset 变量名
命令变量
定义方式一:
    变量名=`命令`
    注意:
      \` 是反引
定义方式二:
    变量名=$(命令)
全局变量
在当前系统的所有环境下都能生效的变量
查看全局环境变量
    env 只显示全局变量,一般结合 grep 和管道符来使用
    printenv 效果与env等同

    export 查看所有的环境变量,包括声明的过程等信息,一般不用
    declare -x 效果与export类似
定义全局变量方法一:
    变量=值
    export 变量
定义全局变量方法二:(最常用)
    export 变量=值

shell脚本常用特殊内置变量

字符串变量解析

变量默认值

格式一:${变量名:-默认值}
    变量a如果有内容,那么就输出a的变量值
    变量a如果没有内容,那么就输出默认的内容
格式二:${变量名+ }
    无论变量a是否有内容,都输出默认值

脚本相关变量

与脚本外交互工具read

read 命令可以实现我们脚本内外的信息自由传递功能。
  read 从标准输入读取一行并赋值给特定变量REPLY。
  read answer 从标准输入读取输入并赋值给变量answer。
  read first last 从标准输入读取内容,将第一个单词放到first中,其他内容放在last中。
  read -s passwd 从标准输入读取内容,写入passwd,不输入效果
  read -n n name 从标准输入读取内容,截取n个字符,写入name,超过n个字符,直接退出
  read -p "prompt" 打印提示,等待输入,并将输入存储在REPLY中。
  read -r line 允许输入包含反斜杠。
  read -t second 指定超时时间,默认是秒,整数
  read -d sper 指定输入信息的截止符号
read相关示例:
[root@rocky9 ~]# read -s password
通过 -p 参数提示用户输入的信心
[root@rocky9 ~]# read -p "请输入登录用户名: " user
请输入登录用户名: root
[root@rocky9 ~]# echo $user
root
[root@rocky9 ~]# read -n 6 -p "只接收6个字符,超过自动退出: " string
注意:
  -p + -s 的组合会导致不会自动换行,可以结合 echo的方式实现换行
[root@rocky9 ~]# read -t 5 -p "等待5秒后自动退出! " second
等待5秒后自动退出! 4

文件表达式

文件属性判断
  -d  检查文件是否存在且为目录文件
  -f  检查文件是否存在且为普通文件
  -S 检查文件是否存在且为socket文件
  -L 检查文件是否存在且为链接文件
  -O  检查文件是否存在并且被当前用户拥有
  -G  检查文件是否存在并且默认组为当前用户组
文件权限判断
  -r  检查文件是否存在且可读
  -w  检查文件是否存在且可写
  -x  检查文件是否存在且可执行
文件存在判断
  -e  检查文件是否存在
  -s  检查文件是否存在且不为空
文件新旧判断
  file1 -nt file2  检查file1是否比file2新
  file1 -ot file2  检查file1是否比file2旧
  file1 -ef file2  检查file1是否与file2是同一个文件,判定依据的是i节点

数学表达式

主要根据给定的两个值,判断第一个与第二个数的关系,如是否大于、小于、等于第二个数。
  n1 -eq n2  相等 n1 -ne n2  不等于 n1 -ge n2  大于等于
  n1 -gt n2  大于 n1 -lt n2  小于 n1 -le n2  小于等于

逻辑组合

方法1:
    [ 条件1 -a 条件2 ] - 两个条件都为真,整体为真,否则为假
    [ 条件1 -o 条件2 ] - 两个条件都为假,整体为假,否则为真
方法2:
    [[ 条件1 && 条件2 ]] - 两个条件都为真,整体为真,否则为假
    [[ 条件1 || 条件2 ]] - 两个条件都为假,整体为假,否则为真

脚本示例

登录模拟案例

cat simple_login.sh
#!/bin/bash
# 定制命令变量
OS_INFO=$(cat /etc/redhat-release)
KERNEL_INFO=$(uname -r)
OS_ARCH=$(uname -m)
HOSTNAME=$(hostname)
# 清屏
clear
# 输出提示信息
echo -e "\e[32m${OS_INFO} \e[0m"
echo -e "\e[32mKernel ${KERNEL_INFO} on an ${OS_ARCH} \e[0m"
echo "---------------------------------"
# 交互输入登陆信息
read -p "请输入用户名:" account
read -s -t30 -p "请输入登录密码:" password
echo
echo "---------------------------------"
# 输出用户输入信息
printf "您输入的用户名:\e[31m%s\e[0m您输入的密码:\e[31m%s\e[0m\n" ${account} ${password}

堡垒机模拟示例

cat simple_jumpserver.sh
#!/bin/bash
# 功能:定制堡垒机的展示页面
# 堡垒机的信息提示
echo -e "\e[31m \t\t 欢迎使用堡垒机"
echo -e "\e[32m
-----------请选择你要登录的远程主机-----------
1: 10.0.0.14 (nginx)
2: 10.0.0.15 (tomcat)
3: 10.0.0.19 (apache)
q: 使用本地主机
----------------------------------------------
"'\033[0m'
# 由于暂时没有学习条件判断,所以暂时选择 q
read -p "请输入您要选择的远程主机编号: " host_index
read -p "请输入登录本地主机的用户名: " user
# 远程连接主机
ssh $user@IP #仅模拟,实际根据需要具体编程

鸡兔同笼

#!/bin/bash
# 定制变量
head="$1"
feet="$2"
# 计算逻辑
# 每个头至少两只脚,多出的脚都是兔子的
rabbit_num=$(( ($feet - $head - $head) / 2))
chick_num=$[ $head - $rabbit_num ]
# 结果输出
echo -e "\e[31m\t鸡和兔的数量\e[0m"
echo -e "\e[32m============================"
echo "鸡的数量: ${chick_num}"
echo "兔的数量:${rabbit_num}"
echo -e "============================\e[0m"

主机网络连通性测试

cat host_network_test.sh
#!/bin/bash
# 功能:测试主机网络连通性
# 版本:v0.1
# 定制普通变量
host_addr="$1"
# 脚本基本判断
[ -z ${host_addr} ] && echo "请输入待测试主机ip" && exit
[ $# -ne 1 ] && echo "请保证输入1个脚本参数" && exit
# 测试主机网络
net_status=$(ping -c1 -w1 ${host_addr} >/dev/null 2>&1 && echo "正常" || echo "异常")
# 信息输出
echo -e "\e[31m\t主机网络状态信息\e[0m"
echo -e "\e[32m================================"
echo "${host_addr} 网络状态: ${net_status}"
echo -e "================================\e[0m"

判断脚本参数数量

#!/bin/bash
# -eq 和 -ne 演示
# 设定普通变量
arg_num=$#
[ $arg_num -eq 1 ] && echo "脚本参数为1,允许执行脚本"
[ $arg_num -ne 1 ] && echo "脚本参数不为1,不允许执行脚本"

判断网站存活性

cat site_healthcheck.sh
#!/bin/bash
# 功能:定制站点的检测功能
# 定制普通变量
site_addr="$1"
# 脚本基本判断
[ -z ${site_addr} ] && echo "请输入待测试站点域名" && exit
[ $# -ne 1 ] && echo "请保证输入1个脚本参数" && exit
# 检测平台的信息提示
echo -e "\e[32m-----------检测平台支持的检测类型-----------
1: wget
2: curl
----------------------------------------"'\033[0m'
# 选择检测类型
read -p "请输入网站的检测方法: " check_type
[ ${check_type} == 1 ] && site_status=$(wget --spider -T5 -q -t2 ${site_addr} && echo "正常" || echo "异常")
[ ${check_type} == 2 ] && site_status=$(curl -s -o /dev/null ${site_addr} && echo "正常" || echo "异常")

# 信息输出
echo
echo -e "\e[31m\t站点状态信息\e[0m"
echo -e "\e[32m================================"
echo "${site_addr} 站点状态: ${site_status}"
echo -e "================================\e[0m"
作者:于浩  创建时间:2026-06-05 15:33
最后编辑:于浩  更新时间:2026-07-12 22:32