空想网安の乌托邦
首页小说读书项目归档照片墙音乐说说杂谈关于
封面

HTB Academy 学习笔记:Introduction to Bash Scripting

写作时间:2026-10-11 18:29:44
# HTB Academy
# 网安

课程来源:Hack The Box Academy Module 21(​Introduction to Bash Scripting​),模块页 <https://academy.hackthebox.com/module/21。本篇按小节归纳课程正文与演示,代码保留课程语义;命令行用户处统一用> ​user@htb[/htb]$​ 占位,不保留页面会话用户名。

模块概览

  • 等级:Easy / Tier 1;预计时长约 5 小时;共 10 节,包含 9 个 Interactive 练习、0 个 Assessment;页面标注最后更新约 6 年前。
  • 前置基础(模块概览列出):Linux Fundamentals、Web Requests。
  • 课程思路:用一个贯穿全章的 ​CIDR.sh​ 脚本,把参数、变量、条件、循环、分支、函数和 I/O 等语法串起来,边看脚本边拆语法。

章节主线

  1. 先建立基本认识:Bash 脚本由解释器执行,适合组合命令、过滤数据、自动化重复任务。
  2. 再逐个拆解脚本组成:条件执行、参数与变量、比较运算符、算术、输入输出控制、循环、分支、函数、调试。
  3. 每个语法点都回看 ​CIDR.sh​ 的对应片段,最终能读懂完整脚本,也能按自己的需求重新组合这些语法。

1. Bourne Again Shell:Bash 与脚本执行

脚本语言与 Bash 的定位

Bash 用于与 Unix 系操作系统交互并给系统下达命令。脚本语言与编程语言最大的区别是不需要先编译,脚本由解释器(这里是 Bash)直接读取执行。做渗透测试或运维时会面对大量数据,掌握终端、过滤和自动化脚本能明显提高处理速度;脚本还是把多个命令组合起来、把单个结果串联起来的主要方式。

Windows 环境也可以通过 Windows Subsystem for Linux (WSL) 运行 Bash,课程明确提到自 2019 年 5 月起 Windows 提供该子系统。

脚本的常见组成

课程把脚本结构拆为以下部分,也是本模块的章节顺序:

  • Input & Output(输入输出)
  • Arguments, Variables & Arrays(参数、变量与数组)
  • Conditional execution(条件执行)
  • Arithmetic(算术)
  • Loops(循环)
  • Comparison operators(比较运算符)
  • Functions(函数)

执行方式

课程给出的三种基本执行方式:

bash script.sh <optional arguments>
sh script.sh <optional arguments>
./script.sh <optional arguments>
  • ​bash script.sh​ / ​sh script.sh​:显式指定解释器处理脚本,不要求文件有执行位。
  • ​./script.sh​:按文件头部的 shebang 指定解释器执行,通常需要先用 ​chmod +x script.sh​ 赋予执行权限(下一节会看到)。
  • 脚本本身不创建新进程,而是由调用它的解释器执行。

贯穿案例:CIDR.sh

课程用 ​./CIDR.sh inlanefreight.com​ 演示脚本能力:先解析域名得到 IP,再交互询问用户要执行哪些检查,最后显示网段信息并 ping 主机。演示输出要点(非完整原文):

Discovered IP address(es):
165. 22.119.202

Additional options available:
    1) Identify the corresponding network range of target domain.
    2) Ping discovered hosts.
    3) All checks.
    *) Exit.

Select your option: 3
NetRange for 165.22.119.202:
NetRange:       165.22.0.0 - 165.22.255.255
CIDR:           165.22.0.0/16

Pinging host(s):
165. 22.119.202 is up.
1 out of 1 hosts are up.

脚本主体(代码保留课程命令语义,中文注释为本笔记归纳):

#!/bin/bash

# 1) 参数检查:没有参数时打印用法并退出
if [ $# -eq 0 ]
then
    echo -e "You need to specify the target domain.\n"
    echo -e "Usage:"
    echo -e "\t$0 <domain>"
    exit 1
else
    domain=$1
fi

# 2) 查询 IP 对应的网段
function network_range {
    for ip in $ipaddr
    do
        netrange=$(whois $ip | grep "NetRange\|CIDR" | tee -a CIDR.txt)
        cidr=$(whois $ip | grep "CIDR" | awk '{print $2}')
        cidr_ips=$(prips $cidr)
        echo -e "\nNetRange for $ip:"
        echo -e "$netrange"
    done
}

# 3) 对网段内主机做 ping 存活检测
function ping_host {
    hosts_up=0
    hosts_total=0
    echo -e "\nPinging host(s):"
    for host in $cidr_ips
    do
        stat=1
        while [ $stat -eq 1 ]
        do
            ping -c 2 $host > /dev/null 2>&1
            if [ $? -eq 0 ]
            then
                echo "$host is up."
                ((stat--)); ((hosts_up++)); ((hosts_total++))
            else
                echo "$host is down."
                ((stat--)); ((hosts_total++))
            fi
        done
    done
    echo -e "\n$hosts_up out of $hosts_total hosts are up."
}

# 4) 域名解析
hosts=$(host $domain | grep "has address" | cut -d" " -f4 | tee discovered_hosts.txt)
echo -e "Discovered IP address:\n$hosts\n"
ipaddr=$(host $domain | grep "has address" | cut -d" " -f4 | tr "\n" " ")

# 5) 交互菜单
echo -e "Additional options available:"
echo -e "\t1) Identify the corresponding network range of target domain."
echo -e "\t2) Ping discovered hosts."
echo -e "\t3) All checks."
echo -e "\t*) Exit.\n"

read -p "Select your option: " opt

case $opt in
    "1") network_range ;;
    "2") ping_host ;;
    "3") network_range && ping_host ;;
    "*") exit 0 ;;
esac
  • 课程按注释把脚本拆为 5 个部分:检查给定参数、识别网段、ping 已发现主机、识别域名 IP、提供可用选项。
  • 脚本用到的 ​whois​、​prips​、​host​、​ping​ 等命令,课程直接使用,没有给出安装步骤;本笔记不补写安装教程。

2. Conditional Execution:条件执行

作用

条件执行让脚本按"条件是否成立"选择执行某段代码;没有它就只能一条命令接一条命令往下跑。条件成立时只执行对应代码段,其他分支被跳过,完成后继续执行条件块后面的命令。

shebang

  • 脚本第一行通常是 ​#!/bin/bash​,以 ​#!​ 开头,指定解释器路径。
  • shebang 也可以指向其他解释器,例如 Python、Perl:
#!/usr/bin/env python
#!/usr/bin/env perl

if / elif / else / fi

课程把 ​if-else​ 与 ​case​ 并列为最基础的条件判断形式。以 CIDR.sh 参数检查为例,伪代码表达为:

if [ 参数个数等于 0 ]
then
    打印 "You need to specify the target domain."
    打印空行
    打印 Usage
    以错误码退出
else
    把第一个参数赋给 domain 变量
fi

实际代码如下:

#!/bin/bash

# Check for given argument
if [ $# -eq 0 ]
then
    echo -e "You need to specify the target domain.\n"
    echo -e "Usage:"
    echo -e "\t$0 <domain>"
    exit 1
else
    domain=$1
fi
  • 结构词:​if​、​then​、​elif​、​else​、​fi​;​fi​ 表示条件块结束。
  • 本段用到的组件:​#!/bin/bash​ 是 shebang,​if-else-fi​ 是条件执行,​echo​ 打印输出,​#/0/$1​ 是特殊变量,​domain​ 是普通变量。

只有 if 的脚本

#!/bin/bash

value=$1

if [ $value -gt "10" ]
then
        echo "Given argument is greater than 10."
fi

执行结果:

  • 只传 ​5​ 时没有输出;
  • 传 ​12​ 时输出 ​Given argument is greater than 10.​。

if-elif-else 组合

#!/bin/bash

value=$1

if [ $value -gt "10" ]
then
    echo "Given argument is greater than 10."
elif [ $value -lt "10" ]
then
    echo "Given argument is less than 10."
else
    echo "Given argument is not a number."
fi

执行结果:

  • ​5​ → less than 分支;
  • ​12​ → greater than 分支;
  • 传 ​HTB​ 这类非数字时,两个整数比较都会报 ​integer expression expected​,最终落到 ​else​,说明把变量当整数比较前应先确认输入确实是数字。

多条件扩展:按参数个数分流

if [ $# -eq 0 ]
then
    echo -e "You need to specify the target domain.\n"
    echo -e "Usage:\n\t$0 <domain>"
    exit 1
elif [ $# -eq 1 ]
then
    domain=$1
else
    echo -e "Too many arguments given."
    exit 1
fi
  • ​$# -eq 0​:没有参数 → 打印用法并退出。
  • ​# -eq 1​:恰好一个参数 → 接受 ​domain=1​。
  • 参数多于一个时由 ​else​ 承接 → 提示参数过多并以错误码退出。

3. Arguments, Variables, and Arrays:参数、变量与数组

位置参数 9

  • 执行脚本时可以传最多 9 个参数:​1​到​1​ 到 ​1​到​9​,​$0​ 保留给脚本名。
  • 使用变量时要加 ​$​;赋值时则不加。
user@htb[/htb]$ ./script.sh ARG1 ARG2 ARG3 ... ARG9
# 对应关系:$0  $1  $2  $3 ... $9
  • 这些位置参数由 shell 自动填充,称为特殊变量(special variables)。

特殊变量

课程列出的常用特殊变量:

变量 含义 ​#​ 传入脚本的参数个数 ​@​ 命令行参数列表 ​n​按位置取第n个参数,例如​n​ 按位置取第 n 个参数,例如 ​n​按位置取第n个参数,例如​1​ ​$$​ 当前执行进程的 PID ​$?​ 上一条命令/脚本的退出状态,0 表示成功,非 0 表示失败

回到 CIDR.sh 的参数检查:

  • ​# -eq 0​ 判断是否缺参数;只传一个 FQDN 时 ​#​ 的值为 1。
  • ​$0​ 显示在 Usage 中,表示正在执行的脚本名。
  • ​$1​ 是第一个参数,被赋给 ​domain​ 变量。

执行权限与执行方式

  • 直接 ​./​ 执行前先设置执行位:
chmod +x cidr.sh
  • 不传参数时,​./cidr.sh​ 和 ​bash cidr.sh​ 都会打印用法并退出。
  • 课程借此说明:​./​ 方式依赖执行位;​bash cidr.sh​ 是显式让解释器读取脚本,即使文件没有执行位也可运行(只要可读)。

变量赋值

变量赋值时必须有空格约束:名称、​=​、值之间不能有空格。

  • 错误写法:
variable = "this will result with an error."

结果是把 ​variable​ 当成一个命令,报 ​command not found: variable​。

  • 正确写法:
variable="Declared without an error."
echo $variable
  • Bash 不严格区分字符串、整数、布尔类型,变量内容默认都按字符串处理;只有数值内容参与某些运算时才按数解释。
  • 使用变量值用 ​variable​或​variable​ 或 ​variable​或​{variable}​。

数组

数组可以把多个值放进一个变量,适合批量扫描域名、IP 等;索引从 0 开始:

#!/bin/bash

domains=(www.inlanefreight.com ftp.inlanefreight.com vpn.inlanefreight.com www2.inlanefreight.com)
echo ${domains[0]}
  • ​echo ${domains[0]}​ 输出 ​www.inlanefreight.com​。
  • 花括号用于变量展开,访问数组元素时不能省略。
  • 单引号或双引号会把内部空格合并为一个元素:
domains=("www.inlanefreight.com ftp.inlanefreight.com vpn.inlanefreight.com" www2.inlanefreight.com)
echo ${domains[0]}

此时第一项是完整带空格的字符串。

IFS 提醒

特殊变量依赖 IFS(Internal Field Separator)识别参数/字段边界;课程只提示 IFS 决定参数何时结束、下一个何时开始,没有在本节展开配置细节。

4. Comparison Operators:比较运算符

四类运算符

比较运算符决定两个值如何比较。课程按用途分为字符串运算符、整数运算符、文件运算符、布尔与逻辑运算符四类。

字符串运算符

运算符 含义 ​==​ 相等 ​!=​ 不相等 ​<​ ASCII 字母序较小(仅 ​[[ ]]​ 内可用) ​>​ ASCII 字母序较大(仅 ​[[ ]]​ 内可用) ​-z​ 字符串为空(null) ​-n​ 字符串不为空

关键点:

  • 变量最好加双引号,例如 ​"$1"​,让 Bash 把内容当字符串处理。
  • ​<​/​>​ 不能直接在单方括号 ​[ ]​ 中使用,需要 ​[[ ]]​。
  • 查看 ASCII 表可以执行 ​man ascii​。

示例:要求参数必须等于 ​HackTheBox​,且参数不多于 1 个:

#!/bin/bash

# Check the given argument
if [ "$1" != "HackTheBox" ]
then
    echo -e "You need to give 'HackTheBox' as argument."
    exit 1
elif [ $# -gt 1 ]
then
    echo -e "Too many arguments given."
    exit 1
else
    domain=$1
    echo -e "Success!"
fi

ASCII 概要

  • ASCII(American Standard Code for Information Interchange)是 7 位字符编码,共 128 个码点(十进制 0–127、十六进制 00–7F)。
  • 前 32 个是控制字符,例如 0(NUL)表示字符串结束;65–68 对应 A–D;127(DEL)是删除。
  • 需要完整表时在终端执行 ​man ascii​。

整数运算符

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

示例:按参数个数分流:

#!/bin/bash

# Check the given argument
if [ $# -lt 1 ]
then
    echo -e "Number of given arguments is less than 1"
    exit 1
elif [ $# -gt 1 ]
then
    echo -e "Number of given arguments is greater than 1"
    exit 1
else
    domain=$1
    echo -e "Number of given arguments equals 1"
fi

文件运算符

运算符 含义 ​-e​ 文件存在 ​-f​ 是普通文件 ​-d​ 是目录 ​-L​ 是符号链接 ​-N​ 自上次读取后被修改 ​-O​ 当前用户拥有该文件 ​-G​ 文件组 ID 与当前用户组匹配 ​-s​ 文件大小大于 0 ​-r​ / ​-w​ / ​-x​ 有读 / 写 / 执行权限

示例:先判断指定文件是否存在,存在返回退出码 0,不存在返回 2:

#!/bin/bash

# Check if the specified file exists
if [ -e "$1" ]
then
    echo -e "The file exists."
    exit 0
else
    echo -e "The file does not exist."
    exit 2
fi

布尔与逻辑运算符

  • 用 ​[[ 条件 ]]​ 可以得到 ​true/false​,例如 ​[[ -z $1 ]]​ 检查第一个参数是否为空。
  • 逻辑运算符:

运算符 含义 ​!​ 逻辑非 NOT ​&&​ 逻辑与 AND `

示例:文件存在且可读 → 成功;不存在 → 退出码 2;存在但不可读 → 退出码 1:

#!/bin/bash

# Check if the specified file exists and if we have read permissions
if [[ -e "$1" && -r "$1" ]]
then
    echo -e "We can read the file that has been specified."
    exit 0
elif [[ ! -e "$1" ]]
then
    echo -e "The specified file does not exist."
    exit 2
elif [[ -e "$1" && ! -r "$1" ]]
then
    echo -e "We don't have read permission for this file."
    exit 1
else
    echo -e "Error occured."
    exit 5
fi

5. Arithmetic:算术运算

算术运算符

运算符 含义 ​+​ 加 ​-​ 减 ​*​ 乘 ​/​ 除 ​%​ 取模 ​变量++​ 变量值加 1 ​变量--​ 变量值减 1

课程用 Arithmetic.sh 汇总演示:

#!/bin/bash

increase=1
decrease=1

echo "Addition: 10 + 10 = $((10 + 10))"
echo "Subtraction: 10 - 10 = $((10 - 10))"
echo "Multiplication: 10 * 10 = $((10 * 10))"
echo "Division: 10 / 10 = $((10 / 10))"
echo "Modulus: 10 % 4 = $((10 % 4))"

((increase++))
echo "Increase Variable: $increase"

((decrease--))
echo "Decrease Variable: $decrease"

输出要点:

Addition: 10 + 10 = 20
Subtraction: 10 - 10 = 0
Multiplication: 10 * 10 = 100
Division: 10 / 10 = 1
Modulus: 10 % 4 = 2
Increase Variable: 2
Decrease Variable: 0
  • 算术表达式写在 ​$(( ... ))​ 中。
  • ​((var++))​ / ​((var--))​ 直接修改变量值。

变量长度

​${#variable}​ 返回变量的字符数。例如:

#!/bin/bash

htb="HackTheBox"
echo ${#htb}

输出 ​10​。

回到 CIDR.sh

CIDR.sh 的 ping_host 函数中多次使用 ​((stat--))​、​((hosts_up++))​、​((hosts_total++))​:

  • ​stat​ 初值为 1,ping 结束后 ​stat--​ 使 while 条件变假,结束当前主机的探测循环。
  • 无论主机 up 还是 down,​hosts_total++​ 都计数;只有 up 时 ​hosts_up++​。
  • 最后用两个计数输出 "N out of M hosts are up"。

6. Input and Output Control:输入与输出控制

交互输入:read

有些流程需要人工决定下一步,例如是否继续执行可能受限的扫描活动;脚本需要能停下来等待用户输入。

CIDR.sh 的菜单使用 ​read -p​:

echo -e "Additional options available:"
echo -e "\t1) Identify the corresponding network range of target domain."
echo -e "\t2) Ping discovered hosts."
echo -e "\t3) All checks."
echo -e "\t*) Exit.\n"

read -p "Select your option: " opt

case $opt in
    "1") network_range ;;
    "2") ping_host ;;
    "3") network_range && ping_host ;;
    "*") exit 0 ;;
esac
  • ​echo​ 先打印菜单;​read -p "Select your option: " opt​ 显示提示并把输入存入 ​opt​。
  • ​-p​ 让提示与输入留在同一行。
  • 后续 ​case​ 按 ​opt​ 的值执行对应函数,具体见第 8 节。

输出控制:tee

  • 直接重定向到文件时看不到命令输出;脚本变复杂、执行时间变长后,等待过程会很不方便。
  • ​tee​ 把结果同时写到终端和文件:​命令 | tee 文件​。
  • ​-a / --append​ 表示追加而不是覆盖,适合把多次结果累积到同一文件。

CIDR.sh 中的两处用法:

netrange=$(whois $ip | grep "NetRange\|CIDR" | tee -a CIDR.txt)

网段信息立即显示并追加保存到 CIDR.txt。

hosts=$(host $domain | grep "has address" | cut -d" " -f4 | tee discovered_hosts.txt)

解析出的 IP 同时写入 discovered_hosts.txt。

查看两个文件可以看到累积结果:

cat discovered_hosts.txt CIDR.txt

课程预期的文件内容要点:

165. 22.119.202
NetRange:       165.22.0.0 - 165.22.255.255
CIDR:           165.22.0.0/16

7. Flow Control - Loops:循环

控制结构概览

  • 分支:if-else 条件、case 语句。
  • 循环:for、while、until。
  • 控制结构通常由布尔值/逻辑表达式控制执行。

for 循环

for 每轮从列表、增量或数据源取一个值,列表耗尽即结束;适合遍历数组、主机、端口,也适合对已知服务和端口批量执行命令,加快枚举。

for variable in 1 2 3 4
do
    echo $variable
done
for ip in 10.10.10.170 10.10.10.174 10.10.10.175
do
    ping -c 1 $ip
done

也可以写成单行:

for ip in 10.10.10.170 10.10.10.174;do ping -c 1 $ip;done

CIDR.sh 的 ​network_range​ 用 ​for ip in $ipaddr​ 遍历解析出的每个 IP,对每个 IP 执行 whois、过滤 ​NetRange|CIDR​、用 tee 保存;再用 ​prips​ 把 CDIR 展开成地址清单,供后续查找更多主机(在客户授权范围内)或继续存活检测。

while 循环

条件为真时反复执行,条件为假时结束;必须靠计数器、布尔变量或 ​break​ 退出,否则会死循环。

课程先用 WhileBreaker.sh 演示 break 与 continue:

#!/bin/bash

counter=0

while [ $counter -lt 10 ]
do
  # Increase $counter by 1
  ((counter++))
  echo "Counter: $counter"

  if [ $counter == 2 ]
  then
    continue
  elif [ $counter == 4 ]
  then
    break
  fi
done

输出到 ​Counter: 4​ 为止:到 2 时 ​continue​ 跳过本轮剩余,到 4 时 ​break​ 终止循环。

CIDR.sh 中的典型用法:

stat=1
while [ $stat -eq 1 ]
do
    ping -c 2 $host > /dev/null 2>&1
    if [ $? -eq 0 ]
    then
        echo "$host is up."
        ((stat--))
        ((hosts_up++))
        ((hosts_total++))
    else
        echo "$host is down."
        ((stat--))
        ((hosts_total++))
    fi
done
  • 条件写法与 ​if-else​ 相同,使用 ​[ 条件 ]​。
  • ​stat​ 每次探测后减 1,循环只跑一次,等价于"等这次 ping 有结果后再继续";课程中这套写法用于统一处理 up/down 计数。

until 循环

与 while 相反:条件为假时反复执行,直到条件变真;适合"跑到目标值"。

课程用 Until.sh 演示从 1 数到 10:

#!/bin/bash

counter=0

until [ $counter -eq 10 ]
do
  # Increase $counter by 1
  ((counter++))
  echo "Counter: $counter"
done

输出 ​Counter: 1​ 到 ​Counter: 10​ 后退出。

嵌套循环注意事项

嵌套循环可以把多个处理步骤合并,但过深嵌套会降低可读性、错误难追踪;课程提醒脚本应保持清晰,必要时把逻辑拆成函数。

8. Flow Control - Branches:分支(case)

case 的作用

case 语句在其他语言中对应 switch-case。它与 if-else 的主要区别:

  • if-else 可以判断任意布尔表达式;
  • case 只把同一个表达式与精确值/模式比较,不能写 ​>​、​<​ 这类范围条件。

语法

case <expression> in
    pattern_1 ) statements ;;
    pattern_2 ) statements ;;
    pattern_3 ) statements ;;
esac
  • 以 ​case​ 开始、​esac​ 结束。
  • 每个分支是 ​模式 ) 语句 ;;​,双分号 ​;;​ 表示该分支结束。
  • 表达式命中哪个模式,就执行对应语句。

CIDR.sh 中的菜单分支

case $opt in
    "1") network_range ;;
    "2") ping_host ;;
    "3") network_range && ping_host ;;
    "*") exit 0 ;;
esac
  • 1 → 只查询网段;
  • 2 → 只 ping 主机;
  • 3 → 先查询网段再 ping 主机;
  • 其他输入(​*​)→ 退出脚本。

9. Functions:函数

为什么用函数

脚本越大越容易混乱;同一段逻辑反复出现时,函数可以把多条命令包成一个块,用名字调用,减少重复并提升可读性。函数必须先定义再调用(脚本自上而下执行),所以定义习惯放在脚本开头。

两种定义方式

function name {
    <commands>
}
name() {
    <commands>
}

两种都可以;CIDR.sh 使用带 ​function​ 关键字的第一种,可读性更好。

调用与参数

  • 直接写函数名即可调用,例如 ​network_range​、​ping_host​。
  • 函数参数与脚本参数规则相同:​1​–​1​–​1​–​9​(或 ​${n}​),也可无参数调用。
  • 每个函数拥有独立的参数集,不会与其他函数或脚本参数冲突。
#!/bin/bash

function print_pars {
    echo $1 $2 $3
}

one="First parameter"
two="Second parameter"
three="Third parameter"

print_pars "$one" "$two" "$three"

输出:

First parameter Second parameter Third parameter

全局变量与 local

Bash 中默认所有变量都是全局的:函数里第一次定义的变量,脚本外部也能访问;需要隔离时才用 ​local​ 显式声明。

返回码

子进程或函数结束时会把返回码交回父进程(shell),用于判断执行是否成功。​$?​ 可读取上一条命令或函数的返回码。

课程列出的常见返回码:

返回码 含义 1 一般错误 2 shell 内建使用不当 126 命令无法执行 127 命令未找到 128 传给 exit 的参数无效 128+n 收到致命信号 n 130 脚本被 Ctrl-C 终止 255* 退出状态超出范围

返回值三种取法

  • ​return​:设置函数返回码,配合 ​$?​ 读取。
  • ​echo​:把结果输出到 stdout。
  • 命令替换:用 ​$(...)​ 捕获函数输出并存入变量。

示例 Return.sh:

#!/bin/bash

function given_args {
    if [ $# -lt 1 ]
    then
        echo -e "Number of arguments: $#"
        return 1
    else
        echo -e "Number of arguments: $#"
        return 0
    fi
}

# No arguments given
given_args
echo -e "Function status code: $?\n"

# One argument given
given_args "argument"
echo -e "Function status code: $?\n"

# Pass the results of the funtion into a variable
content=$(given_args "argument")
echo -e "Content of the variable: \n\t$content"

输出要点:

Number of arguments: 0
Function status code: 1

Number of arguments: 1
Function status code: 0

Content of the variable:
    Number of arguments: 1

10. Debugging:脚本调试

调试的意义

调试是发现、追踪和修复代码错误(bug)的过程,既可用于检查拼写错误,也可用于分析某类输入为什么导致特定错误。课程同时说明,安全研究中也常通过不同输入触发错误、观察程序内部对错误的处理,进而研究是否能把控执行流;这部分内容由其他模块深入展开。

bash -x(xtrace)

​bash -x​ 会逐条显示实际执行的命令和展开后的值,便于核对条件与变量:

bash -x CIDR.sh

课程输出要点:

+ '[' 0 -eq 0 ']'
+ echo -e 'You need to specify the target domain.\n'
You need to specify the target domain.
+ echo -e Usage:
Usage:
+ echo -e '\tCIDR.sh <domain>'
    CIDR.sh <domain>
+ exit 1
  • 每行以 ​+​ 开头,表示这是一条已展开的实际执行步骤。
  • 从中可以直接确认:无参数时 ​[ 0 -eq 0 ]​ 成立,脚本打印用法并以状态 1 退出。

bash -v(verbose)

​bash -x -v​ 在 xtrace 基础上同时显示已经处理到的整段源码,便于对照源代码位置和实际执行步骤:

bash -x -v CIDR.sh

输出先显示脚本源码,再附带 ​+​ 开头的实际执行步骤;相比只用 ​-x​,能看到"整段代码处理过程 + 每一步命令"。

验证方法

调试后重点核对:条件是否按预期进入分支、变量是否展开成预期值、命令是否真的执行、退出码是否符合设计。

模块小结(归纳)

  • 本模块的所有语法点都围绕 ​CIDR.sh​ 展开:参数检查 → 域名解析 → whois 网段查询 → ping 存活 → 菜单分支。
  • 一句话主线:看懂脚本 = 看懂参数/变量 → 条件与比较 → 循环与分支 → 函数 → 用调试确认每一步。
  • 课程提供的命令组合(管道、​tee​、​$(...)​、​case​)可以在授权范围内直接复用于目标枚举、批量检测和结果归档。
  • 本模块正文全部为文字、命令与表格,没有需要下载保留的教学图片;各节的图片盘点记录见同目录 ​.audit.json​。

 

‍

avatar

Zybaxy918039

书本,学术,网安之间反复横跳的业余爱好者,目前在自学计算机网络和AI相关知识

RECOMMENDED

HTB Academy:使用 Nmap 进行网络枚举

2026-09-19 22:17:09

HTB Academy:信息收集-网络版(Web Reconnaissance)学习笔记

2026-09-19 22:22:34

HTB Academy:Footprinting(足迹收集)

2026-09-20 12:23:20

Table of Contents