【问题标题】:Multiline ssh command with for带有 for 的多行 ssh 命令
【发布时间】:2020-09-24 12:21:46
【问题描述】:

我有一个通过ssh 执行命令的bash 脚本。

FILENAMES=(
  "export_production_20200604.tgz"
  "export_production_log_20200604.tgz"
  "export_production_session_20200604.tgz"
  "export_production_view_20200604.tgz"
)

sshpass -p $PASSWORD ssh -T $LOGIN@$IP '/bin/bash' <<EOF
  for f in "${FILENAMES[@]}"; do
    echo Untar "$f"
  done
EOF

问题是当我执行脚本时,$f 是空的。

我在网上查看了多个解决方案来执行多个命令,但没有一个可行:

link 1

link 2

...

你能帮我弄清楚吗?


注意

执行:

for f in "${FILENAMES[@]}"; do
    echo Untar "$f"
done

&lt;&lt;EOFEOF之外,工作


在本地:

bash 4.4.20(1)-发布

远程:

bash 4.2.46(2)-发布



编辑:技巧

时间紧迫,别无选择,我实现了@hads0m提供的解决方案,希望它可以帮助有同样问题的开发人员:

# $1 the command
function executeRemoteCommand() {
    sshpass -p $DB_PASSWORD ssh $DB_LOGIN@$DB_SERVER_IP $1
}

for i in "${!FILENAMES[@]}"; do
    f=$FILENAMES[$i]

    DB_NAME=$DB_NAMES[$i]

    # Untar the file
    executeRemoteCommand '/usr/bin/tar xzvf '$MONGODB_DATA_PATH'/'$TMP_DIRECTORY'/'$f' --strip-components=1'

    # Delete the tar
    executeRemoteCommand 'rm -f '$MONGODB_DATA_PATH'/'$TMP_DIRECTORY'/'$f''

    # Restore the database
    executeRemoteCommand 'mongorestore --host 127.0.0.1:'$DB_PORT' --username "'$MONGODB_USER'" --password "'$MONGODB_PASSWORD'" --authenticationDatabase admin --gzip "'$DB_NAME'" --db "'$DB_NAME'"'
done

【问题讨论】:

    标签: bash ssh heredoc


    【解决方案1】:

    您需要转义 $ 符号以避免它在本地扩展并将数组传递给远程。

    这可能是你想要的:

    #!/usr/bin/env bash
    
    FILENAMES=(
          "export_production_20200604.tgz"
          "export_production_log_20200604.tgz"
          "export_production_session_20200604.tgz"
          "export_production_view_20200604.tgz"
    )
    
    sshpass -p $PASSWORD ssh -T $LOGIN@$IP '/bin/bash' <<EOF
      $(declare -p FILENAMES)                                                                       
      for f in "\${FILENAMES[@]}"; do                                                               
        echo Untar "\$f"                                                                            
      done                                                                                          
    EOF
    

    【讨论】:

    • 您确实需要转义$FILENAMES。试一试你就会发现。
    • 除了你的答案:如果你想声明多个变量,语法是:$(declare -p FILENAMES MONGODB_DATA_PATH TMP_DIRECTORY DB_PORT MONGODB_USER MONGODB_PASSWORD FILE_EXT)
    • 是的,我愿意 :) 我的脚本很长。我只是用一个小样本指出了问题的可读性的主要问题。
    • 在这种情况下,也许可以尝试找到一种不需要引用的方式,因为过多的引用会使代码难以阅读。
    【解决方案2】:

    尝试像这样运行它:

    for f in "${FILENAMES[@]}"; do
      sshpass -p $PASSWORD ssh -T $LOGIN@$IP echo Untar "$f"
    done
    

    另外,不要忘记将#!/bin/bash 添加到脚本的第一行。

    【讨论】:

    • 我展示的代码是我脚本特定部分的摘录。我已经正确设置了shebang。关于您的解决方案,我宁愿打开一个 ssh 连接而不是 X。
    • 暂时没有其他解决方案,我使用了您的语法。仍在等待允许我一次执行多个远程命令的答案。感谢您的意见。
    猜你喜欢
    • 2019-11-14
    • 2012-11-11
    • 1970-01-01
    • 2015-01-26
    • 2015-11-11
    • 2017-05-11
    • 1970-01-01
    • 2019-06-24
    • 1970-01-01
    相关资源
    最近更新 更多