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
判定标准:
- 正常路径下,日志依次出现
stage1至stage4的begin/done信息,最后输出boot sequence completed successfully,退出码为0; - 将配置中
ENABLE_network=0后再次执行,日志应显示network阶段被跳过,且不执行后续阶段; - 将模拟
ip命令改为不输出IP(即删除inet行),并将NET_TIMEOUT设为4,执行后应看到stage2: network not ready错误,脚本退出码为1,且不执行stage3与stage4。