expect script works while invoking individually but not as a salt state - bash

I'm trying to do scp as well as ssh through expect. Below script works if I invoke it directly from terminal like /usr/bin/expect myexpect.sh but when I ran it using salt, the first scp command works where the second ssh fails.
myexpect.sh
#!/usr/bin/expect -f
set timeout 240
spawn scp apps.tar.gz /srv/salt/integration/serverclass_merged.conf foo#10.10.10.10:/home/foo
expect "password:"
send "password\n";
expect eof
spawn ssh -o StrictHostKeyChecking=no foo#10.10.10.10 "cd /home/foo;tar --strip-components=1 -xzvf apps.tar.gz -C /opt/apps/;cp serverclass_merged.conf /opt/local/serverclass.conf"
expect "assword:"
send "password\r"
interact
Relevant salt state looks like,
st.sls
copy_apps:
cmd.run:
- name: /usr/bin/expect /home/ocdn_adm/myexpect.sh

I know nothing about salt-stack but I suspect it's not running your Expect script from a pty. So replace interact with expect eof (or expect -timeout 12345 eof if necessary). interact works only when stdin is on a tty/pty.

Related

How to match this [admin#MikroTik] > in bash script (expect)?

I am trying to write a script that will auto configure mikrotik router, but some weird character appears as soon as password is sent through the script and logins the router. Below is the script that i wrote,
#!/bin/bash
read -p "Enter IP Address: " Public_IP
read -p "Enter username: " Username
read -sp "Enter Password: " Password
echo
expect -c "
spawn ssh -o StrictHostKeyChecking=no $Username#$Public_IP
set timeout -1
expect "password:"
send "$Password\r"
expect "\[admin*"
sleep 4
expect "\[admin*"
"
While I run this script I see below the following in the image,
So what i want to accomplish is to see the second image and send some commands for example;
/ip arp print
send above commmand for instance.
image after running the script
the actual interface i want to get and send command like that
you need to add +tc after username in ssh command
spawn ssh -o StrictHostKeyChecking=no $Username+tc#$Public_IP
it´s works for me

How to run remote script with sudo access

I am trying to run a remote script which need to run as a sudo but its unable to run the script as sudo. Is my approach is correct to do sudo? Please help..Thanks in advance.
spawn ssh -t {*}$ssh_opts $user#$ip bash $script {*}$argv
Try this :-
#!/usr/bin/expect
set timeout -1
spawn -noecho bash -c "ssh user#host \"sudo su -c 'your_command' - sudo_user\""
expect {
-re ".*assword:"{
send "password\r"
exp_continue
} eof {
wait
}
}
Hope it helps.!!!

sftp not working using expect

I am doing the sftp using a bash script, the script is running and it starts the sftp process and also completes it but it does not copy the complete data.( as my data size is approx. 600 MB it only copyies 800KB and terminates. the same is working fine when doing manually.
Below is my script content
#!/bin/bash
HOST=x.x.x.x
PORT=22
USER=abc
PASSWORD=password
SOURCE_FILE=/nobackup/file.gz
TARGET_DIR=/home
/usr/bin/expect<<!
spawn /usr/bin/sftp -o Port=$PORT $USER#$HOST
expect "password:"
send "$PASSWORD\r"
expect "sftp>"
send "get $SOURCE_FILE $TARGET_DIR\r"
expect "sftp>"
send "bye\r"
!
Please help.
My implementation of sftp allows a batch mode, why do you need the expect-script?
.
.
echo "get $SOURCE_FILE $TARGET_DIR" | sftp -b - -o Port=$PORT $USER#$HOST
Consider lftp, which is explicitly built to be scriptable (and supports, among a great many protocols, sftp):
user=abc
password=password
host=x.x.x.x
port=22
source_file=/nobackup/file.gz
target_dir=/home
printf -v cmd 'open %q; get -o %q %q' \
"sftp://$user:$password#$host:$port/" \
"${target_dir}/${source_file##*/}" \
"$source_file"
lftp -c "$cmd"
The printf generates a string akin to the following:
open sftp://abc:password#x.x.x.x:22/; get -o /home/file.gz /nobackup/file.gz
...which is a valid lftp script.

cannot execute command after logging in with expect

I have the following script:
#!/usr/bin/expect -f
set timeout 60
spawn ssh -X user#login.domain.co.uk
expect "Password:"
# Send the password, and then wait for a shell prompt.
send "password\r"
exp_continue
expect "user*"
send "ls -la\r"
however I get the following:
Password: command returned bad code: -101
while executing
"exp_continue"
(file "./hpclogin.sh" line 10)
If I remove the exp_continue i.e.
#!/usr/bin/expect -f
set timeout 60
spawn ssh -X user#login.domain.co.uk
expect "Password:"
# Send the password, and then wait for a shell prompt.
send "password\r"
expect "user*"
send "ls -la\r"
I can log in successfully, however the ls -la command does not get executed. Is there something wrong with the flow-control of my program?
exp_continue is only useful inside an expect block. For example:
spawn ssh -X user#example.com
expect {
"continue connecting (yes/no)? " {
send "yes\r"
exp_continue"
}
"Password:"
}
send "password\r"
I think you're not seeing the ls output because you're not expecting to see anything after to send it. Depending on your workflow, here are 2 thoughts:
add the command as arguments to ssh
spawn ssh -X user#example.com ls -la
expect {
"continue connecting (yes/no)? " {
send "yes\r"
exp_continue"
}
"Password:"
}
send "password\r"
expect eof
expect a prompt after the command, and log out afterwards
spawn ssh -X user#example.com
expect {
"continue connecting (yes/no)? " {
send "yes\r"
exp_continue"
}
"Password:"
}
send "password\r"
expect $theprompt
send "ls -la\r"
expect $theprompt
send "exit\r"
expect eof
Of course, this would be much simpler using ssh keys:
ssh-keygen
ssh-copy-id user#example.com
ssh -X user#example.com ls -la

Issuing commands on remote linux

I'm looking for any way to do this task with expect:
Mac-mini:~ root# scp file peter#Mac-mini:file2
The authenticity of host 'mac-mini (192.168.1.105)' can't be established.
RSA key fingerprint is b6:12:3e:48:10:e6:d2:1f:8f:57:f4:01:2d:f3:23:89.
Are you sure you want to continue connecting (yes/no)? yes
Password: ********
and issue
crontab -l > crontab.src
#!/usr/bin/expect
set machine0 "Mac-minimini"
set machine1 "Mac-mini"
set machine2 "Mac-pro"
...
set machine19 "Mac-air"
for {set i 1} {$i < 20} {incr i 1} {
eval spawn scp file peter#${machine${i}}:file2
expect "connecting (yes/no)?"
send "yes\r"
#use correct prompt
set prompt ":|#|\\\$"
interact -o -nobuffer -re $prompt return
send "password\r"
interact -o -nobuffer -re $prompt return
send "crontab -l > crontab.src\r"
interact
}
Edit: You can use for loop and concatenate names for each machine using the variable of the loop.(e.g. Mac-mini0, Mac-mini1, ... Mac-mini19)
Edit2: I am not sure if ${machine${i}} works but worth to try..
Set up an ssh key like so:
ssh-keygen -t rsa
Place your public key on the remote machine (assuming you create a key in your home directory called id_rsa)
ssh-copy-id peter#Mac-mini
Then you will be able to scp without entering a password.
autoexpect -f scp file peter#Mac-mini:file2
For the crontab part, am assuming you mean on the remote machine.
autoexpect -f crontab ssh peter#Mac-mini "crontab -l > crontab.src"

Resources