how to use sudo command in jenkins exec command

12,490

Solution 1

Jenkins cannot print out the result of certain commands that are executed using sudo.

Hence the best way is to simply allow jenkins to ssh as root to perform those same commands without sudo.

  1. Allow jenkins user to ssh as root without password required.
  2. Read this on how to have ssh login without password.
  3. Then, write the command like so: <exec command="ssh -A ${root-used} 'Console/cake init_runners copy_runners_into_initd'" outputProperty="result" escape="false" /> <echo msg="${result}" />

Note that ${root-used} should have a value like root@ipaddress

Solution 2

The user that is sshing in does not have the command available.

If you look at error it connected could not run command and disconnected

By this I don't mean sudo I mean what you have done after sudo

Console/cake init_runners copy_runners_into_initd

It may be that if you actually ssh in as the user and run the above command it works but not via your jenkins script because it may be that you are missing some environment variables that is defined when you ssh in as per normal and get a session.

I would suggest using full paths to everything including:

which sudo

sudo is /usr/bin/sudo

The full path to sudo to rest assured its nothing to do with that.

UPDATED

Hi Kimsia

Thanks for commenting back and now confirming you have a fix, I still think there is something missing from what you have done with sudo since the return message clearly states command not found. To me it would appear that although you ran sudo the path you were actually in could not run console/cake i.e. command not found !

A few things to try if you still wanted to go down the sudo route since I do believe security wise its a lot safer than opening root ssh access.

  1. run sudo with -i to take on root's profile and then actually change directory to where Console folder and cake command reside.

<exec command="ssh -t -t -A ${host-used} 'sudo -i cd /path/to/cakephp/app; Console/cake init_runners copy_runners_into_initd'" outputProperty="result" escape="false" />

  1. Would it not be possible to write a shell script which sudo's in
#!/bin/bash
function ssh_and_run_cake() { 

 echo "Working on $hostname --- $instance --::"
 $ssh -t $hostname "sudo su -i '
    echo \"CD Folder run cake init -----------------\";
    cd /path/to/cakephp/app; 
    Console/cake init_runners copy_runners_into_initd;
    echo \"All done------------------------\";
 '";

}

function rollout_cake() {

   #for hostname in ${h[@]}; do


        hostname="yourhost"

        ssh_and_run_cake
  # done

}

rollout_cake

and from jenkins web interface use the execute shell script which should then call this script and carry out what you want.

I have seen Jenkins work away fine with this method

Updated the shell script to work so long as you define hostname in 2nd function.

You would then need to use jenkins web front end deploy options to execute shell script and define the fullpath script. The script should be on the local file system of jenkins server

Solution 3

I don't think you need to specify your host twice.

<exec command="ssh -t -t -A ${host-used} 'sudo Console/cake init_runners copy_runners_into_initd'" outputProperty="result" escape="false" />
<echo msg="${result}" />
Share:
12,490

Related videos on Youtube

Kim Stacks
Author by

Kim Stacks

I build end-to-end workflow solutions to process data such as BOQ (Bill of Quantities) for businesses in telecomms, civil engineering, and construction.

Updated on June 25, 2022

Comments

  • Kim Stacks
    Kim Stacks almost 2 years

    I am using jenkins to run my builds.

    One of my steps is to copy over certain files and place them inside /etc/init using sudo

        <exec command="ssh -A ${host-used} '/etc/init.d/ConvertDaemon stop'" outputProperty="result" escape="false">
        </exec>
        <echo msg="${result}" />
    
        <exec command="ssh -A ${host-used} 'sudo Console/cake init_runners copy_runners_into_initd'" outputProperty="result" escape="false" />
        <echo msg="${result}" />
    
    ${host-used} returns www-data@ip-address
    

    The issue is the 2nd command.

    When I run the 1st command, i can see my result printed out in the console log in jenkins.

    For the 2nd command, I get a no tty present message

    So I changed the 2nd command to

        <exec command="ssh -t ${host-used} -A ${host-used} 'sudo Console/cake init_runners copy_runners_into_initd'" outputProperty="result" escape="false" />
        <echo msg="${result}" />
    

    I get a

     Pseudo-terminal will not be allocated because stdin is not a terminal
    

    How do I overcome this?

    UPDATE:

    I tried this as well.

        <exec command="ssh -t -t ${host-used} -A ${host-used} 'sudo Console/cake init_runners copy_runners_into_initd'" outputProperty="result" escape="false" />
        <echo msg="${result}" />
    

    I got:

    bash: www-data@ipaddress: command not found
    Connection to ipaddress closed.
    

    I want to emphasize that the command is correctly used. BUT I cannot read the message.


    UPDATE2:

    There are times when you ask a question, but then you realize the question you want to ask is not the REAL question you want to solve.

    This question is like that.

    All I wanted to do is to execute a few commands run by jenkins and see the print out of the commands. These commands happen to require sudo.

    Jenkins basically ssh as another user www-data to perform these commands.

    I was having trouble with printing out the results in jenkins for those commands requiring sudo.

    Having spent a lovely saturday working on this with some very helpful SO answers, I realized that I could simply try to execute those commands without sudo by having jenkins ssh as root instead.

    It worked.

    I am going to answer this question with that approach instead because that is all I wanted -- execute some commands inside jenkins and see their print out.

  • Kim Stacks
    Kim Stacks over 10 years
    i tried this and the jenkins hanged here for a very long time
  • konsolebox
    konsolebox over 10 years
    @kimsia It probably really needs an input. It could wait forever if it doesn't get anything it needs. You can try <exec command="ssh -t -t -A ${host-used} 'screen -dm sudo Console/cake init_runners copy_runners_into_initd'" outputProperty="result" escape="false" />.
  • Kim Stacks
    Kim Stacks over 10 years
    i tried renaming sudo to /usr/bin/sudo. I get back the same result :(
  • Kim Stacks
    Kim Stacks over 10 years
    i tried ssh -t -t -A ${host-used} 'screen -dm it still hanged
  • Kim Stacks
    Kim Stacks over 10 years
    i tried ssh -t -t ${host-used} -A ${host-used} 'screen -dm. It did not hang but also unable to generate the result.
  • konsolebox
    konsolebox over 10 years
    I'm not really sure why you had to specify the host twice. Try to not add the -d option to screen. Just use -m.
  • Kim Stacks
    Kim Stacks over 10 years
    thanks for your answer. but i tried an entirely different approach and i got what i wanted. Cheers!
  • Kim Stacks
    Kim Stacks over 10 years
    thanks for your answer. but i tried an entirely different approach and i got what i wanted. Cheers!
  • V H
    V H over 10 years
    Glad you have it working, if you are still experimenting please read my updated answer
  • Kim Stacks
    Kim Stacks over 10 years
    ssh -t -t -A ${host-used} for some reason this causes my jenkins to hang a long time
  • Kim Stacks
    Kim Stacks over 10 years
    A few things to try if you still wanted to go down the sudo route since I do believe security wise its a lot safer than opening root ssh access. <-- I agree with this. But right now, I need something that works. Can you explain your 2nd solution with more detail? I don't understand by write a shell script which sudo's in and from jenkins web interface
  • Kim Stacks
    Kim Stacks over 10 years
    I still am, @vahid. If there is something better and more secure, I will adopt it.
  • fduff
    fduff almost 10 years
    you should edit the sudoers file using the $ sudo visudo command instead.