test@tn01:~$ cat setup_ssh_nopass.sh #!/usr/bin/env bash set -Eeuo pipefail usage() { cat <<'USAGE' 用法: setup_ssh_nopass.sh [-u 远端用户] [-p 端口] [-k 私钥路径] 主机 或者: setup_ssh_nopass.sh 用户@主机 [-p 端口] [-k 私钥路径] 示例: setup_ssh_nopass.sh -u root -p 22 192.168.1.10 setup_ssh_nopass.sh alice@server.example.com USAGE } REMOTE_USER="${USER}" PORT=22 KEY_PATH="${HOME}/.ssh/id_ed25519" # 解析形如 user@host 的参数 parse_user_host() { local s="$1" if [[ "$s" == *"@"* ]]; then REMOTE_USER="${s%@*}" HOST="${s#*@}" else HOST="$s" fi } # 参数 while getopts ":u:p:k:h" opt; do case "$opt" in u) REMOTE_USER="$OPTARG" ;; p) PORT="$OPTARG" ;; k) KEY_PATH="$OPTARG" ;; h) usage; exit 0 ;; \?) echo "未知选项: -$OPTARG" >&2; usage; exit 2 ;; :) echo "选项 -$OPTARG 需要参数" >&2; usage; exit 2 ;; esac done shift $((OPTIND-1)) [[ $# -ge 1 ]] || { usage; exit 2; } parse_user_host "$1" # 生成密钥(若不存在) if [[ ! -f "$KEY_PATH" ]]; then mkdir -p "$(dirname "$KEY_PATH")" ssh-keygen -t ed25519 -a 100 -N "" \ -C "${USER}@$(hostname -f 2>/dev/null || hostname)-$(date +%Y%m%d)" \ -f "$KEY_PATH" fi chmod 600 "$KEY_PATH" || true PUB_KEY_CONTENT="$(cat "${KEY_PATH}.pub")" PUB_KEY_B64="$(base64 -w0 2>/dev/null < "${KEY_PATH}.pub" || base64 < "${KEY_PATH}.pub" | tr -d '\n')" # 可选:预先抓取远端主机指纹,避免交互确认(注意:生产环境请先核对指纹!) mkdir -p "${HOME}/.ssh" touch "${HOME}/.ssh/known_hosts" if command -v ssh-keyscan >/dev/null 2>&1; then ssh-keyscan -p "$PORT" -H "$HOST" >> "${HOME}/.ssh/known_hosts" 2>/dev/null || true fi # 把公钥追加到远端 authorized_keys(去重、修权限、SELinux 兼容) ssh -p "$PORT" "${REMOTE_USER}@${HOST}" bash -s <<'REMOTE' "$PUB_KEY_B64" set -Eeuo pipefail PUB_B64="$1" umask 077 mkdir -p "$HOME/.ssh" touch "$HOME/.ssh/authorized_keys" chmod 700 "$HOME/.ssh" chmod 600 "$HOME/.ssh/authorized_keys" # 解码公钥并去重追加 PUB_DEC="$(printf '%s' "$PUB_B64" | (base64 -d 2>/dev/null || openssl base64 -d))" if ! grep -qxF "$PUB_DEC" "$HOME/.ssh/authorized_keys"; then printf '%s\n' "$PUB_DEC" >> "$HOME/.ssh/authorized_keys" fi # SELinux 环境修复上下文(如有) command -v restorecon >/dev/null 2>&1 && restorecon -R "$HOME/.ssh" || true REMOTE # 自检免密是否生效 if ssh -p "$PORT" -o BatchMode=yes -o PasswordAuthentication=no \ "${REMOTE_USER}@${HOST}" 'echo OK' 2>/dev/null | grep -qx 'OK'; then echo "✅ 已配置免密:${REMOTE_USER}@${HOST}(端口 ${PORT}) 使用密钥 ${KEY_PATH}" else echo "⚠️ 看起来免密未生效。请检查远端 /etc/ssh/sshd_config 中的以下项:" echo " PubkeyAuthentication yes" echo " AuthorizedKeysFile .ssh/authorized_keys" echo " (如果远端禁止密码登录,首次安装密钥需用其他方式复制过去)" exit 1 fi