Expect脚本多主机密码变更:多Expect场景处理问题咨询
Hey there! I totally get where you're coming from—Expect scripts are perfect for automating password tasks, but juggling multiple unpredictable login scenarios across hosts can get tricky. Since you've already nailed the active account rotation and expired password reset flows, let's build out the script to smoothly handle the remaining two cases.
First, the core trick for handling multiple matches in Expect: the expect command accepts multiple patterns, and using exp_continue lets you loop back to wait for subsequent prompts without exiting the expect block. This is critical for adapting to inconsistent login flows across different systems.
Let’s assume your remaining two scenarios are:
- Scenario 3: Account is locked (e.g., prompts like "Account locked" or "Too many failed login attempts")
- Scenario 4: First-time login prompt to confirm the host RSA fingerprint (e.g., "Are you sure you want to continue connecting (yes/no)?")
Here’s a robust, commented script framework that covers all four cases:
#!/usr/bin/expect -f # Set timeout (adjust based on your network speed and system response time) set timeout 30 # Define your target hosts and credentials set hosts {host1.yourdomain.com host2.yourdomain.com host3.yourdomain.com} set username "target_user" set old_password "current_password" set new_password "rotated_password" foreach host $hosts { puts "Starting password rotation for: $host" log_file "password_rotation_$host.log" ;# Log each host's session for debugging # Spawn the SSH session to the host spawn ssh $username@$host expect { # Scenario 4: Host key confirmation prompt (first-time login) "Are you sure you want to continue connecting (yes/no)?" { send "yes\r" exp_continue ;# Loop back to wait for the next prompt } # Scenario 2: Password expired prompt (adjust pattern to match your system's message) "Your password has expired. Please enter a new password:" { send "$old_password\r" expect "Enter new password:" send "$new_password\r" expect "Retype new password:" send "$new_password\r" puts "Expired password reset successfully on $host" } # Scenario 1: Normal password rotation prompt (adjust pattern to your system's wording) "Change password for $username" { send "$old_password\r" expect "Enter new password:" send "$new_password\r" expect "Retype new password:" send "$new_password\r" puts "Password rotated successfully on $host" } # Scenario 3: Account locked prompt (adjust regex to match your system's error) -re "(Account locked|Too many failed attempts)" { puts "ERROR: Account is locked on $host — manual intervention needed" send "exit\r" } # Catch-all for timeouts (prevents hanging scripts) timeout { puts "ERROR: Timed out connecting to $host" close } # Handle unexpected session closure eof { puts "Connection to $host closed" close } } log_file ;# Close the log file for the current host }
Pro Tips for Smooth Execution:
- Pattern Flexibility: Use regular expressions (
-re) to match slight variations in system prompts—for example,-re "(assword:|Password:)"catches both lowercase and uppercase password requests. - Debug Mode: Run your script with
expect -d your_script.expto see real-time matching and send events, which is a lifesaver for troubleshooting unrecognized prompts. - Isolate Host Sessions: Using per-host log files ensures issues on one host don’t break the entire batch job.
- Test First: Validate the script against one host covering all four scenarios before rolling it out to your full host list.
Adjust the prompt patterns to match your environment’s exact error messages and prompts—every system has slightly different wording for expired passwords, locked accounts, etc.
内容的提问来源于stack exchange,提问作者goon18

