为参数化变量创建shell脚本[重复]

Posted

技术标签:

【中文标题】为参数化变量创建shell脚本[重复]【英文标题】:create shell script for parameterized variable [duplicate] 【发布时间】:2020-05-20 13:27:15 【问题描述】:

我对 shell 脚本非常陌生,我想创建和运行 shell 脚本。

我想在 simu 和 prod 这两个不同的环境中运行我的 java 程序。

如果我在 simu 环境中运行程序,则执行 SIMU_RUN,否则执行 PROD_RUN。

例如,我有两个目录,其中文件放置在 /data/etl-simu/in//data/etl-prod/in/ 中,正如您在从目录名称读取文件时看到的那样,我可以从 SIMU_PATH 或 @ 识别环境是 simu 还是 prod 987654326@变量。

我不确定编写这样的 shell 脚本并执行它是否容易。

如果我只是创建普通的 shell 脚本并将完整的 SIMU_RUNPROD_RUN 路径放入该 shell 脚本并在相应的环境中执行它,那么它将运行良好。 但是由于我有两个环境,所以我想让这个 shell 脚本灵活,而不是为 simu 和 prod 创建两个单独的 shell 脚本

#!/bin/sh

SIMU_RUN="cd /opt/env/import/import/current; java -Dlog4j.configurationFile=/opt/import/config/logging/log4j2_Importer.xml -Djava.security.egd=file:///dev/urandom -classpath /opt/runner/lib/*:/opt/import/lib/* runner.Application --config /opt/import/config/import.simu.properties --workflow import --inputDir /data/etl-simu/in"
PROD_RUN="cd /opt/import/import/current; java -Dlog4j.configurationFile=/opt/import/config/logging/log4j2_Importer.xml -Djava.security.egd=file:///dev/urandom -classpath /opt/runner/lib/*:/opt/import/lib/* runner.Application --config /opt/import/config/import.prod.properties --workflow import --inputDir /data/etl-prod/in"

SIMU_PATH="/data/etl-simu/in"
PROD_PATH="/data/etl-prod/in"

MODE=$1

if [ "$MODE" = SIMU_PATH ]; then

#execute SIMU_RUN

else
  #execute PROD_RUN


fi

exit $EXIT

【问题讨论】:

见BashFAQ #50,这正是这个问题的重点(并给出了与下面格伦杰克曼的正确答案相同的建议)。 ...在阅读链接的副本时,我强烈建议忽略已接受的答案(如其 cmets 和 BashFAQ #48 中所述,它给出的建议对安全性和正确性均有害)。 嗨,查尔斯,我仍然在 glenn 的答案中遇到错误,因为它是无效模式。我不知道为什么这个问题被关闭了,因为它看起来并不重复 原因是相同的潜在错误具有相同的潜在解决方案集,即使表现形式不同。你读过 BashFAQ #50 链接了吗? ...要清楚,您的问题是将命令放入变量而不是参数化的原因是 这是您所犯的错误。您在向我们展示的代码中没有犯任何关于参数化的错误,您只是向我们展示了试图将代码存储为数据的代码;因此,您会被标记为问题的重复,其中错误是将代码存储为数据(而不是通过使用函数将代码存储为代码)。 【参考方案1】:

不要将代码存储在变量中,使用函数:

#!/bin/sh

run() 
    cd /opt/import/import/current &&
    java -Dlog4j.configurationFile=/opt/import/config/logging/log4j2_Importer.xml \
         -Djava.security.egd=file:///dev/urandom \
         -classpath /opt/runner/lib/*:/opt/import/lib/* \
         runner.Application \
         --config "/opt/import/config/import.$mode.properties" \
         --workflow import \
         --inputDir "/data/etl-$mode/in"


mode=$1

case "$mode" in
    prod|simu) 
        run 
        ;;
    *)  echo "error: invalid mode" >&2
        exit 1
        ;;
esac

注意事项:

改掉使用 ALLCAPS 变量名的习惯,保留那些由 s​​hell 保留的名称。有一天你会写PATH=something,然后写wonder why your script is broken。 我已经用续行分解了很长的行:这将使可维护性变得更加容易。

如果您将其设为 bash 脚本,那么 IMO 会更好:

run() 
    local -a java_options=(
        -Dlog4j.configurationFile=/opt/import/config/logging/log4j2_Importer.xml
        -Djava.security.egd=file:///dev/urandom
        -classpath "/opt/runner/lib/*:/opt/import/lib/*"
    )
    local app="runner.Application"
    local -a app_options=(
         --config "/opt/import/config/import.$mode.properties"
         --workflow import
         --inputDir "/data/etl-$mode/in"
    )

    cd /opt/import/import/current &&
    java "$java_options[@]" $app "$app_options[@]"

【讨论】:

嗨,格伦,我正在尝试您的第一个脚本,但它缺少一小部分..我们还需要处理 dbimport.simu.properties 并在此处相应地放置 simu 或 prod...这非常重要,因为这将确定数据库属性...是否可以像替换路径一样在那里放置参数化变量? @Andrew,代码 确实simu_pathprod_path 识别为参数,并将其作为 $1 传递,因此它被替换为 app_options . @Andrew,.../data/etl-simu/in/data/etl-prod/in 在您的两个硬编码命令中的区别是唯一看起来不像是拼写错误的区别。如果这是不真实的,请明确说明。 @Andrew 我已经更新了答案:将“prod”或“simu”传递给脚本,“run”函数在 2 个地方使用该变量。这使代码更简洁。 是的,谢谢 :) 我只需要在运行脚本而不是路径时在参数中传递“prod”或“simu”即可

以上是关于为参数化变量创建shell脚本[重复]的主要内容,如果未能解决你的问题,请参考以下文章

shell特殊变量

shell脚本函数参数/参数[重复]

Shell编程——位置参数变量

如何在shell脚本中使用'($ var)'作为参数[重复]

Shell脚本连接创建数据库

在Ubuntu下编写shell脚本读取文件