使用expect在script中切换到root用户
1.尚观版本
http://www.uplook.cn/biancheng/133/1335040/
1 a. 命令行: /usr/bin/expect -c "set timeout -1; spawn su; expect \"Password:\"; send \"123456\\r\"; interact"
2
3 b. 脚本:
4
5 #!/usr/bin/expect
6 set timeout 5
7 spawn su
8 expect "Password:"
9
10 send "123456\r"
11 interact
12
13 #expect "# "
14
15 #send "whoami"
---------------------------------------------------------------------------------------------------------------------------------
2.网络小生的疑问(与我遇到的一样)
sutoRoot.sh 脚本: #-----------------------------------------------#
#!/usr/bin/expect #
# Su to Root without entering password manually !
# spawn su -
expect "Password:"
send "lovexia\r"
expect eof #-----------------------------------------------# 执行的情况: [nic@lovexia ~]$ who am i
nic pts/0 2008-09-19 02:30 (192.168.2.81) -----> 用户为nic
[nic@lovexia ~]$ ./sutoRoot.sh
spawn su -
Password:
[root@lovexia ~]# who am i ---> 已经su 成 Root 了,但执行who am i 后停了一会就自动变成下面的样子了,退回到用户nic 了
[nic@lovexia ~]$ who am i
nic pts/0 2008-09-19 02:30 (192.168.2.81)
[nic@lovexia ~]$ 对expect 还不熟,请教了 !
一位网友的解答:
1 expect eof ========> interact
3.一位网友的资源(http://bbs.chinaunix.net/thread-1733075-1-1.html)
1 expect -c "
2 spawn /usr/bin/ssh -t -l squall $IPADDR sudo sed -i '1\i "123"' /root/test.txt
3 expect {
4 \"*yes/no*\" {send \"yes\r\"; exp_continue}
5 \"*password*\" {send \"123456\r\"; exp_continue}
6 \"*Password*\" {send \"123456\r\";}
7 }
8 expect eof;"
4.使用expect脚本登录到root账号并执行命令
1 通过expect脚本登录root账号,方法比较简单,只要先写一个如下格式的脚本即可:
2
3 #!/usr/bin/expect
4
5 set timeout=30 #设置30秒超时
6
7 spwan su root
8
9 expect "Password*"
10
11 send "123456\r" #发送密码,别忘了以\r结尾
12
13 expect "*#*" #等待#提示符的出现
14
15 send "ls -l>/tmp/1\r" #执行ls命令,并重定向到/tmp/1
16
17 expect "*#*" #等待#出现,说明上一个命令执行完毕了
18
19 send "uname -a>/tmp/2\r" #再执行下一条命令
20
21 #interact #使用interact后,脚本将退出到root账号下,可以手动执行root权限的命令
22
23 expect eof
24
25 exit
5.我写的这个Expect程序,用来su root用户,为什么不行?(http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=2265473)
1 写了一个Expect程序:su_root
2 #!/usr/bin/expect
3
4 set timeout 3
5
6 spawn su
7 expect "assword:"
8 send "szcj\r"
9 expect "#"
10 interact
11
12 执行后,结果
13
14 ./su_root
15 spawn su
16 Password: szcj
17 (这里还有一个空行)
18
19 应该不是Expect的配置问题,我写了一个Expect程序,自动Telnet登陆别的服务器,能正常执行的。
20
21 为什么回这样?
这样就可以了:
1 set timeout 3
2
3 spawn su
4 expect "Password:"
5 exec sleep 1
6 send "szcj\r"
7 expect "#"
8 interact
6.吼吼
1 #!/usr/bin/expect
2 spawn su -
3 expect 'assword: '
4 send "NiDeRootMiMa\r"
5 interact
7.一个小哥的总结:
1 昨天一个网友问如何能够将输入密码的工作在shell里面自动完成,研究了一下,发现这种交互式的工作,普通的shell实现不了,据说可以借助expect来搞定,所以初步学习了一下expect,成果和大家分享一下:
2
3 应用一:
4 实现从普通用户“test”切换到root用户,自动输入root的密码,不用在终端提示符下执行密码输入操作。
5 步骤:
6 (1)vi autosu.sh
7 (2)#! /usr/bin/expect -f //指定expect工具的路径,如果不清楚具体路径,可以用"which expect"命令来查看。
8 spawn su - // 在expect 中用"spawn"关键字来调用命令“su - ”
9 expect ":" //在执行了su - 命令之后,提示输入密码的提示符。例如你在执行了su - 命令之后,终端里面会出现提示“口令:”,那么你就可以在这里写expect ":",或者expect -exact "口令:"
10 send "rootpasswd\r" //这里expect用send将你的root密码自动输入到上面的提示符之后。
11 interact //操作完成。
12
13 注意:这里强调一下执行脚本时要注意的地方,不能按照习惯来用sh ***.sh来这行expect的程序,会提示找不到命令,因为expect用的不是bash所以会报错。执行的时候直接./***.sh就可以了。~切记!
14
15
16
17
18
19 应用二:
20 从普通用户切换到root之后,执行“ls”操作,调用执行aaa.sh,返回执行结果,间隔10S。
21 #/usr/bin/expect -f
22 spawn su - // 在expect 中用"spawn"关键字来调用命令“su - ”
23 expect ":" //在执行了su - 命令之后,提示输入密码的提示符。例如你在执行了su - 命令之后,终端里面会出现提示“口令:”,那么你就可以在这里写expect ":",或者expect -exact "口令:"
24 send "rootpasswd\r" //这里expect用send将你的root密码自动输入到上面的提示符之后。
25 expect "#" //当遇到提示符以#结尾时,即为root权限时;
26 send "ls\r" //expect 用spend方法调用ls 命令,并且回车(“\r”)
27 expect "#"
28 send "sh aaa.sh\r" //调用sh aaa.sh,即执行一个脚本文件aaa.sh。
29 expect "#"
30 send "echo $?\r"
31 sleep 10
32 interact
33
34
35 先写这些,可能不对。
8.一位猛人的阐述:
现代的Shell对程序提供了最小限度的控制(开始,停止,等等),而把交互的特性留给了用户。 这意味着有些程序,你不能非交互的运行,比如说passwd。
有一些程序可以非交互的运行,但在很大程度上丧失了灵活性,比如说fsck。这表明Unix的工具构造逻辑开始出现问题。Expect恰恰填补了其中的一些裂痕,解决了在Unix环境中长期存在着
的一些问题。
Expect使用Tcl作为语言核心。不仅如此,不管程序是交互和还是非交互的,Expect都能运用。这是一个小语言和Unix的其他工具配合起来产生强大功能的经典例子。
举个例子,假如你是一个“懒”人,每天要做重复的工作,而偏偏你不想“ 做”。所以,你想到一个“偷懒”的办法就是脚本工具。执行完脚本,你可以一边喝着茶一边收获着结果。这是事物美好
的一面,另一面自然就不那么美好了,也许 shell需要跟你交流才能完成(也就是我们常说的交互)。这时,你就得想起神奇的expect。使用方法如下:
a.在终端下输入autoexpect命令,然后会看到autoexpect started, file is script.exp的提示信息。这时,你已经进入了自动的命令录制中,把你想要做的事儿全部做一遍,这个
工具会详细的记录下来,并写入script.exp文件中;当你确定完成时,输入exit退出“录制”。会看到autoexpect done, file is script.exp的提示信息,说明录制成功。script.exp
是一个文本文件,可以用vim或者emacs打开查看,也可以根据自己的需要进行相应的修改,前提是符合规则。
上面提到的是用自动的方法使用expect,同样也可以手动写脚本来执行。脚本以#!/usr/bin/expect开头,提出expect命令存放的路径,也可以执行which expect获得。下面是一个简单
的例子实现shell的切换:
12 #!/usr/bin/expect
13 # Change a login shell to tcsh
14 spawn chsh
15 expect "]:"
16 send "/bin/tcsh\r"
17 expect eof
18
19 保存为filename.sh文件,添加执行权限,./filename.sh后就可以看到结果。有点感觉吧。。。不要着急,好东西还在后面呢!
20
21 记得Linux里切换用户的命令吧,对了,就是su。如果你想从普通用户切换到root,然后再继续做操作。请接着往下看:
22
23 #!/usr/bin/expect
24
25 set user [lindex $argv 0]
26 set passwd [lindex $argv 1]
27 spawn su - $user
28 expect ":"
29 send "$passwd\r"
30 expect "]#"
31 send "cd /root\r"
32 expect "]#"
33 send "sh t.sh\r"
34 interact
35
36 可以把你想传的参数一并写在后面,如./filename.sh root 123456,argv[0]为root,argv[1]为123456。
spawn以expect的方式执行命令,然后expect发现该行以“:”结束时,会用send传递要执行的命令与shell交互;最后,interact命令给把控制权交给你所切换的用户。
http://blog.csdn.net/classwang/article/details/3928467
10.怎么在expect里面交互两次
http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=2333695
11.我自己总结的:
目的:定期删除GOMS机中测量文件。
背景:GOMS机为诺西定制linux只读系统。没法加入任何启动脚本。
方法:FEWS机为可制定linux系统。在FEWS中利用脚本A加入定时任务,在每月的1,10,20日的20:00点调用脚本B。脚本B会SSH到每个GOMS中调用脚本C,脚本C会
首先切到root用户(只有root用户能删除文件),然后调用脚本D执行清理任务。
缺点:脚本D效率不够高,但是我懒得改了。
脚本A:
1 #!/bin/bash
2
3 crontab -r
4
5 echo "00 20 1,10,20 * * /root/kobe/call_goms_file_del.sh" > /root/kobe/crontab_task
6
7 crontab /root/kobe/crontab_task
8
9 crontab -l
10 exit 0
脚本B:
1 #/bin/bash
2 #########################
3 #1.SSH every GOMS,Call the function script.
4 #2.touch log
5 ###########################
6 call_goms_file_del_log_file=/root/kobe/call_goms_file_del.log
7
8 del_cmd=""
9
10 function log()
11 {
12 echo -e "$(date +'%Y-%m-%d %T ') $*" >> $call_goms_file_del_log_file
13 }
14
15
16 if [ -f "$call_goms_file_del_log_file" ]; then
17 log $call_goms_file_del_log_file exilt!
18 del_cmd=$(date | awk '$3==1{printf("rm -f /root/kobe/call_goms_file_del.log")}')
19 log del_cmd:$del_cmd
20 if [ "${del_cmd}" != "" ]; then
21 ${del_cmd}
22 log recreat $call_goms_file_del_log_file...
23 touch $call_goms_file_del_log_file
24 fi
25
26 else
27 log $call_goms_file_del_log_file not exilt,creating...
28 touch $call_goms_file_del_log_file
29 fi
30
31
32
33 log "Let's go..."
34
35 goms_IP_list[1]='Nemuadmin@10.56.19.30'
36 goms_IP_list[2]='Nemuadmin@10.56.19.28'
37 goms_IP_list[3]='Nemuadmin@10.56.19.26'
38
39
40 for x in ${goms_IP_list[*]}
41 do
42 log "Enter $x"
43 expect -c "
44 spawn ssh $x /home/Nemuadmin/realtime_task/goms_file_del.sh
45
46 expect {
47 \"*assword\" {set timeout 21600; send \"nemuuser\r\";}
48 \"yes/no\" {send \"yes\r\"; exp_continue;}
49 }
50 expect eof"
51
52 done
53
54 log "It is over!."
55 echo "----------------------------------------------------------------------------------" >> $call_goms_file_del_log_file
56 exit 0
脚本C:
1 #!/usr/bin/expect
2
3 spawn su
4 expect ":"
5 send "password\r"
6 #expect "#"
7 #send "touch /root/jj.ll\r"
8 expect "#"
9 send "/home/Nemuadmin/realtime_task/goms_file_del.sh &\r"
10 expect "#"
11
12 interact
13
14 #expect eof
15
16 exit
脚本D:
1 #!/bin/bash
2
3 logfile="/home/Nemuadmin/realtime_task/goms_file_del.log"
4
5 function log()
6 {
7 echo -e "$(date +'%Y-%m-%d %T ') $*" >> $logfile
8 }
9
10
11 #expect -c "
12 # spawn su
13 # expect {
14 # \"Password: \" {send \"password\r\";}
15 # }
16 #interact"
17
18 if [ -f "$logfile" ]; then
19 log $logfile exist!
20 else
21 log $logfile not exist,creating...
22 touch $logfile
23 chmod 777 $logfile
24 fi
25
26 echo "----------------------Start time : $(date +'%Y-%m-%d %T ')--------------------------------------" > $logfile
27
28 #get date
29 year=$(date +%Y)
30 log "Year:$year!"
31
32 month=$(date +%m)
33 log "Month:$month!"
34
35 day=$(date +%d)
36 log "Day:$day!"
37
38
39 ##################################################
40 #argc:1
41 #argv:directory
42 #function:delete the files under argv parameter
43 ##################################################
44 function file_del()
45 {
46 log "cd $1"
47 cd $1
48 for i in *.gz
49 do
50 #get file's date
51 file_date=$(echo $i | cut -d "." -f4)
52 log "file[$i] file_date: $file_date!"
53
54 file_year=${file_date:0:4}
55 # log "file_year:$file_year "
56
57 file_month=${file_date:4:2}
58 # log "file_month:$file_month "
59
60 file_day=${file_date:6:2}
61 # log "file_day:$file_day "
62
63 # if (( (year > file_year) || ((month > file_month) && ((((month - file_month) * 30 + day) - file_day) > 10 ) ) ) )) ;then
64 # del_flag="Delete"
65 # else
66 # del_flag="Nodelete"
67 # fi
68
69
70 del_flag=$(awk -v year=$year -v month=$month -v day=$day -v file_year=$file_year -v file_month=$file_month -v file_day=$file_day 'BEGIN{
71 if ( (year > file_year) || ((month > file_month) && ((((month - file_month) * 30 + day) - file_day) > 10 ) ) )
72 printf("Delete")
73 else
74 printf("Nodelete")}')
75
76 # log "File($i) del_flag:$del_flag"
77 if [[ $del_flag == "Delete" && $i != "*.gz" ]];then
78 log "Delete file :[$i]!"
79 rm -f $i
80 else
81 log "File :[$i] Nodelete!"
82 fi
83 echo "-------------------------------------------------------------------------------" >> $logfile
84 done
85 }
86
87 #DELETE files under /var/opt/OMSftproot/xmlfiles directory
88 cd /var/opt/OMSftproot/xmlfiles/
89 file_del "/var/opt/OMSftproot/xmlfiles/"
90
91 #DELETE files under /var/opt/OMSftproot/xmlfilesBU directory
92 cd /var/opt/OMSftproot/xmlfilesBU/
93
94 for j in $(ls)
95 do
96 cd /var/opt/OMSftproot/xmlfilesBU/
97 file_del "$j"
98 done
99
100 #done successfully.
101 log "It is over!."
102 exit 0