expect: couldn't execute "/usr/bin/zypper patch": no such file or directory - linux

I wrote an expect script
vi /foo/force-zypper-patch.exp
cat /foo/force-zypper-patch.exp
#!/usr/bin/expect
set timeout 300
spawn "/usr/bin/zypper patch"
expect "Continue? [y/n/...? shows all options] (y): " { send "y\r" }
interact
but even though I have the zypper with full path, it fails:
SERVER1:~ # ssh SERVER2 "/usr/bin/expect -f /foo/force-zypper-patch.exp"
spawn /usr/bin/zypper patch
couldn't execute "/usr/bin/zypper patch": no such file or directory
while executing
"spawn "/usr/bin/zypper patch""
(file "/foo/force-zypper-patch.exp" line 4)
SERVER1:~ #
SERVER1:~ # ssh SERVER2 "which zypper"
/usr/bin/zypper
SERVER1:~ #
although I can reach my purpose with a "zypper patch -y --with-interactive" but I would be really interested, how to do this in expect!

Simply remove the quotes from the spawn line.
spawn /usr/bin/zypper patch
Currently, you are trying to execute the command zypper patch in the /usr/bin directory, and clearly no such file exists.

Related

sftp via bash script in a cronjob: 'get' and 'rm' commands not found?

I'm trying to do something real, real simple: download a file from a sftp site at a set time. However, I'm getting errors like 'command: rm does not exist' or 'command get does not exist' which is garbage, because these commands obviously exist.
#!/usr/bin/expect
#remove current version of file
rm -f /home/user/downloads/data/newdata.zip
spawn sftp user#ftpsite.com
expect "password:"
send "PaSsWoRd\n"
expect "sftp>"
get /mycompany/myproject/data/newdata.zip /home/user/downloads/data
expect "sftp>"
send "exit\n"
interact
(base) root#ubuntu:~# ./shellscript.sh
invalid command name "rm"
while executing
"rm -f /home/user/downloads/data/newdata.zip"
or without the removal
(base) root#ubuntu:~# sudo ./shellscript.sh
spawn sftp user#sftpsite.com
EFT Server Login - %DATE% %TIME% - Please enter valid credentials to continueEnter password:
Connected to ftpsite.com
sftp> invalid command name "get"
while executing
"get /mycompany/myproject/data/newdata.zip /home/user/downloads/data"
What gives? Why can't I get real error messages - I'm sure get and rm a perfectly fine commands and I can verify this by running them directly from the command line, where they work fine.
You are writing TCL code in an Expect script. You are not writing Bash in a shell script.
You have to send the commands you want to write to the sftp tool:
send "get /mycompany/myproject/data/newdata.zip /home/user/downloads/data\n"
And exec any commands you want to run non-interactively:
exec rm -f /home/user/downloads/data/newdata.zip

Running Nested Command Lines with HERE

This command myprogram.sh command in CygWin installed with Chocolatey, called from the Windows Command Line, with an alias server01 created at the .ssh folder, everything works fine:
# File myprogram.sh
ssh -p 66622 user#localhost << HERE
ssh server01 << EOF
command1
command2
EOF
HERE
Because i have several servers, i have to build several .sh files for different set of commands, so i have to create a lot of .sh files
But i've been unable to run the same instructions from a single line from the command line. Is that possible, in order to run these chain of instructions from a same place?
#!/bin/bash
array=(server1 server2 server3 .... serverN)
for i in ${array[#]}
do
echo ${i}
ssh -p 66622 user#${i} "command1"
done
you can change the "command1" to "command.sh"

bash command redirection in expect script failing with permission denied (spawn ssh user#host command > outfile)

I have this expect script
#!/usr/bin/expect -f
set pass [ exec echo my_phrase | gpg --batch --quiet --yes --passphrase-fd 0 -d /root/.password-store/ssh/my_pgp_store.gpg ]
spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no -i /home/myuser/.ssh/id_rsa ssh-user#remote-host.com /some/remote/script > /home/myuser/ssh.output
expect "*?assword:*"
send -- "$pass\r"
interact
that is supposed to read a gpg encrypted password, and use it to call a remote script via ssh (there are many reasons why I need to do it like that). Now, my problem is that whenever I run this script, the ssh connection is correctly set up, but it fails in writing the output of the ssh call with the error
bash: /home/myuser/ssh.output: Permission denied
I'm running the script as root (because I have to run it as root), and I already tried to change the permissions and ownerships of all the involved files and directories.
The redir char > is not special for expect's spawn command. The command
spawn ssh user#host command > outfile
means the same as
spawn ssh user#host "command > outfile"
and the redir > outfile will be executed on the remote host.
Try like this:
spawn bash -c "ssh user#host command > outfile"
expect "assword:"
send -- "$pass\r"
interact

am I required to use spawn when using expect?

I am creating a simple automated script. here is the code
#!/bin/sh
echo "testing expect"
/usr/bin/expect <<delim
expect "password for teamer:"
send "itsme\r"
expect eof
delim
sudo apt-get update
I refer to various documents and blogs they are using spawn. So I have question: is it necessary to use spawn every time? I am executing the update on my local machine.
Not using spawn I get this error:
send: spawn id exp0 not open while executing
or am I missing something?
expect's expect command is watching the IO channels of the spawned process waiting for the pattern to specify. If you don't give it something to watch, it will just sit there until it times out and then send the password to nothing.
This is what you need to do:
#!/bin/sh
echo "testing expect"
/usr/bin/expect <<delim
exp_internal 1 ;# remove this when your satisfied it's working
spawn sudo apt-get update
expect "password for teamer:"
send "itsme\r"
expect eof
delim
Be careful that you do not have any leading or trailing whitespace on the line with the heredoc delimiter.
If you don't care that your password is in plain text (you should), you don't need to use expect:
#!/bin/sh
echo "itsme" | sudo -S apt-get update
What you ought to do is to edit the sudoers file to allow yourself to sudo apt-get without having to supply your password, then:
#!/bin/sh
sudo apt-get update
Read the sudoers man page on your system.

how to write a bash shell script to ssh to remote machine and change user and export a env variable and do other commands

I have a webservice that runs on multiple different remote redhat machines. Whenever I want to update the service I will sync down the new webservice source code written in perl from a version control depot(I use perforce) and restart the service using that new synced down perl code. I think it is too boring to log to remote machines one by one and do that series of commands to restart the service one by one manully. So I wrote a bash script update.sh like below in order to "do it one time one place, update all machines". I will run this shell script in my local machine. But it seems that it won't work. It only execute the first command "sudo -u webservice_username -i" as I can tell from the command line in my local machine. (The code below only shows how it will update one of the remote webservice. The "export P4USER=myname" is for usage of perforce client)
#!/bin/sh
ssh myname#remotehost1 'sudo -u webservice_username -i ; export P4USER=myname; cd dir ; p4 sync ; cd bin ; ./prog --domain=config_file restart ; tail -f ../logs/service.log'
Why I know the only first command is executed? Well because after I input the password for the ssh on my local machine, it shows:
Your environment has been modified. Please check /tmp/webservice.env.
And it just gets stuck there. I mean no return.
As suggested by a commentor, I added "-t" for ssh
#!/bin/sh
ssh -t myname#remotehost1 'sudo -u webservice_username -i ; export P4USER=myname; cd dir ; p4 sync ; cd bin ; ./prog --domain=config_file restart ; tail -f ../logs/service.log'
This would let the local commandline return. But it seems weird, it cannot cd to that "dir", it says "cd:dir: No such file or directory" it also says "p4: command not found". So it looks like the sudo -u command executes with no effect and the export command has either not executed or excuted with no effect.
A detailed local log file is like below:
Your environment has been modified. Please check /tmp/dir/.env.
bash: line 0: cd: dir: No such file or directory
bash: p4: command not found
bash: line 0: cd: bin: No such file or directory
bash: ./prog: No such file or directory
tail: cannot open `../logs/service.log' for reading: No such file or directory
tail: no files remaining
Instead of connecting via ssh and then immediately changing users, can you not use something like ssh -t webservice_username#remotehost1 to connect with the desired username to begin with? That would avoid needing to sudo altogether.
If that isn't a possibility, try wrapping up all of the commands that you want to run in a shell script and store it on the remote machine. If you can get your task working from a script, then your ssh call becomes much simpler and should encounter fewer problems:
ssh myname#remotehost1 '/path/to/script'
For easily updating this script, you can write a short script for your local machine that uploads the most recent version via scp and then uses ssh to invoke it.
Note that when you run:
#!/bin/sh
ssh myname#remotehost1 'sudo -u webservice_username -i ; export P4USER=myname; cd dir ; p4 sync ; cd bin ; ./prog --domain=config_file restart ; tail -f ../logs/service.log'
Your ssh session runs sudo -u webservice_username -i waits for it to exit and then runs the rest of the commands; it does not execute sudo and then run the commands following. This has to do with the context in which you're running the series of commands. All the commands get executed in the shell of myname#remotehost1 and all sudo -u webservice_username - i is starts a shell for webservice_username and doesn't actually run any commands.
Really the best solution here is like bta said; write a script and then rsync/scp it to the destination and then run that using sudo.
export command simply not working with ssh like this, what you want to do is remote modify ~/.bashrc and it will source itself each time u do ssh login.

Resources