【问题标题】:Use remote environment variable's value in scp path在 scp 路径中使用远程环境变量的值
【发布时间】:2017-07-13 00:25:40
【问题描述】:

我在不扩展传入的参数时遇到了一些问题。

我的 shell 脚本 (scp_run.ksh) 在具有 3 个服务器的环境中运行 - 脚本的目标是将文件从服务器上的存档文件夹移动到运行此脚本的服务器的存档文件夹中。

我已经在./scp_run.ksh /server/path/to/archive 之类的示例中对此进行了测试,并且 shell 脚本成功地查看了服务器和 scp 在每个 /server/path/to/archive 中找到的文件并将它们移动到当前服务器 /server/path/到/存档

这就是事情变得混乱的地方:我不想使用硬编码的路径,而是使用像 $SERVER_ARCHIVE 这样的环境变量。这个环境变量是在每台服务器上设置的——尽管对于每台服务器来说,它的路径略有不同(我无法控制)。 例如。

Server 1 $SERVER_ARCHIVE= /reports_1/archive
Server 2 $SERVER_ARCHIVE= /reports_2/archive
Server 3 $SERVER_ARCHIVE= /reports_3/archive

当我像 ./scp_run.ksh $SERVER_ARCHIVE 这样调用我的脚本时,它似乎会立即将参数评估为 /reports_x/archive,因此在调用 SCP 命令时,它正在寻找从当前节点上的环境变量设置的文件夹路径,而不是在一个它正在寻找 scp 的来源。

例如:从服务器 1 运行它我看到它正在为服务器 2 执行 scp 命令,例如 /usr/bin/scp -p server_2_name:/reports_1/archive/my_file.dat /reports_1/archive/.

SOURCE_DIR=${1}
...
for server in "${prod_servers_array[@]}"
do
   if [[ ${server} != ${currserver} ]]
   then 
        /usr/bin/scp -p ${server}:${SOURCE_DIR}/${SOURCE_FILES} ${SOURCE_DIR}/.
    fi
done

我希望该 SCP 命令能够从实际服务器实际传递/获取 $SERVER_ARCHIVE(或我传递的任何环境变量)以使用。那么正确的执行/评估

/usr/bin/scp -p ${server}:${SOURCE_DIR}/${SOURCE_FILES} ${SOURCE_DIR}/.

在服务器 1 上运行并查看服务器 2 时的样子

/usr/bin/scp -p server_2_name:/reports_2/archive/my_file.dat /reports_1/archive/.

有没有办法将 $SERVER_ARCHIVE 作为参数传递给 ${1} 并且它不会评估为完整路径?

我的想法是,在我的 scp 命令之前,我需要通过 SSH 连接到 $server 并回显 ${SOURCE_DIR} 但我无法让 $SOURCE_DIR 不立即评估 $SERVER_ARCHIVE。

我认为它类似于remote_var=$(ssh myuser@server_2_name 'printf $SOURCE_DIR'),但我认为在我当前的设置中,这个 $SOURCE_DIR 已经被评估为 /reports_1/archive 而不是设置为 $SERVER_ARCHIVE

【问题讨论】:

  • 我们需要一组简单的代码,我们可以复制/粘贴来进行测试。我没有看到您在发布的代码中的任何位置都为 SERVER_ARCHIVE 设置了值(或使用该变量)。您是说远程服务器应该提供该值还是(只是)每个服务器将具有不同的值,具体取决于${server} 的值。 (为什么不通过您的代码全部使用小写变量。Posix 为系统变量保留大写字母)。请更新您的 Q,而不是在 cmets 中回复。祝您好运。
  • 这不是真正的 ksh 问题,而是 scp 问题。您不是在传递变量,而是传递对变量的引用
  • 顺便说一句,对于 sftp,这在设计上是明确和有意不可能的——拥有一个完全独立的子系统处理 sftp 的部分价值在于该子系统只能访问一组有限的显式操作,并且该组操作不包括扩展或评估环境变量。相比之下, scp 更像是一个... ad-hoc 软件,没有那么明确,它确实利用了远程 shell,所以我不能说没有这是不可能的深入实施。但是,本质上,任何修复都将由实现指定。

标签: shell ssh environment-variables


【解决方案1】:

与 SFTP 不同,SCP 在很大程度上是由实现定义的——这意味着没有正式的协议文档或规范可以确定以向前兼容的方式支持和不支持什么。

如果我们试图写一些将来不会崩溃的东西,那么不依赖它会更安全。

你的一个尝试是朝着正确的方向:

# this only evaluates SOURCE_DIR on the remote end due to the outer single-quotes
remote_var=$(ssh myuser@server_2_name 'printf "%s\n" "$SOURCE_DIR"')

另一种方法是根本不使用 SCP,而是使用 SSH 运行您自己的代码进行传输:

source_dir=$1
source_files=( a.txt b.txt ) # set this yourself
source_files_q=$(printf '%q ' "${source_files[@]}")

copy_remote_files() {
  local server=$1
  # important: unlike a <<EOF heredoc, <<'EOF' prevents any local expansion
  ssh "$server" "ksh -s $source_files_q" <<'EOF'
    # source dotfiles, to ensure we pick up SOURCE_DIR
    # modify for your actual dotfiles
    for f in ~/.profile ~/.rc; do . "$f"; done
    [[ $SOURCE_DIR ]] || { echo 'Unable to find remote $SOURCE_DIR' >&2; exit 1; }

    cd "$SOURCE_DIR" || { echo "Unable to cd to $SOURCE_DIR" >&2; exit 1; }

    exec tar -c -- "$@"
EOF
}

cd "$SOURCE_DIR" || { echo "Unable to cd to local SOURCE_DIR" >&2; exit 1; }
for server in "${prod_servers_array[@]}"; do
  if [[ ${server} != "${currserver}" ]]; then
    copy_remote_files "$server" | tar -x
  fi
done

【讨论】:

    猜你喜欢
    • 2011-05-19
    • 1970-01-01
    • 2015-05-14
    • 2017-01-23
    • 1970-01-01
    • 2016-07-22
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多