2016-09-23 93 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