我有一个华硕路由器,运行的是BusyBox附带的最新版本的FreshTomato。
我需要运行一个考虑到BASH的脚本——它是对这个脚本的改编——但它无法运行,并出现以下错误:line 41: syntax error: bad substitution
使用shellcheck.net检查脚本会产生以下错误:
Line 41:
for optionvarname in ${!foreign_option_*} ; do
^-- SC3053: In POSIX sh, indirect expansion is undefined.
^-- SC3056: In POSIX sh, name matching prefixes are undefined.
Line 42:
option="${!optionvarname}"
^-- SC3053: In POSIX sh, indirect expansion is undefined.
这些是造成问题的线路:
for optionvarname in ${!foreign_option_*} ; do # line 41
option="${!optionvarname}" # line 42
# do some stuff with $option...
done
如果我的理解是正确的,那么原始脚本只是对名称以foreign_option_
开头的所有变量执行一些操作
然而,就我所能确定的,${!foreign_option_*}
和${!optionvarname}
构建体都是BASH特异性的,并且不符合POSIX,因此不存在直接的";bash to sh";代码转换是可能的。
我试图创建一个指向busybox
的/bin/bash
符号链接,但我得到了Read-only file system
错误。
那么,我怎样才能让这个脚本在我的路由器上运行呢?我只看到两个选项,但我不知道如何实现:
- 让BusyBox将脚本解释为BASH而不是SH-我可以为此使用特定的shebang吗?
- 看起来是最快的选项,但前提是BusyBox有一个";完整的";BASH的实施
- 将脚本代码更改为不使用BASH细节。
- 这更安全,但由于没有"收集以X"开始的所有变量;对于SH,我该怎么做
如何让这个脚本在我的路由器上运行?
也很简单:
- 在路由器上安装bash或
- 将脚本移植到busybox/posix兼容的shell
让BusyBox将脚本解释为BASH而不是SH-我可以为此使用特定的shebang吗?
这没有道理。Busybox带有ash
shell解释器,bash就是bash。Bash可以解释Bash扩展,而ash不能解释它们。你不能"使busybox解释bash"-汽车不会飞,飞机就是这样。如果你想让汽车飞起来,你就给它加上翅膀,让它飞得更快。Make BusyBox interpret the script as BASH instead of SH
的答案是:修补busybox并在其中实现所有bash扩展
Shebang用于在不同的解释器下运行文件。使用#!/bin/bash
将调用bash
,这将与任何与busybox相关的内容无关,并且busybox不会参与其中
我该怎么做?
决定一个不切实际的最大值,对名为foreign_option_{1...some_max}
的变量进行迭代,对于每个变量,查看它是否已设置,如果已设置,则协同脚本。
for i in $(seq 100); do
optionvarname="foreign_option_${i}"
# https://stackoverflow.com/questions/3601515/how-to-check-if-a-variable-is-set-in-bash
if eval "[ -z "${${optionvarname}+x}" ]"; then continue; fi;
如果有足够的运气,也许您可以使用set
输出。如果任何变量包含的值为换行符+与正则表达式匹配的字符串,则以下操作将失败:
for optionvarname in $(set | grep -o '^foreign_option_[0-9]+=' | sed 's/=//'); then
eval
:可以很容易地替代间接扩展
eval "option="$${optionvarname}""
如果你真的不能在路由器上安装Bash,这里有一个可能的解决方法,它似乎对我在Qnap-NAS:上的BusyBox中有效
foreign_option_one=1
foreign_option_two=2
for x in one two; do
opt_var=foreign_option_${x}
eval "opt_value=$$opt_var"
echo "$opt_var = $opt_value"
done
(但在将Bash脚本移动到busybox时,您可能会遇到更多问题,因此您可能需要首先考虑替代方案,如更换路由器(