2016-09-23 83 views
0

我一直在尝试自动创建用户和配置ssh访问。如何通过bash脚本向主机添加ssh密钥

到目前为止,我创建了一个访问主机的脚本,并创建希望通过新的用户,如下所示:

expect -c ' 
spawn ssh '$user'@'$ip'; 
expect "assword: "; 
send "'$passwd'\r"; 
expect "prompt\n"; 
send "adduser '$new_user'\r"; 
... 
send "mkdir /home/'$new_user'/.ssh\r"; 
expect "prompt\n"; 
send "exit\r"; 
' 

这工作得很好,在那之后我需要在关键的.pub文件添加到授权密钥文件在主机中,那里是开始的地方。

我想:

ssh_key='/home/.../key.pub' 
content=$(cat $ssh_key) 
expect -c ' 
spawn ssh '$user'@'$ip' "echo '$content' >> /home/'$new_user'/.ssh/authorized_keys; 
expect "password:"; 
... 
' 

,并得到:

missing " 
    while executing 
"spawn ssh [email protected] "" 
couldn't read file "<ssh .pub key content> ... 

我也试过:

cat $ssh_key | ssh [email protected]$ip "cat >> /home/$new_user/.ssh/authorized_keys" 

没有成功,我只得到密码查询闪烁,我不能将期望与最后一种方法联系起来。

+0

你可能会习惯使用http://shellcheck.net/ - 它会抓住你的bug。 –

回答

2

我会忽略这里的大问题,专注于您的问题。 (有更大的问题:在这里不要使用expect - 如果你依靠sshpass而不是你可以非常简化这个脚本)。

现在,当你关闭你的单引号时,你并没有启动任何其他类型的引号。这意味着当你用空白替换一个变量时,你结束了-c参数传递给expect

而不是做这个的:

'foo'$bar'baz' 

做到这一点:

'foo'"$bar"'baz' 

...所以你的脚本看起来更像:

ssh_key='/home/.../key.pub' 
content=$(<"$ssh_key") 
expect -c ' 
spawn ssh '"$user"'@'"$ip"' "echo '"$content"' >> /home/'"$new_user"'/.ssh/authorized_keys; 
expect "password:"; 
... 
' 

来讲尽管完全避免这种情况,但考虑一些事情像下面这样:

#!/bin/bash 
#  ^^^^- NOT /bin/sh 

content=$(<"$ssh_key") # more efficient alternative to $(cat ...) 

# generate shell-quoted versions of your variables 
# these are safe to substitute into a script 
# ...even if the original content contains evil things like $(rm -rf /*) 
printf -v content_q '%q' "$content" 
printf -v new_user_q '%q' "$new_user" 

# use those shell-quoted versions remotely 
sshpass -f"$password_file" ssh "$host" bash -s <<EOF 
adduser ${new_user_q} 
printf '%s\n' ${content_q} >>/home/${new_user_q}/.ssh/authorized_keys 
EOF