【问题标题】:how to pick first machine random out of three in shell?如何从 shell 中的三台机器中随机选择第一台机器?
【发布时间】:2018-04-29 06:13:39
【问题描述】:

我有三台远程机器(machineA、machineB、machineC),我可以从中复制文件。如果由于某种原因我不能从机器A 复制,那么我应该从机器B 复制,如果由于某种原因我不能从机器B 复制,那么就从机器C 开始复制。

下面是我拥有的单个 shell 命令,我需要在许多机器上运行它,但这意味着在所有这些机器上,它只会从 machineA 复制。

(ssh goldy@machineA 'ls -1 /process/snap/20180418/*' | parallel -j5 'scp goldy@machineA:{} /data/files/') || (ssh goldy@machineB 'ls -1 /process/snap/20180418/*' | parallel -j5 'scp goldy@machineB:{} /data/files/') || (ssh goldy@machineC 'ls -1 /process/snap/20180418/*' | parallel -j5 'scp goldy@machineC:{} /data/files/')

现在有什么方法可以让我随机选择第一台机器(从这三台机器中),而不是像往常一样保持machineA。所以随机挑选第一台机器并保留另外两台作为备用,以防第一台机器停机?这可以吗?

更新:

我有这样的事情:

  machines=(machineA machineB machineC)
  for machine in $(shuf -e ${machines[@]}); do
      ssh -o StrictHostKeyChecking=no david@$machine 'ls -1 /process/snap/{{ folder }}/*' | parallel -j{{ threads }} 'scp -o StrictHostKeyChecking=no david@${machine}:{} /data/files/'
      [ $? -eq 0 ] && break
  done

【问题讨论】:

    标签: linux bash shell random scp


    【解决方案1】:

    如何将机器名称保存在一个文件中并使用 shuf 来打乱它们?然后你可以创建一个这样的脚本:

    while read machine; do
        ssh goldy@$machine 'ls -1 /process/snap/20180418/*' | parallel -j5 "scp goldy@$machine:{} /data/files/"
        if [ $? == 0 ]; then
            break
        fi
    done
    

    而机器文件是这样的:

    machineA
    machineB
    machineC
    

    然后像这样调用脚本:

    shuf machines | ./script.sh
    

    这是一个测试版本,它什么都不做,但显示了逻辑是如何工作的:

    while read machine; do
        echo ssh goldy@$machine 'ls -1 /process/snap/20180418/*'
        echo parallel -j5 "scp goldy@$machine:{} /data/files/"
        executenonexistingcommand
        if [ $? == 0 ]; then
            break
        fi
    done
    

    解决您的评论以使用数组代替并将所有内容放在一行:

    shuf -e ${machines[@]} 打乱一个数组。要将其读回数组,您需要将输出输入readarray。将脚本变成单行只是将分号放在我们之前换行符的位置。

    machines=( machineA machineB machineC ); for machine in $(shuf -e ${machines[@]}); do ssh goldy@$machine 'ls -1 /process/snap/20180418/*' | parallel -j5 "scp goldy@${machine}:{} /data/files/"; if [ $? == 0 ]; then break; fi; done
    

    【讨论】:

    • 有趣的想法.. 有什么方法可以让我们在一行中完成所有事情(我可以​​将 while done 循环格式化为一行),而不是将机器保存在文件中,如果可能的话,我们可以打乱一个数组吗?这将帮助我在一条命令中完成所有操作。
    • 更新答案。
    • 知道了。所以这意味着我的整个带有洗牌数组的一行命令看起来像这样machines=( machineA machineB machineC ); shuf -e ${machines[@]}; for machine in "${machines[@]}"; do ssh goldy@$machine 'ls -1 /process/snap/20180418/*'; parallel -j5 "scp goldy@${machine}:{} /data/files/"; if [ $? == 0 ]; then break; fi; done?
    • 我测试了上面分享给你的命令,它总是在我的命令中使用 machineA,所以我确定我上面有问题。此外,在我看来,内部 scp 行由于某种原因无法找出变量 machine
    • 对不起,写的东西与我的原意略有不同。当然,我们需要遍历shuf 的结果。我还意外地将| 字符更改为循环中的分号。更新帖子。
    【解决方案2】:

    这里有一个小例子来说明你可以如何做到这一点 - 它主要是 cmets,以显示我的想法,但你可以删除它们以使其简洁。

    #!/bin/bash
    
    # Machine names, number of machines, random starting index
    machines=("machineA" "machineB" "machineC")
    num=${#machines[@]}
    idx=$((RANDOM%num))
    
    # Make one try per machine, break on success
    for ((try=0;try<num;try++)) ; do
       this=${machines[$idx]}
       echo $this
       ((idx=(idx+1)%num))
    done
    

    所以,你可以把你的命令放在我有 echo $this 的地方,然后跟着它:

    [ $? -eq 0 ] && break
    

    样本输出

    ./go
    machineB
    machineC
    machineA
    

    如果你有shuf,你可以像这样更简洁地做同样的事情:

    #!/bin/bash
    
    # Machine names, in random order
    machines=("machineA" "machineB" "machineC")
    machines=( $(shuf -e "${machines[@]}") )
    
    # Make one try per machine, break on success
    for i in "${machines[@]}"; do
       echo $i
       ... your command
       [ $? -eq 0 ] && break
    done
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-03-18
      • 2018-11-14
      • 2021-10-15
      • 1970-01-01
      • 1970-01-01
      • 2019-05-19
      • 2017-11-10
      • 1970-01-01
      相关资源
      最近更新 更多