How to use telnet in a script? - bash

I need to connect in a system where I have to SSH first then telnet. Then I can start executing some command.
I am struggling about the telnet part. Can you tell me how I can make it please? Is there another alternative than spawn please? Thank you
#!/bin/bash
cat command.sh | sshpass -p 'passowrd' ssh -q -o StrictHostKeyChecking=no root#pc1;
Then my command.sh
#!/bin/bash
spawn telnet pc_modem
expect "login:"
send "root"
expect "Password:"
send "youyou"
cliclient GetMonitoringData;

In this use, the shebang has no effect*. You're passing the contents of the script file to ssh to be executed line by line as if each line were separate commands that will be interpreted by the shell instead of expect.
Try changing command.sh to something like:
# no shebang here
/bin/expect -f - <<<'spawn telnet pc_modem
expect "login:"
send "root"
expect "Password:"
send "youyou"
cliclient GetMonitoringData;'
This sends the expect script as a here string to expect's STDIN. If you use variables in your expect script you may need to change the quoting or escaping depending on whether they are shell or TCL variables and where the substitution needs to take place.
* The shebang is used by the kernel to select the program to interpret the contents of the file when the file has been marked as executable and is run by invoking the file by its name. When a file is run by explicitly naming the interpreter (e.g. sh run_me or ssh user#host run_me_there) the shebang doesn't come in to play.

I find out the answer and works perfectly :
/bin/expect <<<'spawn telnet pc_modem
expect "login:"
send "root\r"
expect "Password: ";
send "youyou\r"
send "yourcommand1\r"
send "yourcommand2\r"
expect eof
'

Related

Automate ssh connection with expect in a bash script

Im trying to do a shell script using expect to automate connection because it's not allow to use ssh keys. Its my first script with expect and I find a little bit confuse for me. In this case I can connect by ssh but I can't close the connection, I don't know how to do, any idea ??
#!/bin/bash
user=pepe
host=server
pass=`cat /tmp/password.txt`
COMMAND=df
PASSWORD=$pass expect -c "
spawn ssh $user#$host
expect "*assword*"
send \$env(PASSWORD)\r
expect {
"*be*" {send $COMMAND\r;interact}}
"
The immediate fix is to specify the command as an argument to ssh -- then the connection will be made and the command will run and the connection will close
#!/bin/bash
user=pepe
host=server
pass=`cat /tmp/password.txt`
COMMAND=df
PASSWORD=$pass expect -c "
spawn ssh $user#$host $COMMAND
expect \"*assword*\"
send \$env(PASSWORD)\r
expect eof
"
A couple of things to note:
expect eof will gracefully wait for the spawned command to exit
I've escaped the internal double quotes.
Next step is to tidy up the quoting/escaping. When embedding code for another language in a shell script, using a quoted heredoc is the best way to avoid quoting hell. This means that all the shell variables need to passed to expect via the environment
#!/bin/bash
export user=pepe
export host=server
export pass=`cat /tmp/password.txt`
export cmd=df
expect << 'END_EXPECT'
spawn ssh $env(user)#$env(host) $env(cmd)
expect "*assword*"
send $env(pass)\r
expect eof
END_EXPECT
Last thing I'd do is to reduce the exposure of the password. Expect is built on the tcl language, which is fully capable of reading files:
#!/bin/bash
export user=pepe
export host=server
export pass=`cat /tmp/password.txt`
export cmd=df
expect << 'END_EXPECT'
set fh [open /tmp/password.txt]
gets $fh pass
close $fh
spawn ssh $env(user)#$env(host) $env(cmd)
expect "*assword*"
send $pass\r
expect eof
END_EXPECT
And make sure the permissions on that password file are as restrictive as possible:
mv /tmp/password.txt ~/.local/share/pass.txt
chmod 0400 ~/.local/share/pass.txt

Passing variable to Expect and Spawn

I'm writing a script that will scp a tar file from my local server to a remote host. Since the script generates the file through a pre-requisite process, the name is generated dynamically. My script needs to take the name of the file and pass it to scp for transfer.
#!/usr/bin/expect -f
spawn scp test.$(date +%y%m%d_%H%M).tar user#IP-ADDRESS:/destination/folder
set pass "password"
expect "password: "
send -- "$pass\r"
expect eof
I've tried setting the filename as a variable but keep seeing the same error:
can't read "(date +%y%m%d_%H%M)": no such variable
while executing "spawn scp test.$(date +%y%m%d_%H%M).tar user#IP-ADDRESS:/destination/folder"
$(date +%y%m%d_%H%M) is not a Tcl command. If you use expect, you have to learn Tcl. To get a formatted date in Tcl, use the clock command. Also, interpolation of the result from a command in Tcl is not done by $(....), but by [....]. You can find examples for this construct here.
Decided to go another route since the team was able to provision a new Artifactory repo for this binary and alike. However, to the advice provided here I was able to make a few discoveries which I used to fix my issues:
I also had a password with $ symbol and that also caused a world of issues.
#!/bin/bash
TEST=$(date +%y%m%d_%H%M)
/usr/bin/expect <<eof
set password {pas\$word}
spawn scp "$TEST" user#IP-ADDRESS:/destination/folder
expect "*password:"
send "$pasword\r"
expect eof

How to execute a expect script while connecting to a ssh server

For example, now I have a "root.exp" expect script as following:
spawn ssh user#ip
expect "Password:"
send "password"
Then, the expect command I want to send to this ssh server is stored in another expect script file branch.exp, which for example is as following:
expect ">>"
send "ls"
My question is, how to call this branch.exp in root.exp? For example, something like following in the root.exp:
spawn ssh user#ip
expect "Password:"
send "password"
*call* branch.exp
As Johannes said, you can use the source command. The Expect and TCL mini reference manual says:
source Procedures and variables can be stored in other files and read using the source command. As the file is read, the commands are executed.
Example:
source ~/def.tcl

pass username, pwd, server information in expect shell scripting

I want to pass all the remote server names as shell script arguments and then want my script to copy the given file/directory to all remote servers. Below is my code.
#!/bin/bash
/usr/bin/expect <<EOD
#connect via scp
usr=Joe
pwd=Password
file_location=/home/file1.txt
for a in $#
do
spawn scp -r $file_location "$usr#$a:$file_location"
expect -nocase "password: "
send "$pwd\r"
expect eof
EOD
Username and password is same for all the remote servers. So I am hard-coding them for time being but while running the script I see a problem with that..
>./scp1.sh server1 server2
invalid command name "usr=Joe"
while executing
"usr=Joe"
Any help is appreciated. Thanks!
To read command line arguments from expect:
$argc - number items of arguments passed to a script.
$argv - list of the arguments.
$argv0 - name of the script.
This was take from this site
If you want more help with expect then google about tcl because expect is an extension to tcl language

Problems with terminating connection after running scripts on remote computer using shell script

This is the first time I am writing a shell script. I tried to do as much research as I can to avoid dumb/repetitive question. Please excuse if its repeat/dumb question.
I have a shell script which connects to remote linux machine and runs scripts there. I am using 'expect' to spawn a ssh connection and to issue commands to trigger the job. However, I am having issues while closing the connection after completing the job.
This is my script:
set prompt "(%|#|\\$|%\]) $"
expect -c 'spawn ssh $UN#$STAGE ;
expect password ; send "$PASS \n";
expect -regexp "$PROMPT"; send "./settings.$UN.sh > settings_log.txt \n";
interact'
This script successfully runs the script file for me ($UN and $STAGE parameters are input to the script. I omitted that here for simplicity). However, this leaves me with an open connection.
I tried to close the connection after running the script by using following instead of above
expect -c 'spawn ssh $UN#$STAGE ;
expect password ; send "$PASS \n";
expect -regexp "$PROMPT"; send "./settings.$UN.sh > settings_log.txt \n";
expect -regexp "$PROMPT"; send "exit \n"'
This does close the connection but I noticed that my script file did not run at all. Also the settings_log.txt is not generated at all.
Does this mean, that exit command is aborting the process before its completion? I tried using 'sleep' before exit but it did not help. Is there a better suggested way to terminate the connection when using expect?
Any help is appreciated.
with expect, you terminate your send commands with \r not \n, so
expect -c 'spawn ssh $UN#$STAGE
expect password
send "$PASS\r"
expect -regexp "$PROMPT"
send "./settings.$UN.sh > settings_log.txt\r"
expect -regexp "$PROMPT"
send "exit\r"
expect eof'
Note you can execute remote shell commands and copy files using ssh and scp, directly, without using expect.
For example,
scp ./settings.$UN.sh $UN#$STAGE:settings_log.txt
ssh $UN#$STAGE whatever-you-need-to-execute
The connection will close as soon as soon as whatever-you-need-to-execute completes.
Your outer script seems to be written in csh and sets a variable named "prompt", but your expect script is using a variable called "PROMPT". Try making the two variable names match case.

Resources