linux - 从原始数组创建一个数组,但基于代码运行的位置?

标签 linux bash shell

我在 machines 数组中有三台机器(每台机器位于不同的数据中心)。

  • 如果我的 shell 脚本在 abc 数据中心上运行,那么我想从 machineA.abc.host.com 中获取文件,这将是我的本地框。我会选择另外两个盒子作为远程服务器来复制文件,以防本地盒子出现故障。
  • 如果我的 shell 脚本在 def 数据中心上运行,那么我想从 machineB.def.host.com 中获取文件,这将是我的本地框。我会选择另外两个盒子作为远程服务器来复制文件,以防本地盒子出现故障。
  • 如果我的 shell 脚本在 pqr 数据中心上运行,那么我想从 machineC.pqr.host.com 中获取文件,这将是我的本地框。我会选择另外两个盒子作为远程服务器来复制文件,以防本地盒子出现故障。

下面是我的脚本,但我相信它可以用更好的方式完成,而不是使用三个不同的变量,然后用 or 分隔三个 scp 状态:

machines=(machineA.abc.host machineB.def.host.com machineC.pqr.host.com)

case $(hostname -f) in
    *abc.host.com)
        local_server=("${machines[0]}")
        primary_remote==("${machines[1]}")
        secondary_remote==("${machines[2]}")
        ;;
    *def.host.com)
        local_server=("${machines[1]}")
        primary_remote==("${machines[2]}")
        secondary_remote==("${machines[0]}")
        ;;
    *pqr.host.com)
        local_server=("${machines[2]}")
        primary_remote==("${machines[0]}")
        secondary_remote==("${machines[1]}")        
        ;;
    *) echo "unknown host: $(hostname -f), exiting." >&2 && exit 1 ;;
    # ?
esac

export local="$local_server"
export remote1="$primary_remote"
export remote2="$secondary_remote"

copyFiles() {
  el=$1
  primsec=$2
  # can we just iterate from for loop instead of writing three scp statements?
  (scp -C -o StrictHostKeyChecking=no goldy@"$local":/proc/data/abc_187_"$el"_111_8.data "$primsec"/.) ||   (scp -C -o StrictHostKeyChecking=no goldy@"$remote1":/proc/data/abc_187_"$el"_111_8.data "$primsec"/.) ||   (scp -C -o StrictHostKeyChecking=no goldy@"$remote2":/proc/data/abc_187_"$el"_111_8.data "$primsec"/.)

}
export -f copyFiles

# using gnu parallel here to call above methods parallely

现在您可以看到我有三个 scp 语句,一个用于本地框,另一个用于 remote1 和 remote2。我在想的是,也许我们可以摆脱这三个 scp 语句,而是将主机名(以特定顺序,第一个索引可以是本地框,其他两个可以是远程框)存储在一个数组中,然后从 for 循环迭代该数组只写一个 scp 语句?

for p in "$machines"; do scp -C -o StrictHostKeyChecking=no goldy@"$p":/proc/data/abc_187_"$el"_111_8.data "$primsec"/. && break; done > /dev/null 2>&1

如果这是可能的,那么我如何相应地重新排列 machines 数组,或者创建一个不同的数组,然后在正确的索引处使用正确的机器?

更新:

不知何故,我在该函数内的 for 循环根本没有运行:

copyFiles() {
  local el=$1
  local primsec=$2
  local remote_file="/proc/data/abc_187_${el}_111_8.data"
  for host in "${hosts[@]}"; do
    echo "$host"
    echo "scp -C -o StrictHostKeyChecking=no "goldy@$host:$remote_file" "$primsec"/." && break
  done
}
export hosts
export -f copyFiles

parallel -j 5 copyFiles {} $proc::: ${pro[@]} &
parallel -j 5 copyFiles {} $data::: ${seco[@]} &
wait
echo "everything copied"

最佳答案

这个怎么样:它使用

  • 一个关联数组来保存“本地”机器名
  • 保存 scp 主机序列的数组
  • 一个 for 循环遍历可能的主机,并在第一个成功的 scp 之后中断
#!/bin/bash
declare -A machines=(
    [abc]=machineA.abc.host.com
    [def]=machineB.def.host.com 
    [pqr]=machineC.pqr.host.com
)

IFS=. read -a host_parts < <(hostname -f)

case "${host_parts[1]}" in
    abc) hosts=( "${machines[abc]}" "${machines[def]}" "${machines[pqr]}" ) ;;
    def) hosts=( "${machines[def]}" "${machines[pqr]}" "${machines[abc]}" ) ;;
    pqr) hosts=( "${machines[pqr]}" "${machines[abc]}" "${machines[def]}" ) ;;
    *) echo "unknown host: $(hostname -f), exiting." >&2; exit 1 ;;
esac

copyFiles() {
    local el=$1
    local primsec=$2
    local remote_file="/proc/data/abc_187_${el}_111_8.data"
    for host in "${hosts[@]}"; do
        scp -C -o StrictHostKeyChecking=no "goldy@$host:$remote_file" "$primsec"/. && break
    done
}

export hosts
export -f copyFiles

关于linux - 从原始数组创建一个数组,但基于代码运行的位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50010881/

相关文章:

javascript - 激活输出不会因输入变化而改变太多 [Synaptic]

mysql - key '1' 的重复条目 'PRIMARY'

bash - 如何在 bash 中制作管道循环

linux - 共享库如何找到 GOT 部分?

linux - 为什么在 bash 中使用显式解释器不使用路径变量

windows - 在 Windows 中的 Git bash 中全局运行 shell 脚本

java - JSch ChannelExec OutputStream 不显示程序输出。但是它适用于 shell 脚本

c - 如何在 SYSTEM 下运行应用程序?

linux - 如何在 shell 脚本中回显动态变量的内容

linux - 为什么 PMP(穷人的分析器)不能在 nginx 上工作?