微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

转换BASH脚本以在SH上运行通过BusyBox

如何解决转换BASH脚本以在SH上运行通过BusyBox

我有一个运行FreshTomato最新版本的Asus路由器-BusyBox随附。

我需要运行一个考虑到BASH的脚本-它是this script的改编版-但由于以下错误而无法运行:0

使用shellcheck.net检查脚本会产生以下错误

 line 41: Syntax error: bad substitution

以下是引起问题的行:

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_*}构造都是BASH特定的,并且不兼容POSIX,因此不可能直接进行“ bash到sh”的代码转换

我试图创建一个指向${!optionvarname}的{​​{1}}符号链接,但是出现了/bin/bash错误

那么,如何使此脚本在路由器上运行?我只看到两个选项,但我无法弄清楚如何实现:

  1. 使BusyBox将该脚本解释为BASH而不是SH-我可以为此使用特定的shebang吗?
    • 似乎是最快的选择,但前提是BusyBox具有“完全”的BASH实现
  2. 更改脚本代码以不使用BASH细节。
    • 这比较安全,但是由于SH没有“以X开头的al变量”,我该怎么办?

解决方法

如何让此脚本在路由器上运行?

那么容易,要么:

  • 在路由器上安装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可能会遇到更多问题,因此您可能首先要考虑其他方法,例如更换路由器)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。