如何在 shell 中从三台机器中随机选择第一台机器?

how to pick first machine random out of three in shell?

我有三台远程机器(machineA、machineB、machineC),我可以从那里复制文件。如果出于某种原因我无法从 machineA 复制,那么我应该从 machineB 复制,如果出于某种原因我无法从 machineB 复制然后开始从 machineC 复制。

下面是我拥有的单个 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

如何将机器名称保存在一个文件中并使用 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

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

#!/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