4. 边缘网关的启动流程定制

任务说明

本案例要求为工业IoT边缘网关定制启动流程,实现按序完成硬件初始化、网络就绪检查、核心服务拉起与业务应用启动,并在启动异常时提供可观测的失败定位信息。完成目标是得到一个可独立运行的启动脚本及配套配置,能够通过模拟命令验证各阶段执行顺序与失败处理逻辑。

启动流程设计

边缘网关启动分为四个阶段,每个阶段对应独立函数与日志标记,便于在串口或系统日志中定位执行进度:

  • stage1_hardware_init:加载内核模块、配置GPIO复用、初始化传感器总线;
  • stage2_network_ready:等待以太网链路建立并获取IP地址,带超时重试;
  • stage3_core_services:启动MQTT Broker与数据采集守护进程;
  • stage4_app_start:拉起边缘业务容器或用户应用。

任一步骤失败时,脚本立即停止后续阶段,输出包含阶段名与退出码的错误信息,并以非零状态退出,供systemd或上层编排捕获。

实现代码


#!/bin/bash
# /opt/gateway/scripts/boot_sequence.sh
# 边缘网关启动流程定制脚本

CONFIG_FILE="/opt/gateway/conf/boot_order.conf"
LOG_TAG="GW_BOOT"

# 加载配置文件中的阶段开关与超时参数
source "$CONFIG_FILE"

log_info() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$LOG_TAG] [INFO] $*"
}

log_error() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$LOG_TAG] [ERROR] $*" >&2
}

# 阶段1:硬件初始化
stage1_hardware_init() {
    log_info "stage1: hardware init begin"
    # 模拟加载内核模块
    modprobe i2c_dev 2>/dev/null || { log_error "stage1: modprobe i2c_dev failed"; return 1; }
    # 模拟GPIO导出与方向设置
    echo 17 > /sys/class/gpio/export 2>/dev/null
    echo out > /sys/class/gpio/gpio17/direction 2>/dev/null
    log_info "stage1: hardware init done"
    return 0
}

# 阶段2:网络就绪检查
stage2_network_ready() {
    log_info "stage2: waiting for network, timeout=${NET_TIMEOUT}s"
    local waited=0
    while [ $waited -lt "$NET_TIMEOUT" ]; do
        # 检查eth0是否有IPv4地址
        if ip -4 addr show eth0 2>/dev/null | grep -q "inet "; then
            log_info "stage2: network ready, IP=$(ip -4 addr show eth0 | grep 'inet ' | awk '{print $2}' | cut -d/ -f1)"
            return 0
        fi
        sleep 2
        waited=$((waited + 2))
    done
    log_error "stage2: network not ready after ${NET_TIMEOUT}s"
    return 1
}

# 阶段3:核心服务启动
stage3_core_services() {
    log_info "stage3: starting core services"
    # 启动MQTT Broker (mosquitto)
    systemctl start mosquitto 2>/dev/null || { log_error "stage3: mosquitto start failed"; return 1; }
    # 启动数据采集服务
    /opt/gateway/bin/collector --daemon 2>/dev/null || { log_error "stage3: collector start failed"; return 1; }
    log_info "stage3: core services started"
    return 0
}

# 阶段4:业务应用启动
stage4_app_start() {
    log_info "stage4: starting edge application"
    # 启动边缘容器应用
    docker start edge-app 2>/dev/null || { log_error "stage4: edge-app start failed"; return 1; }
    log_info "stage4: edge application started"
    return 0
}

# 主流程:按配置顺序执行
main() {
    log_info "gateway boot sequence started"
    local stage_funcs=("stage1_hardware_init" "stage2_network_ready" "stage3_core_services" "stage4_app_start")
    local stage_names=("hardware" "network" "core_services" "app")

    for i in "${!stage_funcs[@]}"; do
        # 检查配置中该阶段是否启用
        local enable_key="ENABLE_${stage_names[$i]}"
        if [ "${!enable_key}" != "1" ]; then
            log_info "stage $((i+1)) (${stage_names[$i]}) disabled by config, skip"
            continue
        fi
        if ! ${stage_funcs[$i]}; then
            log_error "boot aborted at stage $((i+1)) (${stage_names[$i]})"
            exit 1
        fi
    done
    log_info "gateway boot sequence completed successfully"
    exit 0
}

main "$@"

配置文件


# /opt/gateway/conf/boot_order.conf
# 各阶段启用开关:1=启用,0=跳过
ENABLE_hardware=1
ENABLE_network=1
ENABLE_core_services=1
ENABLE_app=1

# 网络等待超时(秒)
NET_TIMEOUT=30

落地与验证

将上述两个文件分别保存到网关的/opt/gateway/scripts/与/opt/gateway/conf/目录,并赋予执行权限:


chmod +x /opt/gateway/scripts/boot_sequence.sh

在开发环境验证时,由于modprobe、systemctl、docker等命令可能不可用,可先创建以下模拟桩命令进行流程验证:


# 创建临时bin目录并加入PATH
mkdir -p /tmp/fakebin
cat > /tmp/fakebin/modprobe <<'EOF'
#!/bin/bash
echo "fake modprobe $*"
exit 0
EOF
cat > /tmp/fakebin/systemctl <<'EOF'
#!/bin/bash
echo "fake systemctl $*"
exit 0
EOF
cat > /tmp/fakebin/docker <<'EOF'
#!/bin/bash
echo "fake docker $*"
exit 0
EOF
chmod +x /tmp/fakebin/*
export PATH="/tmp/fakebin:$PATH"

同时准备一个模拟的ip命令用于测试网络阶段成功与失败两种路径:


# 模拟网络就绪(返回IP)
cat > /tmp/fakebin/ip <<'EOF'
#!/bin/bash
if [ "$1" = "-4" ]; then
    echo "2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500"
    echo "    inet 192.168.1.100/24 brd 192.168.1.255 scope global eth0"
fi
exit 0
EOF
chmod +x /tmp/fakebin/ip

执行启动脚本并观察输出:


/opt/gateway/scripts/boot_sequence.sh

判定标准:

  1. 正常路径下,日志依次出现stage1至stage4的begin/done信息,最后输出boot sequence completed successfully,退出码为0;
  2. 将配置中ENABLE_network=0后再次执行,日志应显示network阶段被跳过,且不执行后续阶段;
  3. 将模拟ip命令改为不输出IP(即删除inet行),并将NET_TIMEOUT设为4,执行后应看到stage2: network not ready错误,脚本退出码为1,且不执行stage3与stage4。
边缘网关启动流程状态机 stage1 硬件初始化 stage2 网络就绪检查 stage3 核心服务启动 stage4 业务应用启动 启动完成 exit 0 启动中止 exit 1 + 错误日志 配置控制(boot_order.conf) ENABLE_hardware=1 → 执行stage1;ENABLE_network=0 → 跳过stage2,直接进入stage3 NET_TIMEOUT=30 → stage2等待网络超时阈值,超时后触发失败路径 正常流转 失败中止路径