- 论坛徽章:
- 93
|
本帖最后由 seesea2517 于 2012-07-11 20:24 编辑
这不格式不好控制嘛,再说整理成一个文档,也方便多年以后检索,总是比在一个回复中找到内容来的容易些。
果然格式很难弄,找到一个取巧的办法,用代码格式,原样过来,哈哈。
回复 88# 无风之谷 - 前言
- 为了参与[url]http://bbs.chinaunix.net/thread-3757201-9-1.html[/url]的这个讨论,整理一下以前写的脚本。现在看来,这个脚本写的很简陋,并发操作也只是分批的控制而不是完全的并行,不过工作起来还算简单稳定。
- 概述
- 此脚本使用 expect 来对需要交互输入用户名和密码等操作进行自动化,并有对于主机提示自动加入信任列表、操作失败记录日志等功能。
- 正文
- 这个脚本分三个文件,逐一附录如下:
- 1. 主脚本:batch_ssh.sh
- 1. #!/bin/bash
- 2. # batch_scp.sh
- 3. # 作者:亚丹
- 4. # 时间:2009-05-27
- 5. # seesea2517#gmail*com
- 6. # [url]http://seesea.blog.chinaunix.net[/url]
- 7. # [url]http://blog.csdn.net/nicenight[/url]
- 8. #
- 9. # 功能:批量无交互scp操作
- 10. #
- 11. # 配置文件格式:
- 12. # IP xxxx ID/Name
- 13. # IP xxxx ID/Name
- 14. # IP xxxx ID/Name
- 15. # IP xxxx ID/Name
- 16. # IP xxxx ID/Name
- 17.
- 18. server_list=$1
- 19. cmd=$2
- 20. if [ -z "$server_list" ] || [ -z "$cmd" ]
- 21. then
- 22. echo "Usage: $0 server_list command"
- 23. exit 1
- 24. fi
- 25.
- 26. if [ ! -f "$server_list" ]
- 27. then
- 28. echo -e "File \"$server_list\" not exist!"
- 29. exit 1
- 30. fi
- 31.
- 32. # The result directory
- 33. res_dir="result"
- 34. if ! [ -d $res_dir ]
- 35. then
- 36. mkdir $res_dir
- 37. fi
- 38.
- 39. readonly MAX_THREAD=300 ;# The max number of the sub threads can be forked
- 40. readonly OLD_IFS=${IFS} ;# Save the current IFS
- 41. IFS=\n' ;# Set the IFS to '\n"
- 42.
- 43. usr="ssh_user"
- 44. port=22
- 45. read -sp "Input the password for $usr: " psw
- 46.
- 47. echo "\nGo!\n"
- 48.
- 49. (( i = 0 ))
- 50.
- 51. for line in `cat $server_list`
- 52. do
- 53. if [ -z "$line" ]
- 54. then
- 55. continue
- 56. fi
- 57.
- 58. echo "$line" | grep '^#' > /dev/null
- 59. if [ $? = 0 ]
- 60. then
- 61. continue
- 62. fi
- 63.
- 64. ip=`echo $line | awk '{print $1}'`
- 65. id=`echo $line | awk '{print $3}'`
- 66.
- if [ "$ip" == "" ]
- then
- continue
- fi
- ./remote_exec.exp $usr $ip $port $psw $cmd >> "$res_dir/${id}.txt" &
- # If the sub thread numbers upto the MAX_THREAD, then wait for all done
- if (( ++i % $MAX_THREAD == 0 ))
- then
- echo "wait....."
- wait
- fi
- echo -ne "\rProcessing $i."
- done
- IFS=${OLD_IFS}
- wait
- echo "Total $i done."
- 2. 主 expect 调用脚本 remote_exec.exp
- 1. #!/usr/bin/expect
- 2. # remote_exec.exp
- 3. # 作者:亚丹
- 4. # 时间:2009-05-27
- 5. # seesea2517#gmail*com
- 6. # [url]http://seesea.blog.chinaunix.net[/url]
- 7. # [url]http://blog.csdn.net/nicenight[/url]
- 8. #
- 9. # 功能:实现无交互远程操作
- 10.
- 11. source func.exp
- 12.
- 13. if {$argc < 5 } {
- 14. puts "remote_exec needs 5 parameters."
- 15. exit 1
- 16. }
- 17.
- 18. log_user 0
- 19. log_file log.txt
- 20.
- 21. set in_user [lindex $argv 0]
- 22. set in_ip [lindex $argv 1]
- 23. set in_port [lindex $argv 2]
- 24. set in_psw [lindex $argv 3]
- 25. set in_cmd [lindex $argv 4]
- 26.
- 27. set out_res ""
- 28.
- 29. set ret [remote_exec $in_user $in_ip $in_port $in_psw $in_cmd out_res]
- 30. if {$ret < 0} {
- 31. puts "remote_exec failed (return code: $ret, return str: $out_res)."
- 32. exit 1
- 33. }
- 34.
- 35. puts $out_res
- 3. expect 的函数库文件:func.exp,现在看来,也没有再新加过函数……不过这个远大蓝图还是曾经存在过的哈
- 1. #!/usr/bin/expect
- 2. # func.exp
- 3. # 作者:亚丹
- 4. # 时间:2009-05-27
- 5. # seesea2517#gmail*com
- 6. # [url]http://seesea.blog.chinaunix.net[/url]
- 7. # [url]http://blog.csdn.net/nicenight[/url]
- 8. #
- 9. # 功能:基本函数库文件
- 10.
- 11. # -----------------------------------
- 12. # Function:
- 13. # Execute the command on the host in_ip
- 14. #
- 15. # Return:
- 16. # If successfully executed, return 0
- 17. # otherwise return the error code:
- 18. # -1: Connect timeout
- 19. # -2: Wrong password
- 20. # -3: Wrong password
- 21. # -4: Checking password timeout
- 22. #
- 23. # Input args:
- 24. # in_user: Specifys the user to login
- 25. # in_ip : Specifys the host for user to login
- 26. # in_psw : Specifys the password for user to login to the host
- 27. # in_cmd : Specifys the command(s) to execute
- 28. #
- 29. # Output args:
- 30. # out_res: Returns the result if executed successfully
- 31. # returns the error description if unsuccessful
- 32. # -----------------------------------
- 33. proc remote_exec {in_user in_ip in_port in_psw in_cmd out_res} {
- 34. upvar $out_res response
- 35.
- 36. # The for loop is used to do the login action
- 37. set timeout 9999
- 38. for {set i 1} {$i < 3} {incr i} {
- 39.
- 40. # Last "////" is used as an end symbol
- 41. # spawn -noecho ssh $in_user@$in_ip ls -ogt --time-style=+'%Y%m%d%H%M%S' | grep ^- && echo ////
- 42. spawn -noecho ssh $in_user@$in_ip -p $in_port $in_cmd && echo ////
- 43.
- 44. expect {
- 45. -nocase "Password:"
- 46. {
- 47. send "$in_psw\n"
- 48. break
- 49. }
- 50.
- 51. -nocase "(yes/no)"
- 52. {
- 53. send "yes\n"
- 54. continue
- 55. }
- 56.
- 57. timeout
- 58. {
- 59. set response "Can't connect to host $in_ip\n"
- 60. return -1
- 61. }
- 62. }
- 63. sleep 1
- 64. }
- 65.
- 66. expect {
- 67. -nocase "password:"
- 68. {
- 69. set response "Wrong password inputed for $in_user@$in_ip.\n"
- 70. return -2
- 71. }
- 72.
- 73. -nocase "denied"
- 74. {
- 75. set response "Wrong password inputed for $in_user@$in_ip.\n"
- 76. return -3
- 77. }
- 78.
- 79. timeout
- 80. {
- 81. set response "Timeout while checking password for $in_user@$in_ip.\n"
- 82. return -4
- 83. }
- 84.
- 85. -re ".*////"
- 86. {
- 87. set response $expect_out(0,string)
- 88. set response [string trim $response "\r\n /"]
- 89. return 0
- 90. }
- 91. }
- 92. }
- --------------------------------------------------------------------------------------
- 对于常用的 scp 操作,有对上述脚本做了针对性的调整,以更加方便的使用:
- 1. 主脚本 batch_scp.sh
- 1. #!/bin/bash
- 2. # batch_scp.sh
- 3. # 作者:亚丹
- 4. # 时间:2009-05-27
- 5. # seesea2517#gmail*com
- 6. # [url]http://seesea.blog.chinaunix.net[/url]
- 7. # [url]http://blog.csdn.net/nicenight[/url]
- 8. #
- 9. # 功能:批量无交互scp操作
- 10. #
- 11. # 配置文件格式:
- 12. # IP xxxx ID/Name
- 13. # IP xxxx ID/Name
- 14. # IP xxxx ID/Name
- 15. # IP xxxx ID/Name
- 16. # IP xxxx ID/Name
- 17.
- 18. # para1 is the server list file
- 19. server_list=$1
- 20. if [ -z "$server_list" ]
- 21. then
- 22. echo "Usage: $0 server_list remote_dir local_dir"
- 23. exit 1
- 24. fi
- 25.
- 26. # If server list file not exists, then exit
- 27. if [ ! -f "$server_list" ]
- 28. then
- 29. echo -e "File \"$server_list\" not exist!"
- 30. exit 1
- 31. fi
- 32.
- 33. # para2 is the remote directory for scp
- 34. # if not inputed, then set to "/"
- 35. rdir=$2
- 36. if [ -z "$rdir" ]
- 37. then
- 38. rdir="/"
- 39. fi
- 40.
- 41. # para3 is the local directory for scp
- 42. # if not inputed, then set to "./"
- 43. ldir=$3
- 44. if [ -z "$ldir" ]
- 45. then
- 46. ldir="./"
- 47. fi
- 48.
- 49. # The result directory
- 50. res_dir="result"
- 51. if ! [ -d $res_dir ]
- 52. then
- 53. mkdir $res_dir
- 54. fi
- 55.
- 56. readonly MAX_THREAD=2 ;# The max number of the sub threads can be forked
- 57. readonly OLD_IFS=${IFS} ;# Save the current IFS
- 58. IFS=\n' ;# Set the IFS to '\n"
- 59.
- 60. usr="ssh_user"
- 61. port=22
- 62. read -sp "Input the password for $usr: " psw
- 63.
- 64. (( i = 0 ))
- 65.
- 66. for line in `cat $server_list`
- 67. do
- 68. if [ -z "$line" ]
- 69. then
- 70. continue
- 71. fi
- 72.
- 73. echo "$line" | grep '^#' > /dev/null
- 74. if [ $? = 0 ]
- 75. then
- 76. continue
- 77. fi
- 78.
- 79. ip=`echo $line | awk '{print $1}'`
- 80. id=`echo $line | awk '{print $3}'`
- 81. if [ "$ip" == "" ]
- then
- continue
- fi
- # ./remote_exec.exp $usr $ip $port $psw $rdir $ldir >> "$res_dir/${id}.txt" &
- # make a local sub-dir for scp, use the id info
- lsub_dir="$ldir/${id}"
- if [ ! -d "$lsub_dir" ]
- then
- mkdir "$lsub_dir"
- fi
- # download and delete the file for release the space of the disk
- # (./remote_exec.exp $usr $ip $port $psw $rdir "$lsub_dir" >> "$res_dir/${id}.txt"; sz "$lsub_dir/*"; rm -R "$lsub_dir";) &
- # for test, not delete the local sub dir
- (./remote_exec.exp $usr $ip $port $psw $rdir "$lsub_dir" >> "$res_dir/${id}.txt"; sz "$lsub_dir/*";) &
- # If the sub thread numbers upto the MAX_THREAD, then wait for all done
- if (( ++i % $MAX_THREAD == 0 ))
- then
- echo "wait....."
- wait
- fi
- done
- IFS=${OLD_IFS}
- wait
- echo "Total $i done."
- 2. remote_exec.exp
- 1. #!/usr/bin/expect
- 2. # remote_exec.exp
- 3. # 作者:亚丹
- 4. # 时间:2009-05-27
- 5. # seesea2517#gmail*com
- 6. # [url]http://seesea.blog.chinaunix.net[/url]
- 7. # [url]http://blog.csdn.net/nicenight[/url]
- 8. #
- 9. # 功能:实现无交互远程操作
- 10.
- 11. source func.exp
- 12.
- 13. if {$argc < 6 } {
- 14. puts "remote_exec needs 6 parameters."
- 15. exit 1
- 16. }
- 17.
- 18. log_user 0
- 19. log_file log.txt
- 20.
- 21. set in_user [lindex $argv 0]
- 22. set in_ip [lindex $argv 1]
- 23. set in_port [lindex $argv 2]
- 24. set in_psw [lindex $argv 3]
- 25. set in_rdir [lindex $argv 4]
- 26. set in_ldir [lindex $argv 5]
- 27.
- 28. set out_res ""
- 29.
- 30. set ret [remote_exec $in_user $in_ip $in_port $in_psw $in_rdir $in_ldir out_res]
- 31. if {$ret < 0} {
- 32. puts "remote_exec failed (return code: $ret, return str: $out_res)."
- 33. exit 1
- 34. }
- 35.
- 36. puts $out_res
- 3. func.exp
- 1. #!/usr/bin/expect
- 2. # func.exp
- 3. # 作者:亚丹
- 4. # 时间:2009-05-27
- 5. # seesea2517#gmail*com
- 6. # [url]http://seesea.blog.chinaunix.net[/url]
- 7. # [url]http://blog.csdn.net/nicenight[/url]
- 8. #
- 9. # 功能:基本函数库文件
- 10.
- 11. # -----------------------------------
- 12. # Function:
- 13. # Execute the command on the host in_ip
- 14. #
- 15. # Return:
- 16. # If successfully executed, return 0
- 17. # otherwise return the error code:
- 18. # -1: Connect timeout
- 19. # -2: Wrong password
- 20. # -3: Wrong password
- 21. # -4: Checking password timeout
- 22. #
- 23. # Input args:
- 24. # in_user: Specifys the user to login
- 25. # in_ip : Specifys the host for user to login
- 26. # in_psw : Specifys the password for user to login to the host
- 27. # in_rdir: Specifys the remote directory for scp
- 28. # in_ldir: Specifys the local directory for scp
- 29. #
- 30. # Output args:
- 31. # out_res: Returns the result if executed successfully
- 32. # returns the error description if unsuccessful
- 33. # -----------------------------------
- 34. proc remote_exec {in_user in_ip in_port in_psw in_rdir in_ldir out_res} {
- 35. upvar $out_res response
- 36.
- 37. # The for loop is used to do the login action
- 38. set timeout 10
- 39.
- 40. # Last "////" is used as an end symbol
- 41. # spawn -noecho ssh $in_user@$in_ip ls -ogt --time-style=+'%Y%m%d%H%M%S' | grep ^- && echo ////
- 42. spawn -noecho scp -p $in_port $in_user@$in_ip:$in_rdir $in_ldir && echo ////
- 43.
- 44. expect {
- 45. -nocase "Password:"
- 46. {
- 47. send "$in_psw\n"
- 48. }
- 49.
- 50. -nocase "(yes/no)"
- 51. {
- 52. send "yes\n"
- 53. exp_continue
- 54. }
- 55.
- 56. timeout
- 57. {
- 58. set response "Can't connect to host $in_ip\n"
- 59. return -1
- 60. }
- 61. }
- 62.
- 63. expect {
- 64. -nocase "password:"
- 65. {
- 66. set response "Wrong password inputed for $in_user@$in_ip.\n"
- 67. return -2
- 68. }
- 69.
- 70. -nocase "denied"
- 71. {
- 72. set response "Wrong password inputed for $in_user@$in_ip.\n"
- 73. send "\003"
- 74. exec kill [exp_pid]
- 75. close
- 76. wait
- 77. return -3
- 78. }
- 79.
- 80. timeout
- 81. {
- 82. set response "Timeout while checking password for $in_user@$in_ip.\n"
- 83. return -4
- 84. }
- 85.
- 86. -re "\[^/]+////"
- 87. {
- 88. set response $expect_out(0,string)
- 89. set response [string trim $response "\r\n /"]
- 90. return 0
- 91. }
- 92. }
- 93. }
复制代码 |
|