shell 远程脚本无法识别屏幕中主机上设置的环境变量

c8ib6hqw  于 2023-02-19  发布在  Shell
关注(0)|答案(1)|浏览(299)

我有一个bash脚本,它在远程计算机的屏幕上运行另一个脚本,环境变量GITLAB_CI_TOKEN在主机上设置,并且定义正确,但是远程计算机上的脚本configure.sh在执行时告知此环境变量为空,即使它与脚本定义在同一行上...
下面是我正在使用的命令:

ssh -o "StrictHostKeyChecking=accept-new" "${COMPUTERS_IPS[i]}" \
    screen -S "deploy_${COMPUTERS_IPS[i]}" -dm " \
        GITLAB_CI_TOKEN=${GITLAB_CI_TOKEN} \
        bash \"${REMOTE_FOLDER}/configure.sh\" \"${REMOTE_FOLDER}\" > ${LOG_FILE} 2>&1;
    "

此外,日志不会写入LOG_FILE,而是显示在屏幕的控制台上。过去两天我一直在为这件事抓狂......任何帮助或指导都将非常感谢:)

1dkrff03

1dkrff031#

为什么GITLAB_CI_TOKEN为“空”:
通过ssh向远程主机传递命令与通过eval运行命令非常相似。例如,在您的示例中,第一次求值时转义的换行符在后续求值时变为 unescaped 换行符。考虑这个非常简单的程序,名为args(将其放在bin或demo路径上的其他位置):

#!/bin/bash
for arg ; do
  echo "|$arg|"
done

这两种使用情形:

args "\
Hello \
World" 
# prints: 
# |Hello World|

ssh host args "\
Hello \
World"
# prints:
# |Hello|
# |World|

正如你所看到的,当我们通过ssh运行这个程序时,我们试图转义的换行符将我们的数据分割成两个单独的行,尽管我们试图将它们都放在一行中。这意味着你对GITLAB_CI_TOKEN的赋值只是一个常规的shell变量,而不是bash命令的作用域环境变量。作用域环境变量要求声明和命令发生在同一行中。
最简单的方法可能是使用export GITLAB_CI_TOKEN=${GITLAB_CI_TOKEN}显式导出变量。
出于类似的原因,命令的输出将显示在屏幕上,而不是日志文件中,因为screen -dm "commands >output"的外引号在第一次求值时被去掉,然后远程主机解析screen -dm commands >output,并将输出重定向分配给screen而不是commands。是screen程序将自己的输出写入日志文件。
要向远程主机发送复杂的命令,您可能需要使用printf %q之类的工具,它可以生成转义输出,适合在类似eval的上下文中进行安全评估。

相关问题