Spawn id exp7 not open while executing error shell script - bash

I am using cron to run a script that connects to another server via sftp and uploads files. Once in a while, I will receive the error: Spawn-id-exp7-not-open while executing send \"ls\r\" and the script will stop executing (files will not be sent). However, most of the time, the script will run with no errors.
Below is my script I use to connect :
#!/bin/bash
HOST="removed.com:\API"
USER="user"
PASS="removed"
VAR=$(expect -c "
spawn sftp -o \"BatchMode no\" -b /var/www/prep/cmd -P 13266 $USER#$HOST
expect \"Password:\"
send \"$PASS\r\"
expect \"\\\\$\"
send \"ls\r\"
expect -re \"$USER.*\"
send \"exit\"
")
echo "==============="
echo "$VAR"
Below is the script that runs after I connect (cmd) :
put "/var/www/prep/1.xml"
put "/var/www/prep/2.xml"
I took a look at a similar question found at send: spawn id exp7 not open , but it has not helped me. Perhaps the connection ends before the cmd script can run?
Thanks for your help!

You're using sftp with -b. Therefore, once you provide the password, there will be no interaction: sftp will read commands from the batch file and exit.
From the man page:
-b batchfile
Batch mode reads a series of commands from an input batchfile instead of stdin. Since it lacks user interaction it should be used in conjunction with non-interactive authentication. A batchfile of ‘-’ may be used to indicate standard input. sftp will abort if any of the following commands fail: get, put, rename, ln, rm, mkdir, chdir, ls, lchdir, chmod, chown, chgrp, lpwd, df, symlink, and lmkdir. Termination on error can be suppressed on a command by command basis by prefixing the command with a ‘-’ character (for example, -rm /tmp/blah*).

Related

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 use telnet in a script?

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
'

Pass password for download script

I'm downloading huge files and have a python downloading script. Since the data are to huge to be stored in their original format, I only download a couple of years, process them, then delete the original before I download the next few years. For every set of years I have a separate download script and I just build a quick bash script to run them
#!/bin/bash
python download_1901-1909.py
## processing, delete
python download_1910-1919.py
## processing, delete
python download_1920-1929.py
## processing, delete
[...]
For the download scipt, I have to type in a password. I know it's is possible to do some automatic password passing with spawn, but I couldn't make it work. Trying the spawn thing does this
#!/usr/bin/expect -f
spawn python download_1901-1909.py
expect "Password:"
send "mypassword"
interact
yields
sh test.sh
test.sh: line 2: spawn: command not found
couldn't read file "Password:": no such file or directory
test.sh: line 4: send: command not found
test.sh: line 5: interact: command not found
How can I pass a password to a python download script?
This answer is trying to solve your question of finishing what you need, not the question of executing a #!/usr/bin/expect, which may be what you are asking.
You may try to use the -c param of expect inline.
For example,
#!/bin/bash
expect -c "spawn python download-1901_1909.py; expect \"assword\"; send \"mypassword\r\n\"; interact"
expect -c "spawn python download-1910_1919.py; expect \"assword\"; send \"mypassword\r\n\"; interact"
# and the remaining, similarly
Note:
Your send part may need to send the \r\n to "simulate" the Enter key of finishing enter the password.
You may use sed within a for to simply the lines.
"assword" is to prevent the case of first letter of that word, "Password" vs "password", for some portability.

automate getting diagnostic files from a controller via ssh commands

I'd like to automate getting diagnostic files from a controller that responds to ssh commands, like e.g.
ssh diag#controller tarred > diags.tgz
Unfortunately, I have to type a password to make the above command go through.
What have I considered to get around that:
using ssh keys: not possible, since I can't login to the controller, it just expects commands and doesn't offer a shell
using ssh-pass package: I don't have admin rights on the machine and can't install packages
using "expect": works to some extent, but the resulting file is corrupted.
Here's the "expect" script I've used:
#!/usr/bin/expect -f
log_user 0
set timeout 300
spawn ssh diag#controller tarred
expect "?assword:"
send "unrealpassword\r"
expect \r\n
log_user 1
expect eof
The script makes sure that only the required output gets stored with the "log_user" commands until eof is encountered.
I've piped this script to a file and that file is corrupted, i.e. it's either too short (because of a timeout?) or too long (?).
Any idea about what goes wrong here.?

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