2017-02-22 147 views
0

我遇到一些麻烦不扩大参数我传递的价值。使用远程环境变量在SCP路径

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

我已经在./scp_run.ksh /server/path/to/archive这样的例子中测试了这个,shell脚本成功地在服务器上查找,scp是在每个/ server/path/to/archive中找到的文件,并将它们移动到当前servers/server/path/to /档案

这里是事情变得麻烦的地方:我想不使用硬编码路径,而是像$ 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 /归档等调用SCP时命令它正在寻找从环境变量在当前节点上设置的文件夹路径不在它正在寻找scp从。

例如:从服务器1运行这个我看到它正在执行SCP命令服务器2像/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到$服务器并且echo $ {SOURCE_DIR},但是我无法让$ SOURCE_DIR不立即评估$ SERVER_ARCHIVE。

我认为这会是这样的remote_var=$(ssh [email protected]_2_name 'printf $SOURCE_DIR'),但我觉得在我的当前设置此$ SOURCE_DIR已经评价/ reports_1 /归档和未设置为$ SERVER_ARCHIVE

+0

我们需要一组简单的代码,我们可以复制/粘贴以进行测试。我没有看到你已经在发布的代码中的任何地方为SERVER_ARCHIVE(或使用该变量)设置了一个值。你是说远程服务器应该提供这个值吗?(只是)每个服务器都有不同的值,这取决于'$ {server}'的值。 (为什么不通过代码使用小写变量,大写由Posix保留用于系统变量)。请更新你的Q,而不是在评论中回复。祝你好运。 – shellter

+0

这不是一个真正的ksh问题,这是一个scp问题。您没有传递变量,而是将*引用传递给*变量。 –

+0

顺便说一句,对于sftp来说,这是明确且有意不可能的设计 - 具有完全独立的子系统处理sftp的价值的一部分是该子系统只能访问有限的显式操作集,并且该操作集不包括扩展或评估环境变量。相比之下,scp更像是一个专门的软件,没有详细说明,它可以利用远程shell,所以我不能说如果没有深入实施,这是不可能的。然而,就本质而言,任何修复*都将被执行指定。 –

回答

1

与SFTP,SCP主要是实现定义 - - 意味着没有正式的协议文档或规范能够以前向兼容的方式确定什么和不支持。

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

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

# this only evaluates SOURCE_DIR on the remote end due to the outer single-quotes 
remote_var=$(ssh [email protected]_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 -- "[email protected]" 
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 
相关问题