expect with nested shell script - linux

I have a shell script batch_wrapper.sh which takes user input and it invokes another script batch.sh.
These two script work perfectly fine.
Now, I have created a expect script test.sh which invokes batch_wrapper.sh and provides the input parameter.
However, for some reason, batch.sh script is not getting invoked which I spawn batch_wrapper.sh from expect script. How can I fix this?
Sample expect script is:
#!/usr/bin/expect
set timeout 2000
spawn "./batch_wrapper.sh"
expect "username" {send "Vikas\r" }
Sample Shell Scripts are:
batch_wrapper.sh
#!/bin/bash
echo "enter username"
read name
echo "your name is $name"
./batch.sh
batch.sh
#!/bin/bash
echo "Inside batch"
echo "exiting batch"

Your script exits immediately afterwards as there's nothing left to do.
You can add interact or expect eof {} as the last line in your expect script to make it process the remainding output:
$ cat lol.expect
#!/usr/bin/expect
set timeout 2000
spawn "./batch_wrapper.sh"
expect "username" {send "Vikas\r" }
expect eof {}
$ expect -f lol.expect
spawn ./batch_wrapper.sh
enter username
Vikas
your name is Vikas
Inside batch
exiting batch

Related

Invalid command error 'mkdir' while excuting #expect script

The expect script returning invalid command while I trying to create a folder after login to server via ssh
This is the below error I got
invalid command name "mkdir"
while executing
"mkdir new"
(file "./connecttotravalour.exp" line 8)
And the code on my expect script is :
#!/bin/bash
#connect to travalour host
spawn ssh travalour#travalour.local
expect "password"
send "P#ssw0rd\r"
interact
mkdir new
Posting an answer form askubuntu for similar question
The main thrust of expect programming is send and expect pairs: you send some text to the spawned process and expect a response. In this case, you send the mkdir command, and expect to see your prompt to know that the command has completed. Prompts are best matched as regular expressions to match the end of it. Since prompts are so configurable, you might want to edit the prompt expression: this one matches a literal dollar sign and a space at the end of the string.
#!/bin/bash
#connect to travalour host
spawn ssh travalour#travalour.local
expect "password"
send "P#ssw0rd\r"
set prompt_re {\$ $}
expect -re $prompt_re
send "mkdir -p new"
expect -re $prompt_re
interact

Run "read" bash command within ssh expect script

Is there a way to execute a "read" command from a spawned ssh subprocess through expect? When I try the below code, read doesn't recognize end of input through "ENTER" key (it just goes to next line). I tried other "read" options (e.g. limiting number of characters, timeout, etc.) but they do not work. I know there are ways to get user input within Expect script itself but I need the input to be received through a bash command.
function foo() {
expect <<EOF
set timeout -1
spawn ssh -t $1
expect "]"
send "read x\r"
expect "]"
send "echo $x\r"
expect "]"
send "exit\r"
expect eof
EOF
}

Executing an if statement after a specific output in expect script

Is there a way to execute an if statement if I see a specific output? For example, when the console says "bad interpreter permission denied" I want to execute a command like "dos2unix file_name"?
So the logic will be like the following,
if (output is "bad interpreter permission denied")
{
send dos2unix file_name
}
fi
This is an expect script.
Edit:
Could I do something like this in an expect script?
if (grep -cim1 '^M$' lruload.sh) -eq 1; then
send dos2unix filename
fi
When you say execute the commands, I hope you meant to execute the command in the shell. You can use exec command for this purpose.
I'm not sure where you are interacting. I mean like telnet or ftp or bash. Anyway, under any case, you will be sending a command and expecting a prompt.
send "command 1"
expect "prompt"
send "command 2"
expect {
timeout { puts "timeout happened"}
"bad interpreter per mission denied" {
set result [exec dos2unix <filename>]
}
}
# if need to intact with three application, further use 'send' and 'expect'
You have the result variable to store the dos2unix output.
How about this logic/psuedo-code?
export cmdText=`myCmd param1 param2 2>&1`
if ($cmdText is "bad interpreter permission denied")
{
send dos2unix file_name
}
fi
The permission denied text probably went to stderr, not stdout, so the redirect 2>&1 lumps both of them together, making the test simple.

Using ssh through an expect script on cygwin

I'm trying to execute commands remotely over ssh using an expect script that will log in with a password. So far I have the following script (details changed of course):
#!/usr/bin/expect
spawn ssh user1#cpu3.lab.ie
expect "password:"
send "psw123\r"
expect "$"
send "mkdir pswdtest\r"
I name this script testpswd.sh and then runchmod +x testpswd.sh, d2u testpswd.sh and ./testpswd.sh.
Apparently the script manages to login because I get the Last login:... prompt. However, after this the script seems to wait for a bit and then exit back out of ssh, without making a directory called pswdtest (as I can check afterwards).
I have tried looking up tutorials etc and changing the script above in all ways I could think of, e.g. expect "user1#cpu3:~$"instead of expect "$" and so on.
I'm running windows and use cygwin (hence the d2u), and the network I'm logging into uses Linux.
Any ideas?
While developing an expect script, always add exp_internal 1 at the top of the script: expect will show you what it's matching (or not).
Perhaps you could match the prompt with this: expect -re {\$\s*$}
After you send something, you should expect something
exp_internal 1
set prompt {\$\s*$}
spawn ssh user1#cpu3.lab.ie
expect "password:"
send "psw123\r"
expect -re $prompt
send "mkdir pswdtest\r"
expect -re $prompt
send "exit\r"
expect eof

Linux Shell Script: Save command outputs in variable/file?

I want to use some output of a command, but I don't know, how I can save the output in a variable or file.
The script is connecting to a specified server via telnet and executes different commands. One command is needed for further commands. Well... I have to save these informations from the command output.
My code:
#!/bin/bash
(
echo open server portnumber
sleep 2s
echo "login username password"
sleep 1s
echo "use sid=1"
CLIENT_LIST=$(echo "clientlist")
sleep 1s
echo "clientupdate client_nickname=Administrator"
for client_id in $(echo $CLIENT_LIST | grep -Eo "clid=[0-9]+" | grep -Eo "[0-9]+"); do
echo "clientpoke clid=$client_id msg=How\sare\syou!"
sleep 1s
done
sleep 1s
echo "logout"
echo "quit"
) | telnet
I want to save the output of the command 'clientlist' in a variable or file. A variable would be the best solution. But actually the variable just saves 'clientlist' and not the output of the command. :(
I hope somebody can help me. Thanks in advance! :)
If you want to test it: It's made for TeamSpeak 3 server.
To run the command 'clientlist' and save the output in a variable:
output_var=$(clientlist)
In bash or sh, the $(...) syntax means "run this command and return whatever output it produces."
If by this question you mean "I want to run the clientlist command on the remote machine, then capture its output to a variable on the local machine", then you can't do this using something like your script. (Note that you script only pipes input into the telnet command; telnet's output isn't captured anywhere.)
You'll need to write a script using something like expect, or one of its work-alikes in another language like Perl or Python.

Resources