本文目录导读:

- 使用
inotifywait监控文件系统事件 - 使用
trap处理信号事件 - 使用命名管道实现异步事件
- 使用
socat实现网络事件驱动 - 事件循环 + 超时机制
- 使用
xargs实现并行事件处理 - 完整的消息队列事件驱动示例
Shell脚本本身不是事件驱动架构的原生语言,但可以通过多种机制模拟事件驱动模式,以下是几种主流实现方法:
使用 inotifywait 监控文件系统事件
#!/bin/bash
# 监控目录变化
WATCH_DIR="/path/to/watch"
inotifywait -m -r -e create -e modify -e delete --format '%w%f %e' "$WATCH_DIR" |
while read file event; do
case "$event" in
CREATE)
echo "文件创建: $file"
# 处理创建事件
;;
MODIFY)
echo "文件修改: $file"
# 处理修改事件
;;
DELETE)
echo "文件删除: $file"
# 处理删除事件
;;
esac
done
使用 trap 处理信号事件
#!/bin/bash
# 定义信号处理函数
cleanup() {
echo "收到终止信号,清理资源..."
# 清理操作
exit 0
}
reload_config() {
echo "重新加载配置..."
# 重新加载配置
}
# 注册信号处理器
trap cleanup SIGINT SIGTERM
trap reload_config SIGHUP
# 主循环
echo "服务启动,PID: $$"
while true; do
# 主业务逻辑
sleep 1
done
使用命名管道实现异步事件
#!/bin/bash
PIPE="/tmp/event-pipe"
mkfifo "$PIPE" 2>/dev/null
# 事件分发器
event_loop() {
while true; do
if read event < "$PIPE"; then
handle_event "$event"
fi
done
}
# 事件处理器
handle_event() {
local event="$1"
case "$event" in
"user_login")
echo "用户登录事件触发"
# 执行登录逻辑
;;
"data_update")
echo "数据更新事件触发"
# 执行更新逻辑
;;
"shutdown")
echo "关闭事件,退出程序"
exit 0
;;
esac
}
# 事件发送函数
send_event() {
echo "$1" > "$PIPE" &
}
# 启动事件循环
event_loop &
# 模拟发送事件
send_event "user_login"
sleep 2
send_event "data_update"
sleep 2
send_event "shutdown"
wait
rm -f "$PIPE"
使用 socat 实现网络事件驱动
#!/bin/bash PORT=8080 # 接收HTTP请求事件 socat TCP-LISTEN:$PORT,fork EXEC:./request_handler.sh # request_handler.sh 内容 #!/bin/bash read request echo "接收到请求: $request" # 解析请求并处理 echo -e "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nEvent processed"
事件循环 + 超时机制
#!/bin/bash
# 事件队列
declare -A EVENT_QUEUE
EVENT_COUNTER=0
# 注册事件
register_event() {
local event_name="$1"
local callback="$2"
EVENT_QUEUE["$event_name"]="$callback"
}
# 触发事件
trigger_event() {
local event_name="$1"
local callback="${EVENT_QUEUE[$event_name]}"
if [ -n "$callback" ]; then
$callback "$@"
else
echo "未注册的事件: $event_name"
fi
}
# 事件循环
event_loop() {
local timeout="$1"
while true; do
# 检查是否有待处理事件
# 这里可以是文件监控、定时器或其他
# 模拟超时
if [ "$EVENT_COUNTER" -ge "$timeout" ]; then
trigger_event "timeout"
break
fi
sleep 1
((EVENT_COUNTER++))
done
}
# 定义事件处理器
on_timeout() {
echo "超时事件触发,退出循环"
}
# 注册事件
register_event "timeout" "on_timeout"
# 启动事件循环(5秒超时)
event_loop 5
使用 xargs 实现并行事件处理
#!/bin/bash
# 事件处理函数
process_event() {
local event="$1"
echo "处理事件: $event (PID: $$)"
sleep 2
}
# 事件源
generate_events() {
for i in {1..5}; do
echo "event_$i"
done
}
# 并行处理事件(最多3个并行)
generate_events | xargs -P3 -I{} bash -c 'process_event "$@"' _ {}
完整的消息队列事件驱动示例
#!/bin/bash
# 事件驱动框架
EVENT_HANDLERS=()
MESSAGE_QUEUE="/tmp/msg_queue"
# 初始化
init() {
mkfifo "$MESSAGE_QUEUE" 2>/dev/null
echo "事件驱动框架初始化完成"
}
# 注册事件处理器
on() {
local event="$1"
local handler="$2"
EVENT_HANDLERS["$event"]="$handler"
}
# 发送事件
emit() {
local event="$1"
shift
local data="$@"
echo "$event|$data" > "$MESSAGE_QUEUE" &
}
# 事件循环
start() {
echo "启动事件循环..."
while true; do
if read line < "$MESSAGE_QUEUE"; then
IFS='|' read -r event data <<< "$line"
handler="${EVENT_HANDLERS[$event]}"
if [ -n "$handler" ]; then
echo "处理事件: $event"
$handler "$data"
fi
fi
done
}
# 定义事件处理器
on_user_login() {
echo "用户登录: $1"
# 执行登录后的逻辑
}
on_data_received() {
echo "收到数据: $1"
# 处理数据
}
on_error() {
echo "错误: $1"
# 错误处理
}
# 主程序
init
on "user_login" "on_user_login"
on "data_received" "on_data_received"
on "error" "on_error"
# 启动事件循环(后台运行)
start &
# 发送测试事件
sleep 1
emit "user_login" "Alice"
sleep 1
emit "data_received" "some_data"
sleep 1
emit "error" "connection_timeout"
# 等待处理完成
sleep 3
kill %1 2>/dev/null
rm -f "$MESSAGE_QUEUE"
- 使用
inotifywait:适合文件系统监控场景 - 使用
trap:处理系统信号事件 - 命名管道:实现进程间通信的事件队列
socat/nc:网络事件驱动- 并行处理:使用
xargs -P实现并发 - 状态机:结合
case语句实现状态转换
选择哪种方法取决于具体需求:文件监控场景首选 inotifywait,进程间通信推荐命名管道,网络服务用 socat,简单的事件处理用 trap。