Bash

ssh-copy-id 在腳本(集群)的循環中工作不正常

  • November 27, 2020

我有一組執行 Ubuntu 20.04 的 RPi4(其中 7 個)。其中之一是 gui,我在其中執行命令。有 3 名經理和 3 名工人(/etc/hosts 均已正確設置)。

最初,它們都有一個具有相同名稱和密碼的使用者。

我想在 gui (gui0) 中執行一次的單個腳本中設置 SSH,這樣我就有了無密碼的 SSH。

gui* 機器應該可以訪問所有機器;manager* 機器應該可以訪問管理器和工人;並且工人應該只能訪問其他工人。

這樣做的原因是我將使用 GlusterFS(和其他一些東西)設置儲存,因此機器需要能夠在它們之間進行通信。

我開發了一個腳本,它或多或少有效:根據我在某些命令之間休眠的時間,實際複製的鍵更多,但我已經休眠了很多次,但仍然沒有達到 100% .

腳本:

#!/bin/bash

################################################################################
##  source                                    ##
################################################################################
source  lib/libalx/sh/sysexits.sh;  ## This provides EX_USAGE=64


################################################################################
##  definitions                               ##
################################################################################
ARGC=0;

guis="gui0";
managers="manager0 manager1 manager2";
workers="worker0 worker1 worker2";
all_machines="${guis} ${managers} ${workers}";
gui_accessible_machines="${all_machines}";
manager_accessible_machines="${managers} ${workers}";
worker_accessible_machines="${workers}";


################################################################################
##  functions                                 ##
################################################################################
## XXX: Pair calls to this function with "unset SSHPASS"!!!
function read_ssh_password()
{

   echo "This script will set up keyless ssh."
   echo "After this script, ssh will not accept passwords again."
   echo "Enter the current password for ssh connections."

   read -s -p "Password to use: " SSHPASS;
   echo;
   export SSHPASS;
}

function create_ssh_keys()
{

   for remote in ${all_machines}; do
       echo "  SSH-KEYGEN  ${remote};"
       sshpass -e ssh ${remote} "
           ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa;
       ";
   done
}

function distribute_ssh_keys_to()
{
   local   accessible_machines="$1";
#   local   ssh_opts="-o PreferredAuthentications=keyboard-interactive";
#   ssh_opts="${ssh_opts} -o PubkeyAuthentication=no";

   for remote in ${accessible_machines}; do
       echo "  SSH-COPY-ID $(cat /etc/hostname)    ${remote};"
       sshpass -e ssh-copy-id -i ~/.ssh/id_rsa.pub ${remote}   \
       2>&1 | grep -e WARNING -e ERROR -e added;
       sleep 60;
   done
}

function distribute_ssh_keys_from()
{
#   ssh_opts="-o PreferredAuthentications=keyboard-interactive";
#   ssh_opts="${ssh_opts} -o PubkeyAuthentication=no";
   local   machines="$1";
   local   accessible_machines="$2";

   for remote in ${machines}; do
       sshpass -e ssh ${remote} "
           $(declare -fg);
           export SSHPASS=${SSHPASS};
           distribute_ssh_keys_to  \"${accessible_machines}\";
           unset SSHPASS;
       ";
       sleep 300;
   done
   sleep 300;
}

function distribute_ssh_keys()
{

   distribute_ssh_keys_from "${guis}" "${gui_accessible_machines}";
   distribute_ssh_keys_from "${managers}" "${manager_accessible_machines}";
   distribute_ssh_keys_from "${workers}" "${worker_accessible_machines}";

   for remote in ${all_machines}; do
       ssh ${remote} "
           $(declare -fg);
           secure_ssh;
       ";
       sleep 60;
   done
}

function secure_ssh()
{

   :; ## TODO
}

function create_distribute_ssh_keys()
{

   read_ssh_password;

   create_ssh_keys;
   sleep 300;
   distribute_ssh_keys;

   unset SSHPASS;
}


################################################################################
##  main                                      ##
################################################################################
function main()
{

   create_distribute_ssh_keys;
}


################################################################################
##  run                                   ##
################################################################################
argc=$#;
if [ ${argc} -ne ${ARGC} ]; then
   echo    "Illegal number of parameters (Requires ${ARGC})";
   exit    ${EX_USAGE};
fi

main;

輸出:

ubuntu@gui0:~$ ./bin/setup_ssh.sh 
This script will set up keyless ssh.
After this script, ssh will not accept passwords again.
Enter the current password for ssh connections.
Password to use: 
   SSH-KEYGEN  gui0;
Generating public/private rsa key pair.
/home/ubuntu/.ssh/id_rsa already exists.
Overwrite (y/n)? n
   SSH-KEYGEN  manager0;
Generating public/private rsa key pair.
/home/ubuntu/.ssh/id_rsa already exists.
Overwrite (y/n)? n
   SSH-KEYGEN  manager1;
Generating public/private rsa key pair.
/home/ubuntu/.ssh/id_rsa already exists.
Overwrite (y/n)? n
   SSH-KEYGEN  manager2;
Generating public/private rsa key pair.
/home/ubuntu/.ssh/id_rsa already exists.
Overwrite (y/n)? n
   SSH-KEYGEN  worker0;
Generating public/private rsa key pair.
/home/ubuntu/.ssh/id_rsa already exists.
Overwrite (y/n)? n
   SSH-KEYGEN  worker1;
Generating public/private rsa key pair.
/home/ubuntu/.ssh/id_rsa already exists.
Overwrite (y/n)? n
   SSH-KEYGEN  worker2;
Generating public/private rsa key pair.
/home/ubuntu/.ssh/id_rsa already exists.
Overwrite (y/n)? n
   SSH-COPY-ID gui0    gui0;
/usr/bin/ssh-copy-id: WARNING: All keys were skipped because they already exist on the remote system.
   SSH-COPY-ID gui0    manager0;
/usr/bin/ssh-copy-id: WARNING: All keys were skipped because they already exist on the remote system.
   SSH-COPY-ID gui0    manager1;
/usr/bin/ssh-copy-id: WARNING: All keys were skipped because they already exist on the remote system.
   SSH-COPY-ID gui0    manager2;
/usr/bin/ssh-copy-id: WARNING: All keys were skipped because they already exist on the remote system.
   SSH-COPY-ID gui0    worker0;
/usr/bin/ssh-copy-id: WARNING: All keys were skipped because they already exist on the remote system.
   SSH-COPY-ID gui0    worker1;
/usr/bin/ssh-copy-id: WARNING: All keys were skipped because they already exist on the remote system.
   SSH-COPY-ID gui0    worker2;
/usr/bin/ssh-copy-id: WARNING: All keys were skipped because they already exist on the remote system.

   SSH-COPY-ID manager0    manager0;
/usr/bin/ssh-copy-id: WARNING: All keys were skipped because they already exist on the remote system.
   SSH-COPY-ID manager0    manager1;
/usr/bin/ssh-copy-id: WARNING: All keys were skipped because they already exist on the remote system.
   SSH-COPY-ID manager0    manager2;
/usr/bin/ssh-copy-id: WARNING: All keys were skipped because they already exist on the remote system.
   SSH-COPY-ID manager0    worker0;
Number of key(s) added: 1
   SSH-COPY-ID manager0    worker1;
   SSH-COPY-ID manager0    worker2;
/usr/bin/ssh-copy-id: WARNING: All keys were skipped because they already exist on the remote system.
   SSH-COPY-ID manager1    manager0;
   SSH-COPY-ID manager1    manager1;
   SSH-COPY-ID manager1    manager2;
   SSH-COPY-ID manager1    worker0;
   SSH-COPY-ID manager1    worker1;
   SSH-COPY-ID manager1    worker2;
   SSH-COPY-ID manager2    manager0;
   SSH-COPY-ID manager2    manager1;
   SSH-COPY-ID manager2    manager2;
   SSH-COPY-ID manager2    worker0;
   SSH-COPY-ID manager2    worker1;
   SSH-COPY-ID manager2    worker2;
   SSH-COPY-ID worker0 worker0;
   SSH-COPY-ID worker0 worker1;
   SSH-COPY-ID worker0 worker2;
   SSH-COPY-ID worker1 worker0;
   SSH-COPY-ID worker1 worker1;
   SSH-COPY-ID worker1 worker2;
   SSH-COPY-ID worker2 worker0;
   SSH-COPY-ID worker2 worker1;
   SSH-COPY-ID worker2 worker2;

我希望總是收到一條說明添加的鍵數量的行,或者一些錯誤或警告。但是在某些情況下,我只收到 INFO 行(我用 grep 將其作為噪音丟棄)。正如你所看到的,前幾個工作(它顯示一個警告,因為這不是我第一次執行它,所以之前執行時已經安裝了密鑰,但這很好),然後一些開始失敗,然後所有這些失敗。

如果我減少睡眠時間,它會更早開始失敗。

作為沒有 grep 的情況的範例:

   SSH-COPY-ID manager0;   worker0;
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/ubuntu/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'worker0'"
and check to make sure that only the key(s) you wanted were added.

   SSH-COPY-ID manager0;   worker1;
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/ubuntu/.ssh/id_rsa.pub"
   SSH-COPY-ID manager0;   worker2;
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/ubuntu/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'worker2'"
and check to make sure that only the key(s) you wanted were added.

為什麼它失敗得如此不規律?

我不明白為什麼你的sleep陳述很長,而且我不相信我已經正確地跟踪了你的程序流程。但是,查看要求,您需要

gui* 機器應該可以訪問所有機器;manager* 機器應該可以訪問管理器和工人;並且工人應該只能訪問其他工人

所以

  • GUI → GUI Managers Workers
  • 經理 → 經理 工人
  • 工人 → 工人

那麼像這樣的東西。我敢肯定,你會想要添加自己的進度更新和退出狀態,但是這個準系統應該讓你執行。

#!/bin/bash
#
guis=(gui0)
managers=(manager0 manager1 manager2)
workers=(worker0 worker1 worker2)

# Grab the password
#
IFS= read -rsp "Master password: " sshpass && echo


# First, GUI to everything
#
if [[ ! -f "$HOME/.ssh/id_rsa" ]] || [[ ! -f "$HOME/.ssh/id_rsa.pub" ]]
then
   # Start clean
   rm -f "$HOME/.ssh/id_rsa" "$HOME/.ssh/id_rsa.pub"
   ssh-keygen -t rsa -b 4096 -f "$HOME/.ssh/id_rsa" -P ""
fi

for dst in "${guis[@]}" "${managers[@]}" "${workers[@]}"
do
   # Using the password we entered at the beginning, copy the keys everywhere
   SSHPASS=$sshpass sshpass -ev ssh-copy-id -o StrictHostKeyChecking=no -i "$HOME/.ssh/id_rsa" "$dst"
done


# Now generate a key on each host in turn
#
for dst in "${managers[@]}" "${workers[@]}"
do
   # Ensure the target is clean and then generate a new key
   ssh -n "$dst" 'rm -f .ssh/id_rsa .ssh/id_rsa.pub'
   ssh -n "$dst" 'ssh-keygen -t rsa -b 4096 -f .ssh/id_rsa -P ""'
done


# Grab each host's key pair
#
for src in "${managers[@]}" "${workers[@]}"
do
   scp -p "$src:.ssh/id_rsa" "$HOME/.ssh/id_rsa.$src"
   scp -p "$src:.ssh/id_rsa.pub" "$HOME/.ssh/id_rsa.$src.pub"
done


# Push each Manager key out to the Managers and Workers
#
for src in "${managers[@]}"
do
   for dst in "${managers[@]}" "${workers[@]}"
   do
       ssh-copy-id -i "$HOME/.ssh/id_rsa.$src" "$dst"
   done
done


# Push each Worker key out to the Workers
#
for src in "${workers[@]}"
do
   for dst in "${workers[@]}"
   do
       ssh-copy-id -i "$HOME/.ssh/id_rsa.$src" "$dst"
   done
done


# Now fix up the "authenticity of host" warnings by connecting everywhere
#
for src in "${managers[@]}"
do
   for dst in "${managers[@]}" "${workers[@]}"
   do
       ssh -n "$src" ssh -n -o StrictHostKeyChecking=no "$dst" id >/dev/null
   done
done

for src in "${workers[@]}"
do
   for dst in "${workers[@]}"
   do
       ssh -n "$src" ssh -n -o StrictHostKeyChecking=no "$dst" id >/dev/null
   done
done


# Delete the unwanted key pairs from this host
#
for src in "${managers[@]}" "${workers[@]}"
do
   rm -f "$HOME/.ssh/id_rsa.$src" "$HOME/.ssh/id_rsa.$src.pub"
done


# All done
#
exit 0

請注意,一切都由客戶端gui0

引用自:https://unix.stackexchange.com/questions/621809