expect Command Linux: Complete Guide to Automate Interactive Programs

August 25, 2025

The expect command is a powerful automation tool in Linux that allows you to automate interactive programs that normally require manual input. Whether you’re dealing with SSH connections, FTP transfers, or any program that prompts for user interaction, expect can streamline your workflow by providing automated responses.

What is the expect Command?

The expect command is a scripting language and tool designed specifically for automating interactive applications. It works by “expecting” certain output patterns from programs and responding with predefined inputs. This makes it invaluable for system administrators, developers, and DevOps engineers who need to automate repetitive interactive tasks.

Key Features of expect

  • Pattern Matching: Recognizes specific text patterns in program output
  • Automated Responses: Sends predefined responses to interactive prompts
  • Timeout Handling: Manages scenarios where expected patterns don’t appear
  • Script Integration: Can be embedded in shell scripts and other automation tools
  • Cross-Platform: Available on various Unix-like systems

Installing expect

Before using expect, you need to install it on your system. Here’s how to install it on different Linux distributions:

Ubuntu/Debian:

sudo apt update
sudo apt install expect

CentOS/RHEL/Fedora:

# For CentOS/RHEL 7 and older
sudo yum install expect

# For CentOS/RHEL 8+ and Fedora
sudo dnf install expect

Arch Linux:

sudo pacman -S expect

Basic expect Syntax and Structure

An expect script follows a specific structure with key commands that control the automation flow:

#!/usr/bin/expect

spawn [command]
expect "pattern"
send "response\r"
interact

Core Commands Explained

  • spawn: Starts a new process that expect will control
  • expect: Waits for a specific pattern in the output
  • send: Sends text to the spawned process
  • interact: Hands control back to the user
  • exp_continue: Continues expecting after a match
  • exit: Terminates the expect script

Simple expect Examples

Example 1: Automating a Basic Interactive Program

Let’s create a simple expect script that automates a program asking for user information:

#!/usr/bin/expect

# Set timeout to 10 seconds
set timeout 10

# Spawn the interactive program
spawn ./user_info.sh

# Expect username prompt and respond
expect "Enter username:"
send "johndoe\r"

# Expect password prompt and respond
expect "Enter password:"
send "secretpass123\r"

# Expect email prompt and respond
expect "Enter email:"
send "[email protected]\r"

# Wait for completion message
expect "User information saved"

# Exit the script
exit

Output:

Enter username: johndoe
Enter password: secretpass123
Enter email: [email protected]
User information saved successfully!

Example 2: Automating SSH Login

One of the most common use cases for expect is automating SSH connections:

#!/usr/bin/expect

set timeout 20
set hostname "192.168.1.100"
set username "admin"
set password "mypassword"

# Start SSH connection
spawn ssh $username@$hostname

# Handle different possible prompts
expect {
    "Are you sure you want to continue connecting" {
        send "yes\r"
        exp_continue
    }
    "password:" {
        send "$password\r"
    }
    timeout {
        puts "Connection timed out"
        exit 1
    }
}

# Wait for shell prompt
expect "$"

# Execute commands
send "ls -la\r"
expect "$"

send "uptime\r"
expect "$"

# Close connection
send "exit\r"
expect eof

Sample Output:

The authenticity of host '192.168.1.100' can't be established.
RSA key fingerprint is SHA256:abc123...
Are you sure you want to continue connecting (yes/no)? yes
[email protected]'s password: 
Last login: Mon Aug 25 05:40:12 2025
admin@server:~$ ls -la
total 24
drwxr-xr-x 3 admin admin 4096 Aug 25 05:30 .
drwxr-xr-x 3 root  root  4096 Aug 20 10:15 ..
-rw-r--r-- 1 admin admin  220 Aug 20 10:15 .bash_logout
admin@server:~$ uptime
 05:40:15 up 5 days,  2:30,  1 user,  load average: 0.00, 0.01, 0.05
admin@server:~$ exit

Advanced expect Techniques

Using Variables and Command Line Arguments

You can make your expect scripts more flexible by using variables and accepting command line arguments:

#!/usr/bin/expect

# Check if enough arguments are provided
if {$argc != 3} {
    puts "Usage: $argv0   "
    exit 1
}

# Assign command line arguments to variables
set hostname [lindex $argv 0]
set username [lindex $argv 1]
set password [lindex $argv 2]
set timeout 30

puts "Connecting to $hostname as $username..."

spawn ssh $username@$hostname

expect {
    "Are you sure" {
        send "yes\r"
        exp_continue
    }
    "password:" {
        send "$password\r"
    }
    "Permission denied" {
        puts "Authentication failed!"
        exit 1
    }
    timeout {
        puts "Connection timeout!"
        exit 1
    }
}

expect "$"
puts "Successfully connected!"

# Interactive mode
interact

Handling Multiple Scenarios with Pattern Matching

Complex automation often requires handling multiple possible scenarios:

#!/usr/bin/expect

set timeout 15

spawn ftp ftp.example.com

expect {
    "Name" {
        send "anonymous\r"
        exp_continue
    }
    "Password:" {
        send "[email protected]\r"
    }
    "Login incorrect" {
        puts "Login failed"
        exit 1
    }
    "Connection refused" {
        puts "Cannot connect to server"
        exit 1
    }
    timeout {
        puts "Connection timed out"
        exit 1
    }
}

expect "ftp>"

# Navigate and download
send "cd pub\r"
expect "ftp>"

send "ls *.txt\r"
expect "ftp>"

send "get readme.txt\r"
expect {
    "Transfer complete" {
        puts "File downloaded successfully"
    }
    "No such file" {
        puts "File not found"
    }
}

send "quit\r"
expect eof

Error Handling and Debugging

Setting Debug Mode

For troubleshooting, you can enable debug mode to see what expect is doing:

#!/usr/bin/expect

# Enable debug mode
exp_internal 1

# Your expect script continues here...
set timeout 10
spawn ssh user@server

expect "password:"
send "mypassword\r"

Logging expect Output

You can log all interactions for later review:

#!/usr/bin/expect

# Start logging to file
log_file /tmp/expect_session.log

set timeout 20
spawn telnet example.com 80

expect "Connected"
send "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n"

expect "200 OK"
puts "Received successful HTTP response"

# Close log file
log_file

Real-World Use Cases

Database Connection Automation

Automate database connections and queries:

#!/usr/bin/expect

set timeout 30
set db_host "db.example.com"
set db_user "dbuser"
set db_pass "dbpassword"

spawn mysql -h $db_host -u $db_user -p

expect "Enter password:"
send "$db_pass\r"

expect "mysql>"
send "USE production_db;\r"

expect "mysql>"
send "SELECT COUNT(*) FROM users;\r"

expect "mysql>"
send "SHOW TABLES;\r"

expect "mysql>"
send "EXIT;\r"

expect eof

Automated Software Installation

Automate interactive software installations:

#!/usr/bin/expect

set timeout 300

spawn ./software_installer.run

expect "Do you accept the license agreement? (yes/no)"
send "yes\r"

expect "Enter installation directory:"
send "/opt/myapp\r"

expect "Install documentation? (y/n)"
send "y\r"

expect "Create desktop shortcut? (y/n)"
send "n\r"

expect "Installation complete"
puts "Software installed successfully!"

exit

Best Practices and Tips

Security Considerations

  • Avoid hardcoding passwords: Use environment variables or secure vaults
  • Set appropriate file permissions: chmod 700 script.exp
  • Use encrypted connections: Prefer SSH over telnet
  • Log management: Be careful with sensitive information in logs

Performance Optimization

#!/usr/bin/expect

# Set reasonable timeouts
set timeout 30

# Use efficient pattern matching
expect {
    -re "password|Password" {
        send "$password\r"
    }
    -exact "login:" {
        send "$username\r"
    }
}

# Clean up properly
expect eof
exit 0

Making Scripts Robust

#!/usr/bin/expect

proc connect_with_retry {host user pass max_retries} {
    set retry_count 0
    
    while {$retry_count < $max_retries} {
        set timeout 20
        
        if {[catch {spawn ssh $user@$host} result]} {
            puts "Spawn failed: $result"
            incr retry_count
            continue
        }
        
        expect {
            "password:" {
                send "$pass\r"
                expect {
                    "$" {
                        puts "Login successful"
                        return 1
                    }
                    "Permission denied" {
                        puts "Authentication failed, retry $retry_count"
                        incr retry_count
                    }
                }
            }
            timeout {
                puts "Connection timeout, retry $retry_count"
                incr retry_count
            }
        }
    }
    
    puts "Failed to connect after $max_retries attempts"
    return 0
}

# Usage
if {[connect_with_retry "server.com" "user" "pass" 3]} {
    interact
} else {
    exit 1
}

Integration with Shell Scripts

You can integrate expect scripts within bash scripts for more complex automation:

#!/bin/bash

# Bash script that uses expect
SERVERS=("server1.com" "server2.com" "server3.com")
USERNAME="admin"
PASSWORD="secretpass"

for server in "${SERVERS[@]}"; do
    echo "Connecting to $server..."
    
    expect << EOF
        set timeout 20
        spawn ssh $USERNAME@$server
        
        expect {
            "Are you sure" {
                send "yes\r"
                exp_continue
            }
            "password:" {
                send "$PASSWORD\r"
            }
        }
        
        expect "$"
        send "uptime\r"
        expect "$"
        
        send "df -h\r"
        expect "$"
        
        send "exit\r"
        expect eof
EOF

    echo "Finished with $server"
done

Troubleshooting Common Issues

Pattern Matching Problems

  • Case sensitivity: Use -nocase flag for case-insensitive matching
  • Regular expressions: Use -re flag for regex patterns
  • Exact matching: Use -exact flag to avoid regex interpretation
# Case-insensitive matching
expect -nocase "password"

# Regular expression matching
expect -re "password|Password|PASSWORD"

# Exact string matching
expect -exact "Enter password:"

Timeout Issues

# Global timeout setting
set timeout 60

# Per-expect timeout
expect {
    timeout 30 "slow_prompt" {
        send "response\r"
    }
    timeout 5 "quick_prompt" {
        send "quick_response\r"
    }
}

Conclusion

The expect command is an invaluable tool for automating interactive programs in Linux environments. From simple password automation to complex multi-server deployments, expect can significantly reduce manual effort and improve consistency in your workflows.

Key takeaways:

  • Use expect to automate any interactive command-line program
  • Always implement proper error handling and timeouts
  • Consider security implications when dealing with passwords
  • Test scripts thoroughly before deploying in production
  • Combine with other tools for more powerful automation solutions

With the examples and techniques covered in this guide, you’ll be well-equipped to automate your interactive programs and streamline your Linux administration tasks.