sftp not working using expect - bash

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.

Related

How to run expect script from remote server via ssh?

I have deployed an expect script on a remote server, which I want to run via ssh.
ssh user#host 'expect -d ./netopeer_expect.sh' (1)
user#host:~$ cat netopeer_expect.sh
#!/usr/bin/expect
set timeout 5
#spawn netopeer2-cli
spawn ./np2_multi_cli
expect ">"
send "listen --timeout 120\r"
expect "ru_id 0"
send "get-config -D=0 --source running --out /home/user/out.xml\r"
expect ">"
send "exit\r"
expect "$"
This code runs a modified version of the netopeer2-cli, which we call ./np2_multi_cli. This netopeer2-cli have an own shell and a prompt like >. It works fine when I do it in two steps
ssh user#host
expect -d ./netopeer_expect.sh (2)
However, the message
send "get-config -D=0 --source running --out /home/user/out.xml\r"
is cut and is sent as,
send "-D=0 --source running --out /home/user/out.xml\r"
From running (1) with the -d argument I see this,
expect: does "\u001b[6n" (spawn_id exp3) match glob pattern ">"? no
When I try to match the first >. When I instead try to run (2), it looks as it should,
expect: does "> " (spawn_id exp4) match glob pattern ">"? yes
I run bash and it seems as if there are some encoding issues regarding the > character. Any idea how to deal with this?
BR
Patrik
Did some investigation and found out why ssh -t makes a difference in patrik's answer. See the following examples:
According to Expect manual:
Internally, spawn uses a pty, initialized the same way as the user's tty.
With -t, ssh would allocate a pty (the same type as the local $TERM) for the remote session, then expect allocates a pty of the same type.
Without -t, ssh would not allocate pty for the remote session, and expect uses the (default?) dumb tty which is not fully featured. As a "workaround", we can explicityly set the TERM var (e.g. set env(TERM) vt100) before spawn.
Here's the command I used. Just for easy copy-and-paste.
[STEP 101] # cmd=' "spawn -noe bash -c {echo TERM=\$TERM | grep --color TERM}; expect eof" '
[STEP 102] #
[STEP 103] # ssh 127.0.0.1 expect -c "$cmd"
TERM=dumb
[STEP 104] # ssh -t 127.0.0.1 expect -c "$cmd"
TERM=linux
Connection to 127.0.0.1 closed.
[STEP 105] #
[STEP 106] # cmd=' "set env(TERM) vt100; spawn -noe bash -c {echo TERM=\$TERM | grep --color TERM}; expect eof" '
[STEP 107] # ssh 127.0.0.1 expect -c "$cmd"
TERM=vt100
[STEP 108] #
Looks as if I made a faulty call when I was running ssh. I forced pseudo terminal allocation it went fine,
ssh -t -t erusim#147.214.83.188 'expect -d ./netopeer_expect.sh'

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

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.

Script with condition

I am a beginner in the development of scripts.I want to do 4 tasks in one script:
1. Connect to machine 1 by ssh
2.Retrieve the data and put it in a CSV file
3.Send the CSV file to a directory
4.connect to machine 2 by ssh and do step 2 and 3
Fisrt test :
#!/bin/bash
#Settings
DATE=$(date +%Y_%m_%d)
DATE1=$(date +%d/%m/%Y)
HIER=$(date -d '1 day ago' "+%Y-%m-%d")
HEURE=$(date +"%T")
#Ip adress of the machine
machine1= IP1
machine2= IP2
#Connexion SSH OLT1
ssh root#IP1
#Command for geting data on machine
enable
config
display XXXX > IP1.csv
#exit connection
exit
I do not have any result so i think
Do i make a loop for executing the task for the 2 machines?
Thanks
I'm trying tu use expect because i find RSA key problem by using SSH and shell script
#spawn ssh $host -l $user
expect "login:"
send "root\r"
expect "passe:"
send "test\r"
expect -re $prompt
send "terminal length 0\r"
expect -re $prompt
send "enable\r"
expect -re $prompt
send "config\r"
expect -re $prompt
send "display .....\r"
expect -re "\r\nend\r\n"
send "exit\r"
I don't know how i can put the result on csv file to a directory?
Besides, can i put the IP on #spawn assume that task should be done on 2 machines
Thanks for your feedback
I try thisaccording to your sample but the ouput file is empty:
#!/usr/bin/expect
spawn ssh X.X.X.X -l root
expect "User password:"
send "admin\n"
expect -re "device>"
send "enable\r"
expect -re "device#"
send "config\r"
expect -re "device(config)#"
send "display .......\r"
expect -re "{ <cr>||<K> }:"
send "\r"
set date [timestamp -format %C%y%m%d]
log_file -noappend /home/device/CSTtest.csv
You can run your command and export to out file in same ssh call like this:
# ...
# first machine command
ssh root#IP1 "<COMMAND>" > /PATH_LOCAL_TO_SAVE_FILE/IP1.csv
# second machine command
ssh root#IP2 "<COMMAND>" > /PATH_LOCAL_TO_SAVE_FILE/IP2.csv

Execute commands after sshpass login in the script

I'm an Ubuntu bash newbie. I successfully login to an sFTP server using sshpass. But once the connection is established I also need to download a directory from the server. My script cannot seem to pass the connection line though. This is what I have in my script (.sh) file:
#!/bin/bash
sshpass -p 'MY_PASSWORD' sftp -o StrictHostKeyChecking=no -o HostKeyAlgorithms=+ssh-dss MYUSER#MYSFTPSERVERADDRESS
echo "hello"
get -r Export
In the snipped above, my echo and my get are not executed. The terminal is waiting for my input with a sftp> prompt.
You would be better served using scp instead of sftp and sharing keys instead of putting the password in a script if you're able, but if you must use sftp for some reason, it can take its commands from a heredoc like:
sshpass -p 'MY_PASS' sftp -o StrictHostKeyChecking=no -o HostKeyAlgorithms=+ssh-dss MYUSER#MYSFTPSERVERADDRESS <<EOF
get -r Export
EOF
note that echo isn't a valid sftp command.
You can put whatever commands you want sftp to execute before the EOF and it will do them each in turn.
If all you want is to get that directory it's probably still simpler to use scp if you can:
sshpass -p 'MY_PASSWORD' scp -o StrictHostKeyChecking=no -o HostKeyAlgorithms=+ssh-dss -r MYUSER#MYSFTPSERVERADDRESS:Export .

multiple commands in spawn script to copy keys

I'm trying to create a script to copy ssh keys to multiple servers for passwordless login. I have a list of servers entered one per line in serverlist.txt. Below is the script I created.
#!/usr/bin/expect -f
set f [open "serverlist.txt"]
set hosts [split [read $f] "\n"]
close $f
foreach host $hosts {
spawn -noecho sh -c "cat ~/.ssh/id_rsa.pub | ssh -t -o StrictHostKeyChecking=no $host 'mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys'"
expect "assword:";
send "abc123\r"; # sending the password
expect "$"; #expecting the $prompt
send "exit\r";
interact
}
Im getting below error while running this script
send: spawn id exp4 not open
while executing
"send "exit\r""
("foreach" body line 6)
invoked from within
"foreach host $hosts {
spawn -noecho sh -c "cat ~/.ssh/id_rsa.pub | ssh -t -o StrictHostKeyChecking=no $host 'mkdir -p ~/.ssh && cat >> ~/.ssh/authori..."
(file "sshkeys" line 6)
If i commented below lines I'm getting diff error
#expect "assword:";
#send "abc123\r";
#expect "$";
#send "exit\r";
Pseudo-terminal will not be allocated because stdin is not a terminal.
user#1.1.1.1's password:
Pseudo-terminal will not be allocated because stdin is not a terminal.
ssh: mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys: Name or service not known
Note:
ssh-copy-id is not available.
None of the target servers have the .ssh directory created.
Can somebody help me to identify the issue.

Resources