Using Expect Script to Implement Conditional Statements with ‘If Else’
To bypass the script running like a human, consider spawning an anticipated to fail ssh connection that accepts the host RSA key without requiring a password prompt. You can delay the password prompt for new systems that require initiation. The list of hosts to execute the script against is stored in the file1 variable.
‘if else’ statement in Expect script
My goal is to generate a script that can transmit input based on the output obtained from running the preceding script.
#!/usr/bin/expect -- set timeout 60 spawn ssh user@server1 expect "*assword*" < send "password\r"; >expect "*$*" < send "./jboss.sh status \r"; >if [ expect "*running*" ]; then < send "echo running \r"; >else < send "./jboss.sh start \r"; >fi
I am attempting to perform a similar task, though I have encountered a roadblock at the if else line. Is there a solution to this issue?
One option is to group them together in a single statement labeled as expect , and then process each matching case accordingly.
#!/usr/bin/expect set timeout 60 spawn ssh user@server1 expect "assword" < send "password\r"; ># We escaped the `$` symbol with backslash to match literal '$' # The last '$' sign is to represent end-of-line set prompt "#|%|>|\\\$ $" expect < "(yes/no)" "password:" -re $prompt > send "./jboss.sh status\r" expect < "running" -re $prompt > expect -re $prompt
Unix — ‘if else’ statement in Expect script, I am trying to create a script which will «send» input as per the output received from executing the previous script. #!/usr/bin/expect — set timeout 60 spawn ssh user@server1 expect «*assword*» < send "password\r"; >expect You can simply group them into single expect statement and whichever matched, it … Code sample#!/usr/bin/expectset timeout 60spawn ssh user@server1expect «assword» < send "password\r"; ># We escaped the `$` symbol with backslash to match literal ‘$’Feedback
Using if/else in expect script
After making changes to my /etc/hosts file, I intend to update my known_hosts file on all devices (approximately 1000) using an expect script to respond with «yes» to the RSA fingerprint inquiry. However, some of these devices are unfamiliar to me, and my password has not been established, which presents two potential scenarios.
- «yes» is sent to the RSA fingerprint question and I’m logged into the server. I’ll then need to send an exit to close the connection before moving onto the next host. Or.
My understanding of the «if/else» concept in expect is basic, but I am unsure about how to properly nest them or if there is a more effective approach. Additionally, I am wondering if my initial understanding is incorrect.
This is what I have right now:
set file1 [open [lindex $argv 0] r] set pw1 [exec cat /home/user/.pw1.txt] set pw2 [exec cat /home/user/.pw2.txt] while <[gets $file1 host] != -1> < puts $host spawn -noecho "ssh $host" expect < "continue connecting"< send "yes\r" expect < "current" < send $pw2\r >"New password" < send $pw1\r >"Retype new password" < send $pw1\r >> expect "msnyder" send "exit\r" > interact >
The variable named file1 contains the list of hosts where the script will be executed.
Despite the fact that it errors on line 22, I am unable to identify the issue that needs to be rectified.
- The «continue connecting» block is likely missing a closing brace.
- The «continue connecting» statement is missing a space before the opening brace, which is a crucial detail in Tcl (and Expect) because whitespace is parsed into separate words before executing the commands. If you want to learn more about this, refer to the 12 syntax rules of Tcl.
Your code might look like:
while <[gets $file1 host] != -1> < puts $host spawn -noecho "ssh $host" expect < "continue connecting" < send "yes\r" expect < "current" < send -- $pw2\r exp_continue >"New password" < send -- $pw1\r exp_continue >"Retype new password" < send -- $pw1\r exp_continue >msnyder > send "exit\r" > > interact >
- The exp_continue enables a loop that returns to the expect statement. It is crucial not to exit the loop until you see the prompt, as you expect to encounter «current,» «new,» and «retype» during the process.
- Develop the practice of typing the send — something with a double dash to prevent any surprises in case someone enters a password beginning with a dash.
Instead of simulating human behavior in running the script, consider creating a failed ssh connection that will automatically accept the host RSA key without asking for a password. This can be done for systems that have already been set up, and the password prompt can be introduced for new systems that require it.
Add this to your ~/.ssh/config file on a temporary basis until the completion of your script.
Host * Protocol 2 PasswordAuthentication 0 StrictHostKeyChecking 'no' CheckHostIP 'no' UserKnownHostsFile ~/.ssh/known_hosts_new
Once you have loaded the new know_hosts_new file, you can substitute the default ~/.ssh/known_hosts and eliminate the UserKnownHostsFile line from your configuration.
Linux — Using if/else in expect script, I recently updated and reformatted my /etc/hosts file and would like to run through every system (roughly 1000) to refresh my known_hosts file. I’m looking at using an expect script to send «yes» to the RSA fingerprint question. Simple enough. However, I know some of these systems are completely new to …
How can I use a variable in if condition in expect script?
An expect script is being executed on a remote host (let’s call it A). The aim is to retrieve certain environment variables from this remote host (A) and then carry out certain conditional operations actions on both host (A) and the host (B) where the expect script is being executed, based on the values of the environment variables on host (A).
While I was able to retrieve the remote variables and assign them values, I encountered difficulties executing the if condition, perhaps due to my struggle with determining the correct syntax or format.
Attempted to utilize resources from Google but was unable to come up with an effective resolution.
send "export vers=`rpm -q --queryformat '%' rpm | grep -o '.$'`\r" send "echo \$vers\r" expect -re $prompt send "`if [[ \$vers -lt 7 ]]; then echo 'RHEL Version is \$vers'; else echo 'RHEL Version is \$vers'; fi`\r"
invalid command name "$vers" while executing "\$vers -lt 7 " invoked from within "[ \$vers -lt 7 ]" invoked from within "send "`if [[ \$vers -lt 7 ]]; then echo 'RHEL Version is \$vers'; else echo 'RHEL Version is \$vers'; fi`\r""
Require an expect script that can properly execute the «if» condition and transfer the resulting value to both my local device and the remote host.
To follow @glenn-jackman’s suggestions, ensure to monitor the usage of single quotes. If you are using bash, consider replacing them with double quotes. For more information, refer to http://www.gnu.org/software/bash/manual/html_node/Single-Quotes.html.
Tcl, which is an extension of expect, employs square brackets for command substitution, similar to how the shell uses backticks. To avoid any issues, it’s necessary to escape the brackets in double quoted strings.
send "if \[\[ \$vers -lt 7 \]\]; then echo 'RHEL Version is \$vers'; else echo 'RHEL Version is \$vers'; fi\r"
One way to circumvent the usage of backslashes is to employ Tcl’s non-interpolating quoting mechanism.
In Tcl, curly braces function similarly to single quotes in shell.
It is worth mentioning that the command no longer includes backticks.
This Q&A centers around rules 4, 6, and 7 of the Tcl language, which can be fully understood by following the 12 rules described in this document. Additionally, rules 8 and 9 are also relevant to this discussion.
Bash — How can I use a variable in if condition in expect, Need the expect script to execute «if» condition correctly and pass the value to the remote host and my local. bash expect rhel. Share. Making statements based on opinion; back them up with references or personal experience. To learn more, see our tips on writing great answers. Sign
If condition for comparing a string in Expect script
My expect script requires me to verify the output of the command ‘uname -a’.
I need assistance with creating the appropriate if condition for executing remote commands using expect. The commands to be executed depend on whether the remote server is Linux or Aix. If it is Linux, a specific set of remote commands will be run, while if it is Aix, a different set of commands will be executed.
expect "Permission denied" < incr count exp_continue >> set strname LINUX set results $expect_out(buffer) if < puts $results >EOF
The output of the uname -a command will contain more information than just the words Linux or Aix . Therefore, it is recommended to utilize regexp to check for their existence.
#!/bin/bash expect eof "password:" "Permission denied" > set results $expect_out(buffer) if <[regexp -nocase "Linux" $results]> < puts "It is a Linux Machine" >elseif <[regexp -nocase "Aix" $results]> < puts "It is a AIX machine" >else < puts "Unknown machine" >EOF
Alternatively, if you solely utilize the uname command, you will receive only the necessary output, and your provided code will function correctly.
Shell — If condition for comparing a string in Expect script, I have a expect script where I want to check uname -a. if the remote server is Linux then I will run few more remote command using expect. If it is Aix then I will run few other set of commands. Stack Overflow. Making statements based on opinion; back them up with references or personal experience.
Using if/else in expect script
I think I have a basic grasp of the concept of «if/else» in expect, but I don’t fully understand how to nest them, if there is a better way, or if I’m completely off-base to begin with.
This is what I have right now:
set file1 [open [lindex $argv 0] r] set pw1 [exec cat /home/user/.pw1.txt] set pw2 [exec cat /home/user/.pw2.txt] while <[gets $file1 host] != -1> < puts $host spawn -noecho "ssh $host" expect < "continue connecting"< send "yes\r" expect < "current" < send $pw2\r >"New password" < send $pw1\r >"Retype new password" < send $pw1\r >> expect "msnyder" send "exit\r" > interact >
The file1 variable is the list of hosts to run the script against.
I know it isn’t accurate because it errors on line 22. But, I have no idea what needs to be fixed.
2 Answers 2
- missing close brace, probably for the «continue connecting» block
- missing space before the open brace of «continue connecting». Tcl (hence Expect) is very sensitive to whitespace as it is parsed into words before the commands are evaluated. For the very few gory details, see the 12 syntax rules of Tcl.
Your code might look like:
while <[gets $file1 host] != -1> < puts $host spawn -noecho "ssh $host" expect < "continue connecting" < send "yes\r" expect < "current" < send -- $pw2\r exp_continue >"New password" < send -- $pw1\r exp_continue >"Retype new password" < send -- $pw1\r exp_continue >msnyder > send "exit\r" > > interact >
- exp_continue is used to «loop» back up to the expect statement: in this case, you will expect to see all of «current», «new» and «retype», so you don’t want to bail out until you see your prompt.
- get into the habit of typing send — something . Without the double dash, you’ll be surprised the day someone types in a password with a leading dash.
Thank you. I’m looking through the code before I run it so I can get a feel for what it’s doing and how to implement similar methods in the future. One thing that dawned on me is that I now have a couple systems that don’t need the RSA fingerprint to be accepted. Does this script assume it will be asked? If it doesn’t appear and drops straight to the command prompt on the remote server will the block be short-circuited and simply send the «exit» from the msnyder block? Seems like I would just need to move it up one level to be an «else» under the «continue connecting» «if». Is that correct?
Or maybe I need it in two places: once after accepting the RSA fingerprint if presented and once in lieu of the RSA fingerprint if I’ve already accepted it.
I ran the script. I think I’m seeing some changes that can be made to my method, but I»m running into problems with it. I’ll probably consider this issue resolved and open another question with the new problem to keep a separation of issues.