【问题标题】:BASH - Read in config file with multiple instances of the same "variable"BASH - 读取具有相同“变量”的多个实例的配置文件
【发布时间】:2011-03-25 12:42:48
【问题描述】:

我正在尝试读取配置文件,然后将配置的“部分”放入 bash 脚本中的数组中,然后运行一个命令,然后再次重复配置,并继续执行直到配置文件结束。

这是一个示例配置文件:

端口="5000" 用户=“没人” 路径=“1” 选项="" 端口="5001" 用户=“没人” 路径=“1” 选项="" 端口="5002" 用户=“没人” 路径=“1” 选项=""

我希望 bash 脚本读取第一个“部分”,将其带入脚本,然后运行以下命令:
scriptname -p $PORT -u $USER -P $PATH -o $OPTIONS

但是,我希望它根据配置文件中有多少“节”来获取“节”的每次迭代,并使用相应的配置设置运行命令并将其应用于最终命令.因此,如果要从上面读取配置文件,输出将是:

脚本名 -p $PORT -u $USER -P $PATH -o $OPTIONS 脚本名 -p $PORT -u $USER -P $PATH -o $OPTIONS 脚本名 -p $PORT -u $USER -P $PATH -o $OPTIONS

又是这样的:

脚本名 -p 5000 -u 没人 -P 1 -o "" 脚本名 -p 5001 -u 没人 -P 1 -o "" 脚本名 -p 5002 -u 没人 -P 1 -o ""

提前致谢。

【问题讨论】:

  • 由于这看起来像是您自己设计的迷你语言,请帮自己一个忙,用空格以外的其他东西来划分逻辑块。
  • 现在,空白块将不得不做。这基本上是对另一个应用程序的修复——它是临时的,但需要快速修复。我必须将它实现到一个初始化脚本中。配置文件需要简单。

标签: linux arrays bash configuration-files


【解决方案1】:
#!/bin/bash

if [[ $# -ne 1 ]]; then
    echo "Usage: $0 script.cfg" >&2
    exit 1
fi

function runscript() {
    scriptname -p $PORT -u $USER -P $PATH -o $OPTIONS
}

while read LINE; do
    if [[ -n $LINE ]]; then
        declare "$LINE"
    else
        runscript
    fi
done < "$1"

runscript

如果你想同时在后台运行脚本,试试这个:

function runscript() {
    nohup scriptname -p $PORT -u $USER -P $PATH -o $OPTIONS &> /dev/null &
}

最后的&amp; 使它们在后台运行,nohup 确保它们在 shell 退出时不会被杀死。最终效果是将脚本变成守护进程,因此无论父脚本发生什么情况,它们都会在后台连续运行。

【讨论】:

  • 我实际上是在尝试将其实现到启动脚本中。它可以工作,但是,它只运行 scriptname 节的一个实例。我将 while 循环更改为从配置文件中读取。就像我说的,我的模组可以工作,但它只启动一个程序,而不是其他程序。
  • 你的意思是它只调用脚本一次然后退出,还是因为脚本没有退出而调用脚本并阻塞?如果是后者,我已经编辑了我的答案以适应。如果是前者,我需要更多关于什么不工作的信息——当我用你的示例配置文件测试它时,脚本工作。
  • 您应该将eval 更改为declaredeclare 避免了eval 的安全风险(即使在这种情况下输入文件可能是安全的,改变它是一个好习惯)。你需要稍微改变一下逻辑。类似[[ -z $LINE ]] &amp;&amp; runscript || declare "$LINE"
  • 如果你使用disown,则不需要nohup
【解决方案2】:

假设各节之间只有一个空行:

cat <yourfile> | while read ; do
    if [ -z "$REPLY" ] ; then
        scriptname -p $PORT -u $USER -P $PATH -o "$OPTIONS" 
    else
        eval "$REPLY" # NOTE: eval is evil
    fi
done

【讨论】:

  • 这就是为什么您应该将eval 更改为declare - 它有效且更安全。哦,cat 是不必要的。使用done &lt; filename。如果不出意外,它会保存对外部可执行文件的调用。
  • 感谢您的声明,我必须记住这一点。 RE:猫——旧习惯很难改掉:)。
【解决方案3】:
#!/bin/bash

awk 'BEGIN{ FS="\n";RS=""}
{
  for(i=1;i<=NF;i++){
   gsub(/.[^=]*=|\042/,"",$i)
  }
  print "scriptname -p "$1" -u "$2" -P "$3" -o "$4
}' file | bash

【讨论】:

  • 这是一个不错的解决方案。实际上,您可以将 print 替换为 system 并去掉 | bash
  • 是的。这是另一种方式,前提是它不多。如果它很多,管道到 xargs 和 bash 会比调用 system() 更好。
猜你喜欢
  • 2018-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-31
  • 2022-10-13
相关资源
最近更新 更多