Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add to slave's PATH using Slave SetupPlugin?

Tags:

jenkins

I have 2 RHEL machines setup in a Master/Slave configuration using Jenkins ver. 1.609.2

The slave is being launched via SSH Slaves Plugin 1.10.

I'm trying to use the Slave Setup Plugin v 1.9 to install the tools that will be necessary for my slave machine to run builds. In particular I am installing sqlplus.

Here is the script that I am running in order to try installing sqlplus:

if command -v sqlplus >/dev/null; then
    echo "sqlplus already setup. Nothing to do."
else
    #Create directory for sqlplus and unzip it there.
    mkdir /jenkins/tools/sqlplus
    tar -xvf sqlplussetup/instantclient-basiclite-linux.x64-12.1.0.2.0.tar.gz -C /jenkins/tools/sqlplus  || { echo 'unzip failed' ; exit 1; }
    tar -xvf sqlplussetup/instantclient-sqlplus-linux.x64-12.1.0.2.0.tar.gz -C /jenkins/tools/sqlplus  || { echo 'unzip failed' ; exit 1; }

    cd /jenkins/tools/sqlplus/instantclient_12_1

    #Create links for the Oracle libs
    ln -s libclntsh.so.12.1 libclntsh.so || { echo 'Could not create link' ; exit 1; }
    ln -s libocci.so.12.1 libocci.so || { echo 'Could not create link' ; exit 1; }

    #Add two lines to .bashrc only if they don't already exist. Export LD_LIBRARY_PATH and add sqlplus to PATH.
    grep -q -F 'export LD_LIBRARY_PATH=/jenkins/tools/sqlplus/instantclient_12_1:$LD_LIBRARY_PATH' /home/jenkins/.bashrc || echo 'export LD_LIBRARY_PATH=/jenkins/tools/sqlplus/instantclient_12_1:$LD_LIBRARY_PATH' >> /home/jenkins/.bashrc
    grep -q -F 'export PATH=$PATH:/jenkins/tools/sqlplus/instantclient_12_1' /home/jenkins/.bashrc || echo 'export PATH=$PATH:/jenkins/tools/sqlplus/instantclient_12_1' >> /home/jenkins/.bashrc

    #Export variables so they can be used right away
    export LD_LIBRARY_PATH=/jenkins/tools/sqlplus/instantclient_12_1:$LD_LIBRARY_PATH
    export PATH=$PATH:/jenkins/tools/sqlplus/instantclient_12_1

    echo "sqlplus has been setup."
fi

This script runs successfully and everything appears to work until I try to run a build and execute the sqlplus command. The build fails because sqlplus is not a recognized command.

My main question is this: What is the proper way to automatically add an environment variable when launching a slave?

Please note I am looking for an automated way of doing this. I don't want to go into the configuration screen for my slave, tick a checkbox and specify an environment variable. That is counter-productive to what I am trying to achieve which is a slave that is immediately usable for builds once connected.


I pretty much understand why my script doesn't work. When Jenkins is launching the slave it first makes an SSH connection and then it runs my setup script using the command

/bin/sh -xe /jenkins/tmp/hudson8035138410767957141.sh

Where the contents of hudson8035138410767957141.sh is my script from above. So obviously, the export isn't going to work. I was hoping adding the exports to the .bashrc file would get around this but it does not work. I think this is because this script is executed after the ssh connection is established and therefore the .bashrc has already been read.

Problem is I can't figure out any way to work around this limitation.

like image 385
FGreg Avatar asked Nov 10 '22 04:11

FGreg


1 Answers

Bash does not read any of its startup files (.bashrc, .profile etc) for non-interative shells that don't have the --login option set explicitly -- that's why the exports don't work.

So, solution "A" is to keep the bashrc magic that you suggest above, and to add the --login option by changing the first line in your build step to

#!/bin/bash --login

<your script here>

The explicit shebang at on the first line will also prevent excessive debug output that you get from the default's -x option (see your console snippet above).

Alternative solution "B" uses the fact that bash will source any script whose name is given in $BASH_ENV (if that variable is defined and the file exists). Define that variable globally in your slave properties (e.g., set to /jenkins/tools/setup.sh) and add exports as needed during slave setup. Every bash shell build step will read the settings then.

With solution "B" you don't need to use the --login option and you don't have to mess up the .bashrc. However, the "BASH_ENV" feature is only active when bash runs in "bash mode". As Jenkins starts the shell via sh, bash tries to emulate historic sh, which does not have that feature. So, also for B, you need a shebang:

#!/bin/bash

<your script here>

But that you'd need anyway to get rid of the tracing output that's usually too much in production setups.

like image 137
Alex O Avatar answered Nov 15 '22 06:11

Alex O