#!/bin/bash

#Function:Script will automatically generate the current login account of the public key to send to 

#multiple remote hosts, in order to achieve the purpose of this machine SSH free login multiple remote host

#Usage:bash ssh-login-withoutpasswd.sh

#Date:2016/8

#Author:Jian


#运行该脚本前,请先安装expect,否则脚本运行不成功,原理:将本机产生的公钥id_rsa.pub用scp传输至远程服务器

#的家目录下的.ssh目录中便可实现本机(注意是用本机产生公钥的账号)登陆远程主机的目的

#需要注意的是要将远程主机各个家目录下的.ssh:chmod 700,其下面的文件全部:chmod 600

#在centos,rhel及ubuntu测试通过,如果成功将本机公钥传输到远程主机却不能免密登陆,请检查远程主机的selinux和iptables

#需要的话,可自行添加日志相关代码


check_hosts_on () {

ping_out=`mktemp ping.XXXXXX`

hosts_online=`mktemp hosts_online.XXXXXX`

cd $current_dir

for ip in $(cat hostnamelist|awk -F : '{print $1}')

do

  ping -c1 -w1 $ip >/dev/null && echo "$ip is up" || echo "$ip is down"

done>>$ping_out

for ip_online in $(cat $ping_out|grep "up"|awk '{print $1}')

do

  grep "$ip_online" hostnamelist >> $hosts_online

done

}

authorized_file_transfer () {

#enter the directory where hostnamelist is located

#the hostnamelist file has a target host IP address that needs to be delivered

#save format as ipaddr:username:password,eg:192.168.1.10:root:123456,note that do not leave spaces

cd $current_dir

for remote_infor in `cat $hosts_online`

do

  remote_ip_addr=`echo "$remote_infor" | awk -F : '{print $1}'`

  remote_username=`echo "$remote_infor" | awk -F : '{print $2}'`

  remote_password=`echo "$remote_infor" | awk -F : '{print $3}'`

expect << EOF

  set timeout 10

  spawn ssh -o StrictHostKeyChecking=no $remote_username@$remote_ip_addr

  set timeout 10

  expect "$remote_username@$remote_ip_addr's password:"

  set timeout 10

  send "$remote_password\r"

  set timeout 10

  expect {

  "*#*" {send "mkdir -p ~/.ssh\r"}

  "*\$*" {send "mkdir -p ~/.ssh\r"}

  }

  set timeout 10

  expect {

  "*#*" {send "scp -o StrictHostKeyChecking=no $local_username@$local_ip_addr:$HOME/.ssh/id_rsa.pub ~/.ssh/authorized_keys_from_$local_ip_addr\r"}

  "*\$*" {send "scp -o StrictHostKeyChecking=no $local_username@$local_ip_addr:$HOME/.ssh/id_rsa.pub ~/.ssh/authorized_keys_from_$local_ip_addr\r"}

  }

  set timeout 10

  expect "$local_username@$local_ip_addr's password:"

  set timeout 10

  send "$local_host_passwd\r"

  set timeout 10

  expect {

  "*#*" {send "cat ~/.ssh/authorized_keys_from_$local_ip_addr >>  ~/.ssh/authorized_keys\r"}

  "*\$*" {send "cat ~/.ssh/authorized_keys_from_$local_ip_addr >>  ~/.ssh/authorized_keys\r"}

  }

  set timeout 10

  expect {

  "*#*" {send "chmod 700 ~/.ssh && chmod 600 ~/.ssh/* && rm -f ~/.ssh/authorized_keys_from_$local_ip_addr\r"}

  "*\$*" {send "chmod 700 ~/.ssh && chmod 600 ~/.ssh/* && rm -f ~/.ssh/authorized_keys_from_$local_ip_addr\r"}

  }

  set timeout 10

  expect {

  "*#*" {send "chown -R $remote_username: ~/.ssh\r"}

  "*\$*" {send "chown -R $remote_username: ~/.ssh\r"}

  }

  set timeout 10

  expect {

  "*#*" {send "exit\r"}

  "*\$*" {send "exit\r"}

  }

  set timeout 10

  expect eof

EOF

done

}

create_authorized_file () {

#using ssh-keygen to generate the key, the path is the default path, the empty password

  if [ -d ~/.ssh ];then

    ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa

  else

    mkdir -p ~/.ssh

    ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa

  fi

}

#get local IP address

local_ip_addr=`/sbin/ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk '{print $2}'|tr -d "addr:"|head -1`

local_host_passwd="123456"

#get the user name of the current login user

local_username=`whoami`

#get the directory where the current run script is located

current_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

cd $current_dir

#first determine whether the host list file exists

if [ -f hostnamelist ]; then

#detect which hosts online, which offline

  check_hosts_on

  if grep "down" $ping_out >/dev/null; then

    echo "Warning:$(sed -n '/down/p' $ping_out|wc -l) hosts offline:"

    sed -n '/down/p' $ping_out

    echo "$(sed -n '/up/p' $ping_out|wc -l) hosts online:"

    sed -n '/up/p' $ping_out

  else

    echo "The hosts in the hostnamelist are all online!"

  fi

  if [ -f ~/.ssh/id_rsa ] && [ -f ~/.ssh/id_rsa.pub ]; then

    authorized_file_transfer

    chown -R $local_username: ~/.ssh/

    chmod 600 ~/.ssh/* 

    chmod 700 ~/.ssh

    rm -f $ping_out

    rm -f $hosts_online

    exit 0

  else

    create_authorized_file

    authorized_file_transfer

    chown -R $local_username: ~/.ssh/

    chmod 600 ~/.ssh/* 

    chmod 700 ~/.ssh

    rm -f $ping_out

    rm -f $hosts_online

    exit 0

  fi

else

  echo "Error:the important file 'hostnamelist' has been lost"

  echo "Now,creat it,but you still write something inside,the format is as follows:"

  touch hostnamelist

  echo "remote_ip_addr:remote_user_name:remote_host_password"

  exit 0

fi