我最近获得了对服务器列表的用户名/密码访问权限,并希望将我的 SSH 公钥传播到这些服务器,以便我可以更轻松地登录。
这样就清楚了:
- 远程服务器上没有任何预先存在的公钥,我可以利用它来自动执行此操作
- 这是我第一次登录这些服务器,我希望不必不断地输入我的凭据来访问它们
ssh-copy-id
我也不想在 for 循环中一遍又一遍地输入密码。
答案1
您无需多次输入密码,而是可以使用pssh
其-A
开关来提示输入一次,然后将密码提供给列表中的所有服务器。
笔记:但是,使用此方法不允许您使用ssh-copy-id
,因此您需要推出自己的方法,将 SSH 公钥文件附加到远程帐户的~/.ssh/authorized_keys
文件中。
例子
这是完成这项工作的示例:
$ cat ~/.ssh/my_id_rsa.pub \
| pssh -h ips.txt -l remoteuser -A -I -i \
' \
umask 077; \
mkdir -p ~/.ssh; \
afile=~/.ssh/authorized_keys; \
cat - >> $afile; \
sort -u $afile -o $afile \
'
Warning: do not enter your password if anyone else has superuser
privileges or access to your account.
Password:
[1] 23:03:58 [SUCCESS] 10.252.1.1
[2] 23:03:58 [SUCCESS] 10.252.1.2
[3] 23:03:58 [SUCCESS] 10.252.1.3
[4] 23:03:58 [SUCCESS] 10.252.1.10
[5] 23:03:58 [SUCCESS] 10.252.1.5
[6] 23:03:58 [SUCCESS] 10.252.1.6
[7] 23:03:58 [SUCCESS] 10.252.1.9
[8] 23:03:59 [SUCCESS] 10.252.1.8
[9] 23:03:59 [SUCCESS] 10.252.1.7
上面的脚本一般结构如下:
$ cat <pubkey> | pssh -h <ip file> -l <remote user> -A -I -i '...cmds to add pubkey...'
高层次pssh
细节
cat <pubkey>
将公钥文件输出到pssh
pssh
使用-I
交换机通过 STDIN 摄取数据-l <remote user>
是远程服务器的帐户(我们假设您在 IP 文件中的服务器上具有相同的用户名)-A
告诉pssh
您询问您的密码,然后将其重新用于它连接到的所有服务器-i
告诉pssh
将任何输出发送到 STDOUT 而不是将其存储在文件中(其默认行为)'...cmds to add pubkey...'
- 这是正在发生的事情中最棘手的部分,所以我会单独分解它(见下文)
在远程服务器上运行的命令
pssh
这些是将在每台服务器上运行的命令:
' \
umask 077; \
mkdir -p ~/.ssh; \
afile=~/.ssh/authorized_keys; \
cat - >> $afile; \
sort -u $afile -o $afile \
'
为了:
将远程用户的 umask 设置为 077,这样我们要创建的任何目录或文件都会相应地设置其权限,如下所示:
$ ls -ld ~/.ssh ~/.ssh/authorized_keys drwx------ 2 remoteuser remoteuser 4096 May 21 22:58 /home/remoteuser/.ssh -rw------- 1 remoteuser remoteuser 771 May 21 23:03 /home/remoteuser/.ssh/authorized_keys
创建目录
~/.ssh
并忽略警告我们(如果它已经存在)- 设置变量 ,
$afile
其路径为authorized_keys 文件 cat - >> $afile
- 从 STDIN 获取输入并附加到authorized_keys 文件sort -u $afile -o $afile
- 对authorized_keys文件进行唯一排序并保存
笔记:最后一点是处理对同一服务器多次运行上述命令的情况。这将消除您的公钥被多次附加的情况。
注意单个刻度!
还要特别注意所有这些命令都嵌套在单引号内。这很重要,因为我们不想$afile
在远程服务器上执行之前对其进行评估。
' \
..cmds... \
'
我扩展了上面的内容,以便在这里更容易阅读,但我通常将其全部运行在一行上,如下所示:
$ cat ~/.ssh/my_id_rsa.pub | pssh -h ips.txt -l remoteuser -A -I -i 'umask 077; mkdir -p ~/.ssh; afile=~/.ssh/authorized_keys; cat - >> $afile; sort -u $afile -o $afile'
奖励材料
通过使用,pssh
您可以不必构建文件并使用提供动态内容,或者您可以使用另一个开关-h <(...some command...)
创建 IP 列表。pssh
-H "ip1 ip2 ip3"
例如:
$ cat .... | pssh -h <(grep -A1 dp15 ~/.ssh/config | grep -vE -- '#|--') ...
~/.ssh/config
上面的内容可用于从我的文件中提取 IP 列表。您当然也可以用来printf
生成动态内容:
$ cat .... | pssh -h <(printf "%s\n" srv0{0..9}) ....
例如:
$ printf "%s\n" srv0{0..9}
srv00
srv01
srv02
srv03
srv04
srv05
srv06
srv07
srv08
srv09
您还可以使用seq
它来生成格式化的数字序列!
参考文献和类似工具pssh
如果您不想像pssh
我上面那样使用,还有其他一些选项可用。
答案2
替代使用xargs
,sshpass
和ssh-copy-id
:
假设您居住在凭据.txt格式 user:password@server
:
$ cat credentials.txt
root:[email protected]
foo:[email protected]
bar:[email protected]
你可以这样做:
tr ':@' '\n' < credentials.txt \
| xargs -L3 sh -c 'sshpass -p $1 ssh-copy-id $0@$2'
注意:记得删除凭据.txt使用后!
答案3
使用安西布尔相当简单。替换<USER>
成真实的登录名即可
$ cd /path/to/public/key
$ cat<<END > hosts
host1.example.com
10.10.10.10
END
$ ansible -i hosts all --ask-pass -u <USER> -m authorized_key \
-a "user=<USER> key='$(cat id_rsa.pub)'"
答案4
有几件事可能符合要求:
- 从功能上讲,ServerFault 也提出了同样的问题:自动化 ssh-copy-id。
- 有一个 Perl 模块,但似乎维护得不多:https://github.com/Ruyk/pssh-copy-id。
正如其他答案中提到的,sshpass
这可能是最简单的解决方案。