Jenkins, Execute Script over ssh with Pipeline

In the previous post I’ve explained how to configure the login over ssh to execute remote commands with Jenkins with a Build Step, now it’s the same but using Pipeline Step.

Avoid login prompt

To avoid logging prompt on each execution with the pipeline script is necessary copy the ssh key to remote server.

  1. Create a ssh key pair, login in the Jenkins server with the user that are executing the Jenkins as a service and execute the next commands:

    sudo su -s /bin/bash jenkins
    ssh-keygen -t -rsa
    

    Leave the options by default, a file $HOME/.ssh/id_rsa is generated, take care if you have a previous file, you will not be able to authenticate using the previous key anymore if you choose overwrite

  2. Copy the public key to remote server use only one of this commands:

    # Using pub key by default ~/.ssh/id_rsa.pub
    ssh-copy-id user@host 
     
    # Using another key 
    ssh-copy-id -i ~/.ssh/otherKey.pub user@host
    
    # if ssh-copy-id is not available, do it manually
    cat ~/.ssh/id_rsa.pub | ssh user@host"mkdir -p ~/.ssh && touch ~/.ssh/authorized_keys && chmod -R go= ~/.ssh && cat >> ~/.ssh/authorized_keys"
    
  3. Test the connection

    # Test the login with the private key 
    ssh -i ~/.ssh/id_rsa user@host 
    
    # Then connect without prompt password
    ssh user@host
    

For more detail check this post

If the authentication fails

If the above steps were followed and ssh’ing to the appropriate user is still prompting for passwords, inspect the permissions on both the local and remote user’s files, per the following command:

[user@ssh-server ~]$ ls -ld ~/{,.ssh,.ssh/authorized_keys*}
drwx------. 25 user user 4096 Aug 21 11:01 /home/user/
drwx------.  2 user user 4096 Aug 17 13:13 /home/user/.ssh
-rw-------.  1 user user  420 Aug 17 13:13 /home/user/.ssh/authorized_keys

And set the permissions as follow:

chmod 600 ~/.ssh/authorized_keys
chmod 700 ~/.ssh/

Don’t forget it, the PubkeyAuthentication yes must be enabled in the server into /etc/ssh/sshd_config

Configure the Pipeline

Create a new Pipeline project and set the next script, notice the end of the pseudo script is intentionally aligned at left, if I indent the text does not work.

pipeline {
    agent any
    stages {
        stage('execute') {
            steps {
		script {
			echo 'Using remote command over ssh'
			sh 'echo "Today is:" date'
			echo '*** Executing remote commands ***'
	 		sh '''#!/bin/bash
				date
				ssh devops@hostname << ENDSSH
				java -version
			    	date
			    	cd /tmp
			    	pwd
ENDSSH
'''

			sh '''
				date
				ssh devops@hostname << ENDSSH
				javac -version
				date
				cd /tmp
				pwd
ENDSSH
'''
                }
            }
        }
    }
}

Then save it and execute the job.

Checking the job log

The script have different ways to call a sh command, let’s check each one.

sh 'echo "Today is:" date'

The first is a simple sh command to get date, the interesting part is how Jenkins execute this, if see the job log each command is executed by separate, the echo first and date after.

[Pipeline] echo
Using remote command over ssh
[Pipeline] sh
[PL_REMOTE_COMMAND] Running shell script
+ echo Today is:
Today is:
+ date
mié dic 18 05:05:06 CST 2019

The second command is executed line by line, one per command:

echo '*** Executing local commands ***'
sh '''
	ls -l
	date
	cd /tmp
	pwd
'''

output:

[Pipeline] echo
*** Executing local commands ***
[Pipeline] sh
[PL_REMOTE_COMMAND] Running shell script
+ ls -l
total 0
+ date
mié dic 18 05:05:07 CST 2019
+ cd /tmp
+ pwd
/tmp

The next command use a pseudo script style to hide the commands and connect to remote server, note my servers have a different date time, that means the commands in the script are hidden in the log and only shows the result of each one:

echo '*** Executing remote commands ***'
    sh '''#!/bin/bash
	date
    	ssh devops@hostname << ENDSSH
	    	java -version
	    	date
	    	cd /tmp
	    	pwd
ENDSSH
'''

output:

*** Executing remote commands ***
[Pipeline] sh
[PL_REMOTE_COMMAND] Running shell script
mié dic 18 05:31:05 CST 2019
Pseudo-terminal will not be allocated because stdin is not a terminal.
java version "1.6.0_45"
Java(TM) SE Runtime Environment (build 1.6.0_45-b06)
Java HotSpot(TM) Server VM (build 20.45-b01, mixed mode)
vie dic 20 18:20:22 CST 2019
/tmp

This is a good option if you don’t want to show sensible commands in other way, remove the script header to show them.

echo '*** Executing remote commands ***'
sh '''
	date
	ssh devops@hostname << ENDSSH
    	java -version
    	date
    	cd /tmp
    	pwd
ENDSSH
'''

output:

[Pipeline] echo
[Pipeline] sh
[PL_REMOTE_COMMAND] Running shell script
+ date
mié dic 18 05:31:05 CST 2019
+ ssh devops@hostname
Pseudo-terminal will not be allocated because stdin is not a terminal.
javac 1.6.0_45
vie dic 20 18:20:22 CST 2019
/tmp

This is the full output of the job:

2019-12-20 18_44_15-PL_REMOTE_COMMAND #6 Console [Jenkins] - Brave

References

Cheers!

5 comentarios en “Jenkins, Execute Script over ssh with Pipeline

  1. L V Prasad Kancharla dijo:

    Hey, thanks for the steps, but i was getting permission denied when i use the script.
    Pseudo-terminal will not be allocated because stdin is not a terminal.
    — WARNING — This system is for the use of authorized users only. Individuals
    using this computer system without authority or in excess of their authority
    are subject to having all their activities on this system monitored and
    recorded by system personnel. Anyone using this system expressly consents to
    such monitoring and is advised that if such monitoring reveals possible
    evidence of criminal activity system personal may provide the evidence of such
    monitoring to law enforcement officials.

    Permission denied, please try again.
    Permission denied, please try again.
    Received disconnect from port 22:2: Too many authentication failures

  2. Amit Dwivedi dijo:

    I am getting permission denied error while runningthe job, even though through jenkins server I can ssh into my remote server. Please suggest what needs to be done in this case.

    • jaehoo dijo:

      Hi, I’ve written a new entry of this topic and is more easy to configure, may you want to read it.

      Jenkins, pipeline execute script over ssh

      Regarding of your question may you could verify this:

      1. Execute a telnet command from the jenkins server to the remote ssh server, in order to verify the port 22 is open
      2. Enruse the /etc/ssh/sshd_config has the property PubkeyAuthentication yes in the remote ssh server

      bye

Deja un comentario

Este sitio utiliza Akismet para reducir el spam. Conoce cómo se procesan los datos de tus comentarios.