本文目录导读:

Shell脚本实现任务队列有多种方式,从简单到复杂,我为你介绍几种常用方案:
基于文件的任务队列(最简单)
生产者-消费者模式
#!/bin/bash
QUEUE_DIR="/tmp/task_queue"
mkdir -p "$QUEUE_DIR"
# 生产者:添加任务
add_task() {
local task_id=$(date +%s%N)
local task_file="$QUEUE_DIR/$task_id"
# 写入任务内容
cat > "$task_file" << EOF
{
"id": "$task_id",
"command": "$1",
"created_at": "$(date)"
}
EOF
echo "Task $task_id added"
}
# 消费者:处理任务
process_tasks() {
while true; do
# 获取最早的任务文件
local task_file=$(ls -t "$QUEUE_DIR" 2>/dev/null | tail -1)
if [[ -n "$task_file" ]]; then
local full_path="$QUEUE_DIR/$task_file"
echo "Processing: $task_file"
# 执行任务(使用source加载任务内容)
source "$full_path"
eval "$command"
# 处理完成后删除任务文件
rm "$full_path"
echo "Completed: $task_file"
fi
sleep 1
done
}
# 使用示例
add_task "echo 'Hello World'"
add_task "sleep 2; echo 'Task 2 done'"
add_task "date"
# 启动消费者(在后台运行)
process_tasks &
基于命名管道的任务队列
#!/bin/bash
PIPE="/tmp/task_pipe"
LOCK_FILE="/tmp/task_pipe.lock"
# 初始化管道
init_pipe() {
if [[ ! -p "$PIPE" ]]; then
mkfifo "$PIPE"
fi
}
# 添加任务到队列
enqueue() {
echo "$1" >> "$PIPE"
}
# 从队列取出任务
dequeue() {
local task=""
# 使用文件锁确保原子操作
(
flock -x 200
# 读取一个任务
read -r task < "$PIPE"
if [[ -n "$task" ]]; then
echo "$task"
fi
) 200>"$LOCK_FILE"
}
# 工作进程
worker() {
while true; do
local task=$(dequeue)
if [[ -n "$task" ]]; then
echo "Worker $$ executing: $task"
eval "$task"
echo "Worker $$ completed: $task"
fi
sleep 0.1
done
}
# 使用示例
init_pipe
# 添加任务
for i in {1..5}; do
enqueue "echo 'Task $i: $(date)'"
done
# 启动2个工作进程
worker &
worker &
# 等待所有任务完成
wait
带有并发控制的队列
#!/bin/bash
MAX_CONCURRENT=3
QUEUE_FILE="/tmp/queue.txt"
RUNNING_FILE="/tmp/running.txt"
# 初始化队列
init_queue() {
> "$QUEUE_FILE"
> "$RUNNING_FILE"
}
# 添加任务
add_to_queue() {
echo "$1" >> "$QUEUE_FILE"
}
# 获取任务计数
get_queue_count() {
wc -l < "$QUEUE_FILE" 2>/dev/null || echo 0
}
# 获取运行中的任务数
get_running_count() {
wc -l < "$RUNNING_FILE" 2>/dev/null || echo 0
}
# 执行任务
execute_task() {
local task="$1"
local task_id=$(date +%s%N)
# 记录运行中的任务
echo "$task_id:$task" >> "$RUNNING_FILE"
echo "Starting: $task"
# 执行任务
eval "$task"
# 从运行列表中移除
sed -i "/^$task_id:/d" "$RUNNING_FILE"
echo "Completed: $task"
}
# 调度器
scheduler() {
while true; do
local queue_count=$(get_queue_count)
local running_count=$(get_running_count)
# 检查是否有空闲槽位和待处理任务
if [[ $running_count -lt $MAX_CONCURRENT && $queue_count -gt 0 ]]; then
# 获取第一个任务
local task=$(head -1 "$QUEUE_FILE")
if [[ -n "$task" ]]; then
# 从队列中移除
sed -i '1d' "$QUEUE_FILE"
# 在子进程中执行
(execute_task "$task") &
fi
fi
sleep 0.5
done
}
# 使用示例
init_queue
# 添加一些耗时任务
add_to_queue "sleep 2; echo 'Task 1 done'"
add_to_queue "sleep 3; echo 'Task 2 done'"
add_to_queue "sleep 1; echo 'Task 3 done'"
add_to_queue "sleep 4; echo 'Task 4 done'"
add_to_queue "sleep 2; echo 'Task 5 done'"
# 启动调度器
scheduler &
# 等待完成
sleep 10
echo "All tasks dispatched"
带有资源限制的队列系统
#!/bin/bash
# 任务队列类
declare -A TASK_QUEUE
TASK_COUNTER=0
MAX_TASKS=10
MAX_MEMORY=500 # MB
# 检查系统资源
check_resources() {
local memory_usage=$(free -m | awk 'NR==2{print $3}')
local cpu_usage=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1)
if [[ $memory_usage -gt $MAX_MEMORY ]]; then
return 1 # 内存不足
fi
if [[ $(echo "$cpu_usage > 80" | bc) -eq 1 ]]; then
return 1 # CPU负载过高
fi
return 0
}
# 添加任务
add_task() {
local priority=${2:-5} # 默认优先级5
local task_id=$((++TASK_COUNTER))
TASK_QUEUE[$task_id]="$1:$priority"
# 按优先级排序
sort_tasks
}
# 排序任务(按优先级)
sort_tasks() {
# 创建临时排序文件
local temp_file=$(mktemp)
for id in "${!TASK_QUEUE[@]}"; do
IFS=':' read -r task priority <<< "${TASK_QUEUE[$id]}"
echo "$priority $id $task" >> "$temp_file"
done
sort -n "$temp_file" | while read line; do
echo "$line"
done
rm "$temp_file"
}
# 获取最高优先级任务
get_next_task() {
local highest_priority=999
local next_task_id=""
local next_command=""
for id in "${!TASK_QUEUE[@]}"; do
IFS=':' read -r task priority <<< "${TASK_QUEUE[$id]}"
if [[ $priority -lt $highest_priority ]]; then
highest_priority=$priority
next_task_id=$id
next_command=$task
fi
done
if [[ -n "$next_task_id" ]]; then
echo "$next_task_id:$next_command"
fi
}
# 执行任务
run_task() {
local command="$1"
if check_resources; then
echo "Executing: $command"
eval "$command"
return $?
else
echo "Resource limit reached, waiting..."
sleep 2
run_task "$command" # 重试
fi
}
# 任务管理器
task_manager() {
while true; do
local next_task=$(get_next_task)
if [[ -n "$next_task" ]]; then
local task_id="${next_task%%:*}"
local command="${next_task#*:}"
# 删除任务
unset TASK_QUEUE[$task_id]
# 执行任务
run_task "$command"
echo "Task $task_id completed"
fi
sleep 1
done
}
# 使用示例
add_task "echo 'High priority task'" 1
add_task "sleep 2; echo 'Normal task'"
add_task "sleep 1; echo 'Low priority task'" 10
# 启动任务管理器
task_manager &
企业级队列管理(带状态记录)
#!/bin/bash
# 队列数据库(使用文件模拟)
QUEUE_DB="/tmp/queue.db"
STATUS_DB="/tmp/queue_status.db"
# 初始化数据库
init_db() {
echo "task_id|status|command|created_at|completed_at" > "$QUEUE_DB"
echo "idle" > "$STATUS_DB"
}
# 添加任务到数据库
db_add_task() {
local task_id=$(uuidgen 2>/dev/null || date +%s%N)
local command="$1"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "$task_id|pending|$command|$timestamp|" >> "$QUEUE_DB"
echo "$task_id"
}
# 更新任务状态
db_update_status() {
local task_id="$1"
local new_status="$2"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
# 使用临时文件更新
local temp_file=$(mktemp)
while IFS='|' read -r id status command created completed; do
if [[ "$id" == "$task_id" ]]; then
if [[ "$new_status" == "completed" || "$new_status" == "failed" ]]; then
echo "$id|$new_status|$command|$created|$timestamp"
else
echo "$id|$new_status|$command|$created|$completed"
fi
else
echo "$id|$status|$command|$created|$completed"
fi
done < "$QUEUE_DB" > "$temp_file"
mv "$temp_file" "$QUEUE_DB"
}
# 获取待处理任务
get_pending_tasks() {
awk -F'|' '$2 == "pending" {print $0}' "$QUEUE_DB"
}
# 任务执行器
task_executor() {
local worker_id=$1
echo "Worker $worker_id started"
while true; do
# 获取当前系统状态
local queue_status=$(cat "$STATUS_DB")
if [[ "$queue_status" == "running" ]]; then
# 获取待处理任务
local pending_tasks=$(get_pending_tasks)
if [[ -n "$pending_tasks" ]]; then
# 取第一个任务
local task=$(echo "$pending_tasks" | head -1)
local task_id=$(echo "$task" | cut -d'|' -f1)
local command=$(echo "$task" | cut -d'|' -f3)
# 更新状态为运行中
db_update_status "$task_id" "running"
echo "Worker $worker_id executing: $command"
# 执行任务
if eval "$command"; then
db_update_status "$task_id" "completed"
echo "Worker $worker_id completed task $task_id"
else
db_update_status "$task_id" "failed"
echo "Worker $worker_id failed task $task_id"
fi
fi
fi
sleep 2
done
}
# 队列控制器
queue_controller() {
echo "Queue controller started"
# 添加示例任务
for i in {1..5}; do
db_add_task "echo 'Task $i: $(date)'; sleep 2"
done
# 设置队列为运行状态
echo "running" > "$STATUS_DB"
# 启动3个工作进程
for i in {1..3}; do
task_executor "$i" &
done
# 监控队列状态
while true; do
local pending=$(get_pending_tasks | wc -l)
local total=$(wc -l < "$QUEUE_DB")
echo "Queue status: $pending pending / $((total - 1)) total"
if [[ $pending -eq 0 ]]; then
echo "All tasks completed"
echo "idle" > "$STATUS_DB"
break
fi
sleep 5
done
}
# 使用示例
init_db
queue_controller
使用建议
- 简单场景:使用基于文件的队列(方法1)
- 并发控制:使用命名管道方案(方法2)
- 资源限制:使用带有资源控制的队列(方法3-4)
- 企业级应用:使用带数据库记录的方案(方法5)
这些方案可以根据你的具体需求进行修改和扩展,需要我详细解释某个具体实现吗?
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播