대략 expect, send, send_user 구문만 가지고도 어느정도 동작하는 스크립트 작성이 가능하다.
아래 스크립트에 대해서는 약간 설명이 필요한데, 특정 서버에 접속하여 로그를 다운로드 받아 분석기에 돌리고, 분석기가 생성한 스크립트를 다시 서버에 업로드하여 실행하는 스크립트이다. 로그를 다운로드 받고 스크립트를 다시 올리는 두번의 scp 과정은 ssh-agent를 통해 패스워드 없이 자동화 하였다. 분석기가 생성한 스크립트에서 일어나는 동작, 그러니까 다른 서버에 접속하여 파일을 가져오는 부분이 있는데, 이것은 expect를 사용하여 자동화 하였다.
#!/usr/local/bin/expect -f
set LOGDATE [timestamp -format %Y%m%d] (agent의 로그가 agent20070709.log 와 같은 파일 형식으로 저장된다. 오늘자 로그의 timestring을 생성한다.)
set HOST [lindex $argv 0] (첫번째 argument가 대상 HOST가 된다.)
system "scp root@$HOST:/user/service/logs/agent$LOGDATE.log .\n" (LOG를 가져온다. ssh-agent와 dsa, rsa key로 자동화가 되어 있지 않으면 패스워드를 입력해야 한다.)
system "./a.out agent$LOGDATE.log\n" (LOG를 분석한다. 이때 recover.sh이 생성된다.)
system "rm -f agent$LOGDATE.log\n" (LOG를 삭제한다.)
system "scp recover.sh root@$HOST:/root\n" (복구 shell script를 업로드 한다. ssh-agent와 dsa, rsa key로 자동화가 되어 있지 않으면 패스워드를 입력해야 한다.)
spawn ssh -l root $HOST (원격 HOST에 접근한다. ssh-agent와 dsa, rsa key로 자동화가 되어 있지 않으면 패스워드를 입력해야 한다.)
expect "\[root@" (원격 shell이 획득되었는지를 확인한다.)
send "./recover.sh\n" (복귀 shell script를 실행한다.)
expect {
Password: { (패스워드를 물어보는 부분. 대상 서버의 패스워드를 미리 입력해둔다.)
send "password-here!\r"
exp_continue
}
"ALL DONE" { (recover.sh이 완료되면 이런 메시지를 뿌린다. recover.sh을 지우고 메시지를 뿌린다.)
send "rm -f /root/recover.sh\n"
sleep 1
send_user "All Done.\n"
exit
}
"Command not found" { (recover.sh이 제대로 복사되지 않았다고 판단한다.)
send_user "recover.sh copy failed!\n"
exit
}
"ETA" { (복사가 매우 오래 걸리는 경우, timeout을 초과할때를 대비해서 scp의 ETA 메시지마다 new line을 전송한다.)
send "\r"
exp_continue
}
만일 FreeBSD에서 expect를 설치하려면 port를 통해서 설치하는 것 보다 별도로 소스를 구해서 설치하는 것을 권장한다. /usr/ports/x11-toolkits/tk84 이 패키지에 dependency가 설정되어 있어서, X11 관련된 바이너리들이 주르륵 깔리기 때문이다. 단, X11이 이미 설치되어 있다면 상관없다.
이 방법으로는 Interactive한 입력을 처리하는데 유용하고 별도의 key를 서버에 생성하지 않아도 된다는 장점이 있다. 하지만 서버상에 plain 한 패스워드를 저장하게 되어 보안상으로는 더 좋지 않게 된다는 생각이 든다.