如何在Bash后台运行的while循环中导出变量?
问题根源
当你将while循环后台运行(加&)时,该循环会在子shell中执行。子shell与父shell拥有完全独立的环境变量空间,子shell内修改或export的变量无法反向传递给父shell——这就是updates变量始终为空的原因。
解决方案
方案1:用文件存储变量值(最简便)
通过文件作为中间介质,子shell将更新数写入文件,其他需要读取的地方从文件获取:
#!/bin/bash # 定义存储更新数的临时文件 UPDATE_FILE="/tmp/arch_updates_count" echo 0 > "$UPDATE_FILE" # 初始化内容 # 后台循环检查更新并写入文件 while true; do if ping -q -c 1 -W 1 ping.eu > /dev/null; then updates=$(yay -Qu | wc -l) else updates=0 # 网络不通时设为0 fi echo "$updates" > "$UPDATE_FILE" sleep 600 done & # 示例:父脚本中读取当前更新数 echo "当前待更新包数量:$(cat "$UPDATE_FILE")" # 若需实时监控,可添加循环读取 # while true; do # echo "实时更新数:$(cat "$UPDATE_FILE")" # sleep 300 # done
方案2:将变量处理逻辑移入后台进程
如果你的业务逻辑不需要在父shell中执行,直接把使用updates的代码放到后台循环内:
#!/bin/bash while true; do updates=$(ping -q -c 1 -W 1 ping.eu > /dev/null && yay -Qu | wc -l) # 在这里直接处理updates,比如写入日志、发送通知 echo "$(date '+%Y-%m-%d %H:%M:%S') 待更新包数:$updates" >> /var/log/update_check.log # notify-send "系统更新提醒" "共有 $updates 个包可更新" sleep 600 done &
方案3:用命名管道实现进程通信(适合复杂场景)
通过命名管道(FIFO)实现子shell与父shell的实时数据传递:
#!/bin/bash # 创建命名管道 FIFO="/tmp/update_fifo" mkfifo "$FIFO" # 后台循环写入更新数到管道 while true; do updates=$(ping -q -c 1 -W 1 ping.eu > /dev/null && yay -Qu | wc -l) echo "$updates" > "$FIFO" sleep 600 done & # 父shell读取管道内容并处理 while read -r updates < "$FIFO"; do echo "收到更新数:$updates" # 在这里添加你的业务逻辑 done # 脚本退出时清理管道 trap 'rm -f "$FIFO"' EXIT
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

