Run remote command from script - linux

I need to run a shell script from within jenkins, to commit changes after making the build. Deploying build to remote server is not a problem, so the new build is there. All I need to do is just commit it.
For that I need to login with ssh to that remote server using shell script, and so far it is okay:
#!/user/bin/expect -f
spawn ssh myusername#url
expect "password:"
send "mypassword\r"
interact
So now when I am logged in, I want to run a few commands: cd /path/to/repository; svn commit -m "Some change log"
I tried something like:
#!/user/bin/expect -f
spawn ssh -o "LocalCommand cd /path/to/repository" myusername#url
expect "password:"
send "mypassword\r"
But it just don't work, as I have no idea how to do it.
If anyone know how to do it, please let me know.
The remote server is running on linux, and the jenkins on osx.

I found solution just with expect:
#!/user/bin/expect -f
spawn ssh myusername#url
expect "password:"
send "mypassword\r"
expect "some server prompt"
send "cd /path/to/repository\r"
send "svn commit -m 'Some change log'\r"
EDIT:
This solution seems to work from time to time only. I mean commiting changes.

Related

How to download file through linux expect?

I face a trouble about linux expect script.
I have a computer A which only have LAN connection, while another computer B in the same LAN which have Internet connection. What I want to do is writing a script which can login into computer B through ssh and download file to it and finally use scp to transfer the file to computer A.
And below is my script.
#!/bin/expect
set url [lindex $argv 0];
spawn ssh "user#computer-B"
expect "password:"
send "passwd\n"
expect "Last login:"
send "cd tmp\n"
send "wget $url\n"
expect "saved"
send "scp * user#computer-A:~/\n"
expect {
"yes/no" { send "yes\n"; exp_continue }
"password:" { send "passwd\n" }
}
expect "100%"
send "rm *\n"
send "exit\n"
But now the script will scp the file to A immediately not until wget finishing. Is my script close to the proper way to do it? If not what should I do? Thanks very much.
You don't need expect, and you could use key-based login to make your life easier.
SOCKS
You could use a socks proxy.
From computer A :
ssh -D 1080 address-of-B
followed by
export SOCKS_SERVER=127.0.0.1:1080
You can now use wget from computer A.
One liner
From computer A :
ssh computer-B 'wget -O - $url' >> filename_on_computer_a

How to use gnome-terminal to log in a remote linux server(SSH) and executes commands on the server

The code is following:
gnome-terminal -x sh -c "ssh root#ip 'ls'"
And the 'ls' can executed well on the server, but after the execution it will log out the server and I want to stay in the server. So I want to know is there any way to solve this problem
Because you are supplying a command (the 'ls' part of your code) ssh will execute it on the remote server then log out of it, just as you experienced.
It you leave out the command, ssh should stay logged into the server,
gnome-terminal -x sh -c "ssh root#ip"

Cannot use expect in Bash script

In my bash script file, I try to use expect to provide password for ssh command but it doesn't work. Here is my script:
#!/bin/bash
/usr/bin/expect << EOD
spawn ssh root#192.168.1.201
expect "root#192.168.1.201's password:"
send "mypassword\r"
interact
expect eof
EOD
And the output after I execute the script:
[oracle#BTMVNSRV191 Desktop]$ ./login.sh
spawn ssh root#192.168.1.201
root#192.168.1.201's password: [oracle#BTMVNSRV191 Desktop]$
Could someone let me know, how to use expect in my script without changing #!/bin/bash to #!/usr/bin/expect?
The following works as a single line of bash script in OS X Terminal. It was only intended for use on a firewall protected LAN. Further details at my original post.
expect -c 'spawn ssh -o StrictHostKeyChecking=no remote-user#remote-IP;
expect assword; send remote-password\r; expect remote-user$;
send "sudo shutdown -h +1\r"; expect assword; send remote-password\r; interact'
ssh (and any other password reading tool) reads its password not from its standard input. It uses some tricky ioctl()-s on its terminal device. This is because you can't give them your password in a pipe.
It is not really a big problem, because widely used cleartext passwords caused more harm as if sometimes we need to find some alternative, password-less solution.
In cases of the ssh, there is a very simple thing for that. Google for ssh-keygen. I suggest to use that, configure a passwordless ssh and everything will be fine.

expect utility is not working when executing from jenkins

we have a unix script which uses expect utility for interactive execution. This script works well when we run from unix server.
If we run this script from Jenkins, it is not working.
Below is the script
var="xxxxx"
expect -c "
spawn sudo cp /abcd/sjws/config/obj.conf /abcd/sjws/config/obj.conf_jenkins
expect {
"Password:" { send $var\r;interact }
}
exit
"
Below is the output when we run from jenkins
spawn sudo cp /abcd/sjws/config/obj.conf /abcd/sjws/config/obj.conf_jenkins
Password:
Password:
Build step 'Execute shell' marked build as failure
Finished: FAILURE
Since Jenkins doesn't run it from an actual terminal, interact doesn't work, since there can't actually be any user interaction there.
You can replace interact with
expect eof
wait
Please use var='xxxxx' instead of var="xxxxx". Hope this help.
It seems that Jenkins doesn't support the interactive command model.
Try to use sshpass tool to pass the password in a non-interactive way.
install sshpass
$ sshpass -p "password" {your command}
This question is very similar to: Jenkins not waiting on call to a bash script with expect; for those encountering the similar problem, especially when using "su" utility to change the user, please be aware that Jenkins closes the SSH connection as soon as the user is changed. You can not continue giving commands with the new user. Design your script in such a way that you are sending the command directly, such as:
spawn su - username -c "yoursinglewordcommand"
and then the rest of the expect script as usual (I was also successful with the interact command).
You may use ssh steps plugin. This plugin will provide steps like sshScript which executes given script(file) on remote node and responds with output, sshCommand that executes given command on remote node and responds with output and also sshPut, sshGet, sshRemove.
Add to your Jenkinsfile :
node {
def remote = [:]
remote.name = 'test'
remote.host = 'test.domain.com'
remote.user = 'root'
remote.password = 'password'
remote.allowAnyHosts = true
stage('Remote SSH') {
sshCommand remote: remote, command: "cp /abcd/sjws/config/obj.conf /abcd/sjws/config/obj.conf_jenkins"
}
}

Using Expect to administer machines via SSH, but does not complete all tasks

*Please do not pile on and tell me to just use SSH keys. If it bugs you that this is the way I am doing it, pretend that I am trying to telnet in instead. :-) *
I am using an expect script to run some routine commands on a set of servers under my control via ssh. The script should run set of commands (eg svn update ~/folderx\r") on each of the machines. My current script does everything I want it to do... sometimes. Other times it exits the ssh connection before it completes one of the last few commands.
Any thoughts on how I can make the connection stay until all of the commands are completed? The code below successfully logs on, successfully runs the first two commands or so (ap-get update and one of the svn updates) and then disconnects.
#!/usr/bin/expect -f
spawn ssh username#ipaddress
set timeout -1
expect "Are you sure you want to continue connecting" {send "yes\r"; exp_continue} "password:" {send "*******\r"; exp_continue
} "username#machine" {send "sudo apt-get update\r"}
expect "password" {send "*******\r"; exp_continue} "username#machine" {send "sudo svn update ~/folder1\r"}
expect "password" {send "*******\r"; exp_continue} "username#machine" {send "sudo svn update ~/folder2\r"}
expect "password" {send "*******\r"; exp_continue} "username#machine" {send "sudo svn update ~/folder3\r"}
expect "password" {send "*******\r"; exp_continue} "username#machine" {send "sudo reboot\r"}
close
Using Expect is generally the wrong way to do this kind of thing.
The right way is to set up ssh keys so that you can ssh and run commands on the remote machine without supplying a password. Here's how to do that:
0. Create public/private key pair on local machine.
(Only needs to be done once on local machine for all remote machines.)
Go to the ~/.ssh directory on your local machine and do this:
% ssh-keygen -t rsa
1. Copy the public key to the remote machine:
% scp ~/.ssh/id_rsa.pub you#foo.com:.
2. Append that key to the authorized_keys file on the remote machine:
% ssh you#foo.com 'cat id_rsa.pub >> .ssh/authorized_keys; /bin/rm id_rsa.pub'
3. Finally, in case it doesn't work, check permissions, which must be just so:
(or maybe it's just that they can't be group/world writeable)
% cd ~; ls -ld . .ssh .ssh/authorized_keys
drwxr-xr-x .
drwxr-xr-x .ssh
-rw-r--r-- .ssh/authorized_keys
Here's a script that does the above in one fell swoop:
http://jakehofman.com/code/sshkey
You can then run commands on the remote machine like so:
ssh alice#remote.com ./foo args
To run commands on the remote machine with sudo, however, may be another story.
Hopefully others can chime in about that.
But as a first step you should avoid Expect for the initial login.
It turns out that the reason it was exiting earlier was that the prompt pattern that I was matching against matched not only the prompt, but also some of the output from the svn commands I was running. I was matching against only the "username" portion of the prompt pattern (the prompt form was "username#machine:~$"). Once I altered the script to match only "username#" it began to work as expected.
p.s. the ssh script that dreeves links to above works very nicely.

Resources