Trong công việc hàng ngày, chúng ta phải quản lý rất nhiều server Linux, từ ở công ty cho đến các server cá nhân. Điều này đòi hỏi chúng ta phải nhớ vô số tài khoản SSH, mật khẩu, rồi cả tài khoản và mật khẩu superuser (các user quản trị có toàn quyền trong hệ thống).
Mọi thứ trở nên khá rắc rối khi số lượng server tăng lên. Có thể bạn sẽ gặp khó khăn với việc làm thế nào để nhập mật khẩu SSH, vì các shell Unix thông thường không có cách nào để gửi mật khẩu khi nhận được yêu cầu đăng nhập.
Bạn có thể dùng Expect để viết script cho việc tự động đăng nhập vào server. Đây là một tiện ích rất hữu dụng trên Linux/Unix. Nó cho phép bạn tự động hóa việc tương tác với các chương trình yêu cầu nhập liệu qua terminal nói chung, trong đó có đăng nhập SSH.
Viết Expect script
Công cụ Expect rất dễ làm quen. Đúng như tên gọi của nó, Expect phân tích kết quả đầu ra của một lệnh. Khi kết quả này khớp với một biểu thức chính quy (regular expression) được chỉ định, nó sẽ thực thi một lệnh đã được chỉ định tương ứng.
Ví dụ dùng Expect Script để đăng nhập SSH
Dưới đây là một script giúp tự động đăng nhập vào SSH server, sau đó đăng nhập với superuser và chạy một lệnh đơn giản. File sshsudologin.expect
:
#!/usr/bin/expect
#Usage sshsudologin.expect <host> <ssh user> <ssh password> <su user> <su password>
set timeout 60
spawn ssh [lindex $argv 1]@[lindex $argv 0]
expect "yes/no" {
send "yes\\r"
expect "*?assword" { send "[lindex $argv 2]\\r" }
} "*?assword" { send "[lindex $argv 2]\\r" }
expect "# " { send "su - [lindex $argv 3]\\r" }
expect ": " { send "[lindex $argv 4]\\r" }
expect "# " { send "ls -ltr\\r" }
interact
Những điểm quan trọng cần biết khi viết một Expect script
- Dòng đầu tiên chỉ định Expect sẽ được dùng làm trình thông dịch (interpreter) cho script này.
- Thời gian chờ (timeout) mặc định của là 10 giây. Ta đã tăng lên 60 giây để tránh lỗi timeout trong trường hợp cửa sổ yêu cầu đăng nhập xuất hiện chậm.
- Cấu trúc lệnh
expect
đi kèm với một biểu thức chính quy, theo sau là nội dung cần gửi đi để phản hồi. Lựa chọn Yes/No đầu tiên được thêm vào để đảm bảo script không bị lỗi nếu khóa (key) của server từ xa chưa được import. - Các biểu thức chính quy khác trong lệnh
expect
có thể thay đổi tùy server. Ví dụ, ở đây server có dấu nhắc lệnh kết thúc bằng#
. Nhưng với các server khác có thể là$
, do đó bạn có thể cần phải chỉnh sửa cho phù hợp. Điều duy nhất cần kiểm tra là biểu thức chính quy phải khớp với dấu nhắc lệnh, để script có thể gửi đúng lệnh hoặc mật khẩu tương ứng. - Lệnh
expect
cuối cùng cho thấy rằng chúng ta cũng có thể gửi các lệnh khác sau khi đã đăng nhập thành công vào server.
Đây là kết quả đầu ra khi chạy script trên với các tham số hợp lệ.
pankaj@Pankajs-MacBook-Pro:~$/Users/pankaj/scripts/sshloginsudo.expect 'journaldev.com' 'pankaj' 'ssh_pwd' 'su_user' 'su_pwd'
spawn ssh pankaj@journaldev.com
pankaj@journaldev.com's password:
Last login: Sun Jun 9 19:54:17 2013 from c-67-161-57-160.hsd1.ca.comcast.net
pankaj@journal [~]# su - su_user
Password:
su_user@journal [~]# ls -ltr
total 708
...
Lưu ý: Script trên đã được kiểm thử trên hệ điều hành Mac OS và Linux.
Những mẹo nhỏ khi dùng Expect
- Vì mọi thông tin đều được truyền dưới dạng tham số, các script Expect có thể được tái sử dụng dễ dàng. Tốt nhất là bạn nên tạo một
alias
(bí danh) cho mỗi server để đăng nhập nhanh hơn và tiết kiệm thời gian gõ lại toàn bộ các tham số. Ví dụ:alias journal="/Users/pankaj/scripts/sshloginsudo.expect '[journaldev.com](<http://journaldev.com/>)' 'pankaj' 'ssh_pwd' 'su_user' 'su_pwd'"
- Bạn nên luôn dùng dấu nháy đơn để truyền tham số vì mật khẩu thường chứa các ký tự đặc biệt. Nếu không đặt trong dấu nháy, chúng có thể gây ra những lỗi không mong muốn.