Bash
ssh-copy-id 在腳本(集群)的循環中工作不正常
我有一組執行 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
(