【问题标题】:Why a command fails when executing from inside a script? [duplicate]为什么从脚本内部执行命令会失败? [复制]
【发布时间】:2020-04-01 03:52:25
【问题描述】:

我正在尝试通过 bash 脚本将远程文件夹中的所有内容复制到我的本地计算机:

    #!/usr/bin/env bash

    REMOTE_SOURCE="/absolute/path/to/source/data"
    TARGET="/absolute/local/path/to/target"
    SSH="ssh myuser@myhost"

    cd $TARGET
    echo $PWD

    TRANSFER="$SSH -- 'cd $REMOTE_SOURCE; tar cz ./' | tar xz"

    echo $TRANSFER
    $TRANSFER

运行脚本,传输命令存储在变量中失败:

bash: cd /absolute/path/to/source/data; tar cz ./: 没有这样的文件或目录

虽然从echo $TRANSFER 复制输出并直接运行到 shell 时它可以正常工作:

ssh myuser@myhost -- 'cd /absolute/path/to/source/data; tar cz ./' | tar xz

注意:

  • 远程文件夹当然存在,因此报告的错误令人困惑,无法帮助我理解要修复的内容。
  • 我收到错误消息,同时删除了 tar cz ./ 部分并只留下了 cd 命令。

更新:

删除'-quoting 使命令生效。

但是那么如何将ssh 结果通过管道传输到tar xz

解决办法:

脚本应尽可能少引用,避免过多的变量扩展魔法:

echo "$SSH -- \"cd $REMOTE_DATA; tar cz ./  \" | tar xz"
$SSH -- "cd $REMOTE_DATA; tar cz ./" | tar xz

【问题讨论】:

标签: linux bash shell ssh


【解决方案1】:

Bash 支持数组,但您会遇到引用问题(并且完全不带引号地运行会导致意外的混乱)。

让我们更新它以使用数组:

#!/usr/bin/env bash

REMOTE_SOURCE="/absolute/path/to/source/data"
TARGET="/absolute/local/path/to/target"
SSH="myuser@myhost"

cd "$TARGET"
echo "$PWD"

TRANSFER=(ssh "$SSH" -- "cd $REMOTE_SOURCE; tar cz ./")
AFTER=(tar xz)

echo "${TRANSFER[@]} | ${AFTER[@]}"
"${TRANSFER[@]}" | "${AFTER[@]}"

这需要一个额外的变量,因为你不能把 | 放在那里而不引用它,这会阻止它按照你的意愿行事。

【讨论】:

  • 对在保留的全大写命名空间中使用变量有点抱怨
  • 此代码也将受益于将; 更改为&&,因此如果cd 跟随失败,tar 不会在错误的目录中运行。倒数第二行 echo 绝不保证写入的输出与它后面的复合命令管道所做的事情相同;您需要使用生成 eval-safe 引用的东西来获得该保证。就我个人而言,我倾向于使用set -x 进行调试。
  • @CharlesDuffy——我同意。我认为我已经做出了足够的改变,并希望尽可能多地保留原始问题。
猜你喜欢
  • 2012-07-21
  • 2015-09-01
  • 2013-12-03
  • 2021-01-20
  • 1970-01-01
  • 1970-01-01
  • 2018-08-20
  • 2019-05-28
  • 1970-01-01
相关资源
最近更新 更多