Failed to transfer some file with mput on sftp - bash

I have a problem with my script that allows me to transfer several excel files with SFTP, every day some file is not transmitted, it's not a problem of file content or name.
Here is the code:
sshpass -f password/pass_sftp sftp $SFTP_USER#$SFTP_HOST << EOF
cd /store/availability
mput *.csv
bye
EOF
Do you have any idea what it could be ?

The proper form of use for the command, for cat to use "EOF" as the pattern to indicate end of input, is to use the combination "<<-" followed by the {string}.
Your first line should read as:
sshpass -f password/pass_sftp sftp $SFTP_USER#$SFTP_HOST <<-EOF

The heredoc construct is sometimes misleading with interactive programs as you may face synchronization problems. That is to say that the interactive programs may not accept data until it prompts it or it can flush out the data received so far before displaying its prompt. This is why using a utility like expect which simulates an operator in front of the interactive tool is more robust.
Let's consider the following interactive program example which prompts for a first and a last name and simulates some activity between the two inputs:
#!/bin/bash
echo "Enter your first name: "
read fname
# Do some actions here and make some cleanup in the input buffer
read -t 1 -n 1000 garbage
echo "Enter your last name: "
read lname
echo you have entered $fname $lname
If we run it interactively, it works fine:
$ ./interact.sh
Enter your first name:
azerty
Enter your last name:
qwerty
you have entered azerty qwerty
But if we run it with an heredoc, it fails because the second input arrives too early:
$ ./interact.sh <<EOF
> azerty
> qwerty
> EOF
Enter your first name:
Enter your last name:
you have entered azerty
The heredoc does not provide the ability to synchronize with the displayed prompts.
With an expect script, it is possible to wait for the display of the prompts before entering the answers as a human being would do. Let's consider the following to automate interact.sh:
#!/usr/bin/expect
set timeout -1
spawn ./interact.sh
expect "first name:"
send "azerty\n"
expect "last name:"
send "qwerty\n"
expect eof
The execution result is the same as if a human interacted:
$ ./exp
spawn ./interact.sh
Enter your first name:
azerty
Enter your last name:
qwerty
you have entered azerty qwerty

Related

Bash script to operate another script

I am trying to create a bash script to operate another bash script through CRON without the need for human intervention.
The script needs to be able to interact with the other script so that it accomplishes:
Enter
Press a number..
Then takes you to another section of the script where you need to enter another number..
Then enter another number..
Press enter again..
I can't get the script to hit Enter correctly. What I have so far, "echo | ./module1.sh" flickers, even tried "echo "\n"" which doesn't work.
#!/bin/bash
cd /home/usernamehere/scripts
echo | ./module1.sh
echo "1"
This script requires a person to sit at the terminal while it finishes what it needs to or be run in a tmux session with the user safely exiting the session.
If everything is read from stdin (as opposed to from the terminal device--which is what passwd and screen editors do), and the script requires you to enter ENTER, 1, 2 and 3, you can run it with
printf '\n1\n2\n\3\n' | ./module1.sh
An alternative is with a here-document (read your shell's manual page):
./module1.sh << EOF
1
2
3
EOF

How can I login to a program in Linux with a .sh script?

I'm sure that this is somewhere on stack overflow, but I've been researching this for hours and none of the answers work.
I need to answer prompts in a .sh script to log in to different accounts automatically.
My script will not answer the prompts automatically.
#!/bin/bash
program9000 login
That part works fine.
Then i get a series of prompts and cannot figure out how to get the .sh script to reply automatically. I will be replying to these 4 prompts the same way every time.
Would you like to enter a new key?
I would like to reply
y
How would you like to authenticate?
1. enter password
2. do something else
3. do something else
q. Quit
I would like to reply
1
Enter your password, please
I would like to reply
mypassword
Enter your Domain name, please
I would like to reply
https://mydomain.mine.com
Please note that I am not writing the prompts, they are coming from program9000. I just want to reply with the same 4 responses every time.
The following have not worked in my .sh script
yes
echo
send
What should the following lines of my script look like?
Here are some things that don't work
#!/bin/bash
program9000 login
send "y"
send "1"
send "fakepassword"
send "https://fakedomain.com"
#!/bin/bash
program9000 login
{ send -- "y" }
{ send -- "1" }
{ send -- "fakepassword"
{ send -- "https://fakedomain.com" }
You can use expect language, available almost with every *nix distributive
You can send multiline "answerfile" or string to your program using redirection
program9000 login <<< "
y
1
fakepassword
https://fakedomain.com"
As others have already mentioned, use expect.
apt show expect
...
Description: Automates interactive applications
Expect is a tool for automating interactive applications according to a script.
Following the script, Expect knows what can be expected from a program and what
the correct response should be.
...
See the expect man page here
To install it on Debian or it's derivatives:
apt install expect
You can use expect.
My English is terrible.So I write a example.
fakeprogram9000.sh
assert_var()
{
if [ $1 != $2 ]; then
echo err; exit 1
fi
}
read -p 'Would you like to enter a new key?' var1
assert_var $var1 'y'
read -p 'How would you like to authenticate?' var1
assert_var $var1 '1'
read -p 'Enter your password, please' var1
assert_var $var1 'fakepassword'
read -p 'Enter your Domain name, please' var1
assert_var $var1 'https://fakedomain.com'
echo success
example.sh
#!/bin/bash
expect<<EOF
spawn bash ./fakeprogram9000.sh login
expect "Would you like to enter a new key?" {send "y\r"}
expect "How would you like to authenticate?" {send "1\r"}
expect "Enter your password, please" {send "fakepassword\r"}
expect "Enter your Domain name, please" {send "https://fakedomain.com\r"}
expect eof
EOF

Writing shell script using another shell script

I'm trying to automate running of a shell script that would take some user inputs at various points of its execution.
The basic logic that I've in my mind is copied below, but this is only for one input. I wanna run it recursively until the shell prompt is received after the original script completes its execution. I said recursively because, the question that prompts for an input and the input itself will be the same all the time.
#!/usr/bin/expect
spawn new.sh $1
expect "Please enter input:"
send "my_input"
Sharing any short-cut/simple method to achieve this will be highly appreciated.
You don't need expect to do this - read can read from a pipe as well as from user input, so you can pass the input through a pipe to your script. Example script:
#!/bin/bash
read -p "Please enter input: " input
echo "Input: $input"
Running the script prompts for input as normal, but if you pipe to it:
$ echo "Hello" | sh my_script.sh
Input: Hello
You said that your input is always the same - if so, then you can use yes (which just prints a given string over and over) to pass your script the input repeatedly:
yes "My input" | sh my_script.sh
This would run my_script.sh, any read commands within the script will read "My input".

How to make expect command in expect program script to wait for exact string matching

I want to know how to make expect command in expect script to wait for exact string to be matched before proceeding to next line in the script.
Bourne shell (sh) script:
#!/bin/sh
#!/usr/bin/expect
spawn ssh -Y localuser#lbblr-tirumala
expect -exact "localuser#lbblr-tirumala's password: "
# replace password with ur own passwd
send "geomax45\r"
# replace the prompt with ur own prompt
expect "localuser#lbblr-tirumala:~$ "
# run application
send "./sample\r"
expect "*Menu*\r
1. print hello world\r
2. print Bye world\r
3. quit\r
enter choice: "
# enter choice 1
send "1\r"
expect "Bye world\r
*Menu*\r
1. print hello world\r
2. print Bye world\r
3. quit\r
enter choice: $"
# enter choice 2
send "2\r"
In the above code after entering 1 the code should wait for "Bye world\r......" string to occur on the screen. But even though the screen prompts different string altogether, the code is executing the next line and entering option 2, which should not occur as per definition of expect. It should wait until the complete string in expect command matches.
I want to know whether there is any stricter command that can be used so that expect waits until exact string matching occurs. Please help me in this issue
You're already using it earlier in your script: expect -exact. But long matching strings are pretty much guaranteed to cause problems; you should try to cut it down to the shortest unique match, if necessary breaking it into multiple expect commands.
In this case, just based on what you show, the proper command is probably expect -exact "choice:". But inherently it is not possible to determine this without full details of the possible program outputs.

Preparation of shell script

Recently I have been involved for the preparation of the shell script on SunOS with csh shell. I will have multiple queries but first the short program isn't working.
[username]% expect - << EOF
Spawn telnet 74.125.71.103
expect "Password:"
send "google\r"
EOF
The following error pops up:
/bin/csh: Event not found
[username]% expect: Command not found
Please advise.
This script should run in following manner :
Telent the IP and use the existing passwd (explicitly given in the script).
After the telnet, it shows MENU options
MB station
RC
ODU
AP
SU
Exit
type 1 // a "MB station" MENU options will open i.e.
1 - Show
2 - Unit Control
type 2 // UC MENU options will open i.e
1 - Change Password
2 - Reset
type 1 //change passwd MENU options will open i.e.
1 - Change PC Password
2 - Change LU Password
3 - Change Admin Password
type 3 // to change ADMIN passwd
MB station - Change Admin Password
Enter New Password : XYZ enter
Re-enter Password : XYZ enter
New password accepted
3 times escape // to escape from telnet
1.MB station
2. RC
3. ODU
4. AP
5. SU
6. Exit
type 6 // to exit
Exit? [Y/N] y
Connection to host lost.
then move to step with different IP. The IP values will be given by the user one-time while executing the script at the prompt e.g. ./pass-change IPs.txt
The Event not found message implies you're trying to do some kind of history substitution. This normally involves the ! character. Did you type something with a ! character in it at some point?
And expect: Command not found means just what it says: the shell wasn't able to find the expect command. Is it installed? If not, you should install it if you can, or ask a system administrator to install it for you, or, failing that, obtain the source and build and install it under your home directory.
Once you fix that, there's an expect command called spawn, and it's case-sensitive; Spawn won't be recognized.
If you're specifically asking how to accomplish the above without using expect, please update your question to make that clear.
I have a working script below, you are getting error because i believe you are trying to run the script using some sh or other command. Try to run it as ./script. I used below sample script for file transfer but i did teh key exchange manyally by ssh back and forth which is one time activity.
#!/usr/bin/expect -f
set timeout 130
spawn ssh "idk#server.com"
expect "password: "
send "pass#1234\r"
expect "$ "
send "sh /home/nathalok/HTML/run.sh\r"
expect "$ "
send "exit\r"

Resources