我没有扩展我传入的参数,我遇到了一些麻烦。
我的shell脚本(scp_run.ksh)在具有3台服务器的环境中运行 - 该脚本的目标是将文件从服务器上的存档文件夹移动到运行此脚本的服务器的存档文件夹。
我已在类似./scp_run.ksh /server/path/to/archive
的示例中对此进行了测试,并且shell脚本成功查看服务器,scp是每个/ server / path / to / archive中找到的文件,并将它们移动到当前服务器/服务器/路径/到/存档
这里的事情变得凌乱:我不想使用硬编码路径,而是使用像$ 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(或者我传递的任何env varible)。那么正确执行/评估
/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
答案 0 :(得分: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