Lệnh expect trong Linux — Tự động hóa tương tác shell

Bạn đã bao giờ cảm thấy mệt mỏi khi phải ngồi canh màn hình để nhập thủ công hàng loạt mật khẩu hoặc các câu trả lời xác nhận mỗi khi thực hiện script tự động trên VPS chưa nhỉ? Trong vai trò một Senior System Admin, mình từng gặp tình huống cực kỳ đau đầu khi phải cấu hình hàng trăm máy chủ cùng lúc, nếu làm tay thì chắc chắn sẽ sai sót mất thôi. Đó chính là lúc chúng ta cần đến một "trợ lý" thực thụ để tự động hóa mọi thao tác tương tác. Vậy expect là gì và làm thế nào để làm chủ nó? Thực tế, expect là một công cụ cực kỳ mạnh mẽ giúp bạn tự động hóa các lệnh tương tác trong môi trường Linux. Bài viết này sẽ giúp bạn hiểu rõ cách dùng expect để xử lý các kịch bản cần phản hồi văn bản một cách mượt mà. Hãy cùng mình khám phá cách tự động hóa tương tác terminal một cách chuyên nghiệp nhất nhé!

Cần chuẩn bị gì trước khi dùng lệnh expect?

  • id="quyen-user">Quyền user: Yêu cầu quyền user thường để thực thi các kịch bản tự động hóa cơ bản. Trong trường hợp kịch bản cần tương tác với các lệnh yêu cầu đặc quyền, bạn cần sử dụng quyền sudo.
  • Hệ điều hành hỗ trợ: Hoạt động trên hầu hết các bản phân phối Linux (Ubuntu, Debian, CentOS, Fedora, RHEL) và macOS.
  • Cài đặt package: Nếu hệ thống chưa có sẵn, bạn cần cài đặt gói expect bằng các lệnh sau:
    • Ubuntu/Debian: sudo apt update && sudo apt install expect
    • CentOS/RHEL/Fedora: sudo yum install expect hoặc sudo dnf install expect
    • macOS (sử dụng Homebrew): brew install expect

Cú pháp lệnh expect là gì?

Lệnh expect hỗ trợ các dạng cú pháp khác nhau để thực hiện tương tác tự động trên các hệ thống Linux/Unix.

expect [OPTIONS] SCRIPT [ARGUMENTS...]
expect [OPTIONS] COMMAND
# Yêu cầu thông tin Bạn chưa cung cấp **{COMMAND_NAME}** cần viết tài liệu. Để tôi soạn phần "Tùy chọn thường dùng" theo tiêu chuẩn đã nêu, bạn vui lòng cung cấp: 1. **Tên lệnh** (ví dụ: ls, grep, find, cp, etc.) 2. **Nếu có**: Man page hoặc danh sách tùy chọn cụ thể bạn muốn đưa vào Sau khi bạn cung cấp thông tin, tôi sẽ: - ✓ Liệt kê đầy đủ các tùy chọn từ man page (không bịa) - ✓ Soạn theo cấu trúc HTML (tiêu đề → context → bảng) - ✓ Dùng giọng trung tính, từ ngữ kỹ thuật chính xác - ✓ Cung cấp ví dụ output nếu cần thiết **Chờ lệnh của bạn.**

xem thêm: Scripting and Programming

Cách sử dụng lệnh expect trong các kịch bản tự động hóa là gì?

Các ví dụ dưới đây mô phỏng các tình huống thực tế khi cần tự động hóa các tiến trình tương tác yêu cầu nhập liệu thủ công.

expect không tham số là gì? [Kiểm tra cài đặt lệnh]

expect -v
expect version 5.45.4

Lệnh hiển thị phiên bản hiện tại của công cụ. Trong thực tế, bước này giúp xác nhận môi trường đã sẵn sàng trước khi viết script phức tạp.

expect -c là gì? [Chạy kịch bản ngắn trực tiếp]

expect -c 'spawn echo "Hello"; expect "Hello"; send "\r"'
Hello

Tham số -c cho phép thực thi các câu lệnh expect trực tiếp từ dòng lệnh mà không cần tạo file script. Trong thực tế, cách này thường dùng để xử lý nhanh các tác vụ một dòng (one-liner) trên terminal.

expect trong tự động hóa SSH là gì? [Tự động đăng nhập SSH]

expect -c "
spawn ssh user@192.168.1.10
expect \"password:\"
send \"my_secure_password\r\"
interact
"
user@192.168.1.10's password: 
Welcome to Ubuntu!

Script này tự động nhận diện câu hỏi mật khẩu của SSH và gửi chuỗi ký tự đã định nghĩa. Trên môi trường production, đây là kỹ thuật cốt lõi để thực hiện các tác vụ quản trị từ xa hàng loạt khi không sử dụng SSH Key.

expect kết hợp với lệnh sudo là gì? [Tự động hóa quyền root]

expect -c "
spawn sudo apt update
expect \"\[sudo\] password for user:\"
send \"user_password\r\"
expect eof
"
[sudo] password for user: 
Hit:1 http://archive.ubuntu.com/ubuntu jammy InRelease

Kịch bản gửi mật khẩu ngay khi lệnh sudo yêu cầu quyền truy cập. Trong thực tế, kỹ thuật này giúp các tiến trình CI/CD hoặc cronjob có thể thực thi các lệnh yêu cầu quyền quản trị cao nhất một cách tự động.

expect kết hợp pipe và log file là gì? [Ghi lại phiên làm việc]

expect -c "
set logfile [open \"session.log\" w]
log_file \$logfile
spawn ftp 192.168.1.50
expect \"Name \"
send \"admin\r\"
expect \"Password:\"
send \"password123\r\"
expect eof
"

Sử dụng biến logfile để ghi lại toàn bộ quá trình tương tác vào một tệp tin cụ thể. Trên môi trường production, việc này cực kỳ quan trọng để phục vụ mục đích audit (kiểm toán) và debug khi script tự động gặp lỗi trong quá trình vận hành.

Lệnh expect thường gặp lỗi gì và cách xử lý như thế nào?

Dưới đây là các tình huống lỗi thực tế phát sinh khi cấu hình và thực thi kịch bản với công cụ expect trong quản trị hệ thống.

Lỗi không tìm thấy từ khóa mong đợi (Timeout)

#!/usr/bin/expect
spawn ssh user@remote_host
expect "password:"
send "my_password\r"
interact
(expect error: timeout)

Lệnh dừng lại và báo lỗi timeout do script không tìm thấy chuỗi "password:" trong thời gian mặc định (thường là 10 giây), có thể do kết nối mạng chậm hoặc host yêu cầu định dạng chuỗi khác.

Lỗi sai cú pháp khi gửi lệnh bằng send

#!/usr/bin/expect
spawn ftp 192.168.1.1
expect "Name"
send "admin"
expect "Password"
send "123456"
# Lỗi: Thiếu ký tự xuống dòng \r

Việc thiếu ký tự xuống dòng \r ở cuối lệnh send khiến script không thể thực thi lệnh tiếp theo, dẫn đến việc dừng lại vô hạn ở bước chờ đợi phản hồi từ server.

Lỗi không nhận diện được chuỗi ký tự đặc biệt

#!/usr/bin/expect
spawn telnet 10.0.0.1
expect "Login:"
expect "User: [a-z]*"

Khi chuỗi pattern trong lệnh expect chứa các ký tự đặc biệt hoặc các ký tự điều khiển mà không được bao bọc hoặc xử lý đúng quy tắc regex, script sẽ không khớp được với output của tiến trình đang chạy.

Lỗi mất kết nối khi sử dụng tương tác (interact)

#!/usr/bin/expect
spawn ssh user@remote_host
expect "password:"
send "password\r"
expect "$ "
interact
# Kết quả: Script kết thúc ngay lập tức khi tiến trình con đóng

Nếu tiến trình được spawn kết thúc quá nhanh hoặc gặp lỗi ngay sau khi gửi mật khẩu, lệnh interact có thể không duy trì được phiên làm việc, khiến người dùng không kịp thực hiện các thao tác thủ công.

Quy trình thực tế dùng expect trong tự động hóa tác vụ Linux?

Trong các dự án quản trị hệ thống, expect thường được sử dụng như một bước trong kịch bản automation để xử lý các tương tác yêu cầu nhập liệu thủ công từ người dùng.

Bước 1: Tạo kịch bản tương tác tự động

vi auto_ssh.exp
# Nội dung script chứa các câu lệnh expect, send và interact

Người dùng tạo một file script với đuôi .exp để định nghĩa các mẫu văn bản cần chờ (expect) và các phản hồi tương ứng (send).

Bước 2: Kiểm tra cú pháp và thực thi script

expect auto_ssh.exp
password123
logged in to server

Lệnh expect được gọi để chạy kịch bản, cho phép tự động điền mật khẩu hoặc các tham số cấu hình khi gặp câu hỏi từ hệ thống.

Bước 3: Kết hợp với shell script để điều khiển quy trình lớn

./deploy_app.sh
[Running expect automation...]
Deployment successful.

Trong các kịch bản triển khai ứng dụng phức tạp, expect được gọi bên trong một shell script lớn để xử lý các bước cần xác nhận trực tiếp từ terminal.

Vì bạn chưa cung cấp tên lệnh cụ thể `{COMMAND_NAME}`, tôi sẽ viết một bản mẫu dựa trên lệnh `chown` (một lệnh rất hay gây lỗi cho người mới chuyển từ Hosting sang VPS) để bạn hình dung đúng phong cách. Khi bạn cung cấp tên lệnh, tôi sẽ thực hiện chính xác theo cấu trúc này. ***

Việc thực thi lệnh chown trên môi trường VPS thường phát sinh lỗi nếu thiếu quyền quản trị cao nhất. Việc chạy lệnh chown mà không có sudo dẫn đến thông báo "Operation not permitted". Trong các kịch bản quản lý website trên VPS, việc xác định sai chủ sở hữu thư mục web có thể khiến dịch vụ Nginx hoặc Apache không có quyền đọc file. Ví dụ, lệnh sudo chown -R www-data:www-data /var/www/html giúp thiết lập lại quyền sở hữu cho web server. Một sai sót phổ biến khi quản lý VPS là sử dụng tùy chọn -R (recursive) trên các thư mục hệ thống nhạy cảm, gây ra tình trạng mất quyền truy cập của các tiến trình hệ thống. Người dùng cần kiểm tra kỹ đường dẫn trước khi áp dụng thay đổi hàng loạt.

Tư khóa cần viết: chown

Những câu hỏi thường gặp về lệnh expect?

Dưới đây là các tình huống phổ biến mà người dùng thường gặp phải khi bắt đầu sử dụng công cụ tự động hóa tương tác này.

Làm thế nào để tự động hóa việc nhập mật khẩu khi kết nối SSH?

Bạn có thể sử dụng expect để lắng nghe chuỗi ký tự yêu cầu mật khẩu và tự động gửi chuỗi mật khẩu đã định nghĩa trước.

#!/usr/bin/expect
spawn ssh user@hostname
expect "password:"
send "your_password\r"
interact

Làm sao để kiểm tra xem một phản hồi cụ thể đã xuất hiện hay chưa?

Lệnh expect cho phép bạn theo dõi đầu ra của tiến trình và thực hiện hành động tiếp theo ngay khi nhận được một từ khóa mục tiêu.

expect "Access denied" {
    send_user "Kết nối thất bại!\n"
    exit 1
}

Làm thế nào để kết thúc phiên làm việc tự động sau khi hoàn thành?

Sử dụng lệnh exit để đóng tiến trình expect và trả lại quyền kiểm soát cho shell sau khi các thao tác đã hoàn tất.

#!/usr/bin/expect
spawn ftp ftp.example.com
expect "Name"
send "user\r"
expect "Password"
send "pass\r"
send "quit\r"
expect eof

Lệnh expect có thể xử lý các lỗi timeout như thế nào?

Trong trường hợp phản hồi không xuất hiện trong khoảng thời gian quy định, tham số timeout sẽ giúp bạn kiểm soát lỗi.

set timeout 5
expect "unexpected_prompt" {
    send_user "Hết thời gian chờ phản hồi\n"
}

Làm thế nào để chuyển quyền điều khiển lại cho người dùng sau khi chạy script?

Lệnh interact cho phép duy trì phiên làm việc và cho phép người dùng nhập liệu thủ công sau khi các bước tự động đã chạy xong.

#!/usr/bin/expect
spawn top
expect "top - "
interact

Làm sao để gửi phím Enter trong script expect?

Để mô phỏng việc nhấn phím Enter, bạn cần thêm ký tự xuống dòng \r vào cuối chuỗi gửi đi.

send "\r"

Lệnh expect là một công cụ tự động hóa mạnh mẽ giúp bạn tương tác với các ứng dụng yêu cầu nhập liệu từ bàn phím một cách thông minh. Bạn có thể vô cùng dễ dàng làm chủ các kịch bản phức tạp bằng cách sử dụng tham số expect để chờ đợi các chuỗi phản hồi cụ thể, hay dùng send để tự động gửi các câu lệnh tiếp theo, đúng không nhỉ? Việc kết hợp linh hoạt giữa chúng sẽ giúp bạn tiết kiệm được rất nhiều thời gian khi phải xử lý các tác vụ lặp đi lặp lại trên terminal. Chúc bạn thành công!