3

I am executing a pkill command on a linux shell via Jenkins. This command always fails the build, when the process does not exist.

sudo docker exec mycontainer sh -c 'pkill -f processToKill || true '

Why? How can I make it succeed, even when pkill fails?

Skip
  • 6,240
  • 11
  • 67
  • 117
  • 1
    I suspect the outer command is returning non-zero, so move the `|| true`: `sudo docker exec mycontainer sh -c 'pkill -f processToKill' || true` – bishop Jun 20 '16 at 19:43
  • Nope, this is not the case. docker exec returns whatever the nested script returns. I can check that, by doing some echo instead of pkill – Skip Jun 20 '16 at 19:49
  • That this would happen even with `|| true` is... surprising. **Very** surprising. Suspect-there's-something-pertinent-the-anonymization-is-hiding level surprising. – Charles Duffy Jun 20 '16 at 23:59
  • If I were seeing this, I'd jump straight to `sysdig` to trace what was going on -- watching each process, its exit status, any signals sent or received, etc. – Charles Duffy Jun 21 '16 at 00:01
  • Accoriding to this answer Jenkins executes Shell scripts with `/bin/sh -xe` : http://stackoverflow.com/questions/22814559/how-when-does-execute-shell-mark-a-build-as-failure-in-jenkins. Can it be, that when the left side of the OR is evaluated by Jenkins as `failed` that Jenkins fails the whole Job immediately, ignoring the `|| true` ? – Skip Jun 21 '16 at 06:27
  • I have no idea about linux shell but on windows cmd you could add something like "if %ERORLEVEL% GTR 0 set ERRORLEVEL=0" after pkill line which would stop the build from failing. But you have to be careful for lines before your pkill command generating errors. Add some logic before pkill to exit the command or something might help. – zalimgandhera Jun 21 '16 at 09:14
  • For windows batch if last command returns error greater than zero Jenkins assumes its a build failure so I think Linux shell must be doing the same thing for pkill which might be returning non zero value when process does not exist. – zalimgandhera Jun 21 '16 at 09:29
  • @Skip, no, `|| true` marks whatever's on the rest of it as "checked", which makes `set -e` not apply. – Charles Duffy Jun 22 '16 at 20:01

2 Answers2

8

You're killing yourself -- the || true part will never be reached:

$ sh -c 'pkill -f processToKill || true' ; echo $?
Terminated
143

The reason is the -f flag that you provide to pkill. From manpage:

   -f, --full
          The pattern is normally only matched against the process name.
          When -f is set, the full command line is used.

You need to improve the process selection for your pkill statement, so it will not catch the command line that you pass to sh.

Alex O
  • 7,746
  • 2
  • 25
  • 38
0

You can encapsulate the pkill inside a try-catch block so that exception on killing self can be caught and ignored

stage('Stop script') {
    try {
        execute_cmd = "pgrep -f script.sh | xargs -r kill"
        sh """
            ssh ${SSH_USER}@${HOST_IP} "$execute_cmd"
        """
    } catch (ex) {
        echo "${ex}"
    }
}