Chinaunix首页 | 论坛 | 博客
  • 博客访问: 220939
  • 博文数量: 42
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 420
  • 用 户 组: 普通用户
  • 注册时间: 2014-03-09 10:55
个人简介

每天改变一点点,生活充满了惊喜。

文章分类

全部博文(42)

文章存档

2016年(8)

2015年(29)

2014年(5)

我的朋友

分类: 系统运维

2014-09-23 11:44:35

  1. A 主机要与B 主机的账户user01 建立SSH信任关系,即A使用SSH协议,user01用户登录到B时无需使用密码,
  2. 一些使用SSH协议的命令也无需输入密码,如scp。

  3. 脚本要在A主机上执行,执行以下命令行:
  4. ssh ssh_set_pubkey.sh -n B -u user01

  5. 代码的主要使用ssh工具在A主机本地生成公钥和私钥,然后把公钥写入到B主机用户user01主目录的.ssh/id_rsa.pub文件中。
  下面的Shell脚本中增加了许多设置执行环境的代码,是为了脚本更加规范,可移植和安全。


  1. #! /bin/sh -
  2. # ssh_set_pubkey.sh : generate publice and private key,
  3. # and snyc publice key to remote server
  4. # USAGE : ssh_set_pubkey.sh [-?|-h|--help]
  5. # [-v|--version]
  6. # [-u|--user]
  7. # [-n|--host]

  8. #-----script initinizle
  9. IFS=$' \n\t'
  10. export PATH="/usr/bin:/bin:/usr/local/bin"


  11. UMASK=022
  12. umask ${UMASK}

  13. unset -f unalias
  14. unalias -a

  15. #----functions
  16. function error()
  17. {
  18.   echo "$@" 1>&2
  19.   usage_and_exit 1
  20. }

  21. function usage()
  22. {
  23.   cat <<EOF
  24. Usage:
  25.        $PROGRAM [-?|-h|--help]
  26.                 [-v|--version]
  27.                 [-u|--user]
  28.                 [-n|--hostname]
  29. EOF
  30. }

  31. function usage_and_exit()
  32. {
  33.   usage
  34.   exit $1
  35. }
  1. function version()
  2. {
  3.   echo "$PROGRAM version $VERSION"
  4. }

  5. #----global variable declare
  6. VERSION="v1.0 2014/01/05"
  7. PROGRAM="`basename $0`"
  8. CURR_USER_HOME="`(cd ~;pwd)`"

  9. DATE_TIME=`date "+%Y%m%d_%H%M%S"`

  10. USER=
  11. HOSTNAME=

  12. SSH="ssh"
  13. SSH_KEY_GEN="ssh-keygen"
  14. SSH_KEY_SYNC="ssh-copy-id"

  15. ENCRYPTION_TYPE="rsa"
  16. PRIVATE_KEY_FILE="${CURR_USER_HOME}/.ssh/id_rsa"
  17. PUBLIC_KEY_FILE="${CURR_USER_HOME}/.ssh/id_rsa.pub"

  18. #----main workflow
 #处理命令行选项
  1. while [ $# -gt 0 ]
  2. do
  3.   case $1 in
  4.   '-?'|-h|--help)
  5.      usage_and_exit
  6.      ;;
  7.   -v|--version)
  8.      version
  9.      exit 0
  10.      ;;
  11.   -u|--user)
  12.      USER=$2
  13.      shift 1
  14.      ;;
  15.   -n|--hostname)
  16.      HOSTNAME=$2
  17.      shift
  18.      ;;
  19.   -*)
  20.      error "Unrecognized option : $1"
  21.      ;;
  22.   *)
  23.      break
  24.      ;;
  25.   esac
  26.   shift 1
  27. done

  28. [ -z ${USER} ] && error "Unspecified user !"
  29. [ -h ${HOSTNAME} ] && error "Unspecified hostname !"

  30. #生成公钥和私钥
  31. if ! [ -f ${PRIVATE_KEY_FILE} ] || ! [ -f ${PUBLIC_KEY_FILE} ]
  32. then
  33.   rm -rf ${PRIVATE_KEY_FILE}
  34.   rm -rf ${PUBLIC_KEY_FILE}
  35.   ${SSH_KEY_GEN} -t ${ENCRYPTION_TYPE} -N "" -f ${PRIVATE_KEY_FILE} > /dev/null
  36. fi

 #同步私钥,使用ssh_key_sync命令,或通过ssh直接写入authorized_keys文件,
 #当然这里是要输入一次密码的,不过以后登录就无需再输入密码了

  1. if which "$SSH_KEY_SYNC" >/dev/null 2>&1
  2. then
  3.   ${SSH_KEY_SYNC} -i ${PUBLIC_KEY_FILE} ${USER}@${HOSTNAME}
  4. else
  5.   #~/.ssh 必须存在,而且权限必须是 700,本机的私钥的权限必须设置成600
  6.   ${SSH} ${USER}@${HOSTNAME} "mkdir -p ~/.ssh; chmod 700 ~/.ssh; cat >> ~/.ssh/authorized_keys ; chmod 700 ~/.ssh/authorized_keys" < $PUBLIC_KEY_FILE >/dev/null 2>&1
  7. fi
或者也可以写成函数的形式,方便在其他脚本中调用:
  1. ##! @TODO : create trust relationship between local host and remote host
  2. ##! @IN : $1 => remote hostname or ip
  3. ##! @IN : $2 => remote host username
  4. function createTrustRelationship(){
  5.     local l_remote_host="$1"
  6.     local l_remote_user="$2"

  7.     local l_home_dir="$(cd ${HOME}; pwd)"
  8.     local l_private_key_file="${l_home_dir}/.ssh/id_rsa"
  9.     local l_public_key_file="${l_home_dir}/.ssh/id_rsa.pub"

  10.     local l_curr_time=$(date "+%Y%m%d_%H%M%S")
  11.     # backup
  12.     if [ -f "${l_private_key_file}" ]
  13.     then
  14.       mv "${l_private_key_file}" "${l_private_key_file}_${l_curr_time}"
  15.     fi
  16.     if [ -f "${l_public_key_file}" ]
  17.     then
  18.       mv "${l_public_key_file}" "${l_public_key_file}_${l_curr_time}"
  19.     fi
  20.       
  21.     # generate key and sync to server
  22.     ssh-keygen -t "rsa" -N "" -f ${l_private_key_file} >/dev/null
  23.     
  24.     if command -v ssh-copy-id >/dev/null 2>&1
  25.     then
  26.       ssh-copy-id -i ${l_public_key_file} ${l_remote_user}@${l_remote_host}
  27.     else
  28.       # ~/.ssh 必须存在,而且权限必须是 700,本机的私钥的权限必须设置成600
  29.       ssh ${l_remote_user}@${l_remote_host} "mkdir -p ~/.ssh; chmod 700 ~/.ssh; cat >> ~/.ssh/authorized_keys; chmod 700 ~/.ssh/authorized_keys" <${l_public_key_file} >/dev/null 2>&1
  30.     fi
  31. }
以上是 Shell 中常用的功能实现形式:
脚本形式,既可以单独执行,也可以其他脚本中,作为命令行的形式直接调用,一般是以子进程的形式执行的,执行完即退出。
函数形式,它不能单独执行,使用前必须以 source 的方式加载进当前的脚本执行环境,自加载后,在整个脚本的执行过程中都存在。

不同的执行方式,会产生差别:
子进程执行的形式有自己的进程空间,不能操作父进程的变量,父子进程要交换信息,就需要使用进程间的通信机制,处理起来会更加复杂。
而函数形式,主脚本的执行环境可能会对函数的执行产生影响,而函数的执行也可能改变脚本的执行环境。

另外,调试时在主脚本使用sh -x,对在主脚本中调用的其他脚本是无效,如果要连带调试这些脚本,需要在这些脚本的开头#! /bin/sh 

后面也加上 -x 选项。

因此,如果只是实现整个脚本中的部分功能,建议写成函数的形式。

问题:
1.在使用过程中,有一次发现脚本执行完成,还未建立信任关系成功,
结果查明,是服务端的机器没有创建 ~/.ssh目录,所以在上面的脚本中增加了创建 目录 以及赋权限的操作,问题解决。
阅读(2227) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~