You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Bash脚本中将FC磁带驱动器路径每行输出存入独立变量的报错问题

问题分析

你遇到了两个核心问题:一是动态变量赋值的语法错误,二是管道创建子shell导致变量无法在循环外访问。

先看语法错误:${!var} 是bash中用来读取间接变量值的语法(比如如果var=foo,${!var}就等于$foo),但不能直接用它来赋值。你写的${!var}=$(...)会被bash解析成执行=/dev/st0这个“命令”,自然就报错了。

另外,你用管道| while read...的写法,while循环是运行在子shell中的,哪怕赋值成功,循环结束后父shell也看不到这些变量,这也是一个容易忽略的隐藏坑。


修复方案1:正确的动态变量赋值(解决语法+子shell问题)

我们可以用declare来实现动态变量赋值,同时用**进程替换(process substitution)**代替管道,避免子shell:

#!/bin/bash
i=0
# 用< <(command)让while在当前shell执行,避免子shell
while read line ; do
    var="path_tape$i"
    # 使用declare完成动态变量赋值
    declare "$var=$(echo "$line" | awk '{print $4}')"
    ((i++))
done < <(/usr/bin/lsscsi --transport | grep fc: | grep tape)

# 测试变量是否可用
echo "第一个驱动器路径:$path_tape0"
echo "第二个驱动器路径:$path_tape1"

更推荐的方案2:使用bash数组(更简洁易维护)

其实处理多个同类路径时,bash数组比动态命名的变量更合适——不需要手动计数,遍历和访问都更方便:

#!/bin/bash
# 用mapfile直接把命令的每行输出存入数组
mapfile -t drive_array < <(/usr/bin/lsscsi --transport | grep fc: | grep tape | awk '{print $4}')

# 访问单个元素
echo "第一个驱动器:${drive_array[0]}"
echo "第二个驱动器:${drive_array[1]}"

# 遍历所有驱动器
echo "所有找到的磁带驱动器:"
for drive in "${drive_array[@]}"; do
    echo "- $drive"
done

mapfile -t会把命令输出的每一行(自动去掉换行符)依次存入数组drive_array,索引从0开始。如果你的bash版本较旧(低于4.0),可以用read循环手动填充数组:

#!/bin/bash
drive_array=()
while read -r path; do
    drive_array+=("$path")
done < <(/usr/bin/lsscsi --transport | grep fc: | grep tape | awk '{print $4}')

额外优化:简化命令链

你原来的命令链lsscsi --transport | grep fc: | grep tape | awk...可以简化成单个awk命令,减少管道开销:

/usr/bin/lsscsi --transport | awk '/fc:/ && /tape/ {print $4}'

把这个替换到上面的脚本里,会更高效。

内容的提问来源于stack exchange,提问作者Yves C.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:51:03