Execute shell script from jenkins

3,489 views
Skip to first unread message

Poonkuzhali Muthiah

unread,
Aug 12, 2021, 11:00:28 AM8/12/21
to Jenkins Users
Hello everyone,

How can I execute shell scripts from jenkins? 

I have the below code in "Execute Shell" command
""
#!/bin/bash
echo "hello"

Received the following Error Msg  in the console.

Running as SYSTEM Building on master in workspace C:\Users\crnat\.jenkins\workspace\ssh-task-test [ssh-task-test] $ /bin/bash C:\Users\crnat\AppData\Local\Temp\jenkins563122492098989130.sh The system cannot find the file specified FATAL: command execution failed java.io.IOException: CreateProcess error=2, The system cannot find the file specified at java.lang.ProcessImpl.create(Native Method) at java.lang.ProcessImpl.<init>(Unknown Source) at java.lang.ProcessImpl.start(Unknown Source) Caused: java.io.IOException: Cannot run program "/bin/bash" (in directory "C:\Users\crnat\.jenkins\workspace\ssh-task-test"): CreateProcess error=2, The system cannot find the file specified at java.lang.ProcessBuilder.start(Unknown Source) at hudson.Proc$LocalProc.<init>(Proc.java:252) at hudson.Proc$LocalProc.<init>(Proc.java:221) at hudson.Launcher$LocalLauncher.launch(Launcher.java:996) at hudson.Launcher$ProcStarter.start(Launcher.java:508) at hudson.tasks.CommandInterpreter.perform(CommandInterpreter.java:144) at hudson.tasks.CommandInterpreter.perform(CommandInterpreter.java:92) at hudson.tasks.BuildStepMonitor$1.perform(BuildStepMonitor.java:20) at hudson.model.AbstractBuild$AbstractBuildExecution.perform(AbstractBuild.java:803) at hudson.model.Build$BuildExecution.build(Build.java:197) at hudson.model.Build$BuildExecution.doRun(Build.java:163) at hudson.model.AbstractBuild$AbstractBuildExecution.run(AbstractBuild.java:513) at hudson.model.Run.execute(Run.java:1906) at hudson.model.FreeStyleBuild.run(FreeStyleBuild.java:43) at hudson.model.ResourceController.execute(ResourceController.java:97) at hudson.model.Executor.run(Executor.java:429) Build step 'Execute shell' marked build as failure Finished: FAILURE


Thanks,
Poo

Mark Waite

unread,
Aug 12, 2021, 11:16:40 AM8/12/21
to Jenkins Users
Your Jenkins controller is running on Windows.  Windows uses batch and powershell for its command line scripting.

If you want to run a shell script, add an agent on an operating system that supports bash.  That could be a Linux Docker based agent running in Docker on your Windows computer.  It could be an agent on a Linux computer.  It could be an agent on macOS, FreeBSD, or OpenBSD.

In any case, you should add agents to your controller so that you are not running jobs on the controller.

Mark Waite

Jerome Godbout

unread,
Aug 12, 2021, 11:40:36 AM8/12/21
to Jenkins Users

You can also use the WSL on recent Windows and call the wsl shell, which can be call with:

“wsl ${cmd}”

I made myself a function that do call the proper shell based on the current platform, so my pipeline script does look like a big if else mess for each shell command, on windows it append the wsl in front of my command and fix the stdout return value. 

Here is some groovy scripts function I do inject to “fix” (or if you prefer bring it to human decent version of command) the shell: 

/*

* Console cross platform command

*/

def BasicConsole(labelStr, cmd, returnStatus = false, returnStdout = false, useWsl = false) {

    // Only good for exact same syntax command on all platform or use wsl to execute the command into unix like under Windows if this is available

    if(isUnix()) {

        return sh(label: labelStr, script: cmd, returnStatus: returnStatus, returnStdout: returnStdout);

    } else {

        return WindowFixReturn(bat(label: labelStr, script: WindowFixCmd(cmd, useWsl), returnStatus: returnStatus, returnStdout: returnStdout), returnStdout);

    }

}

 

def ConsoleVar(varName) {

    if(isUnix()) {

        return "\${${varName}}";

    } else {

        return "%${varName}%";

    }

}

 

def WindowFixReturn(data, returnStdout) {

    if(returnStdout) {

        // Remove the requested command echo into the shell, this make the behavior more closer to unix for cross platform behavior

        return data.trim().readLines().drop(1).join("\n");

    }

    return data;

}

 

def WindowFixCmd(cmd, useWsl) {

    if(useWsl) {

        return WindowsWslCommand(cmd);

    }

    return cmd;

}

 

def WindowsWslCommand(cmd) {

    return "wsl ${cmd}";

}

 

def WindowsEscapeVarPercentage(str) {

    if(isUnix()) {

        return str;

    }

    // If we want literal %

    return str.replace("%", "%%");

}

 

def ConsoleScriptExtension() {

    if(isUnix()) {

        return ".sh";

    } else {

        return ".bat";

    }

}

 

def ConsoleCommandDelimiter() {

    // When doing command that must be execute no matter the results of the first one

    if(isUnix()) {

        return ";";

    } else {

        return "&";

    }

}

 

 

I did some file manipulation commands for files and folders manip (delete, create, exist, etc) some my pipeline scripts now run the same code on all platform without issues and remove the big if(isWindows()) mess all around.

 

Wish they have made this build in. This is a CI, this is what it should do manipulated files in many env. Feel like this is lacking big time.

 

If you want to detect the main platform for the 3 majors OS and you need to determine which one it is:

/*

* Platform specific check

*/

def GetOS() {

    if(isUnix()) {

        def uname = sh(script: 'uname', returnStdout: true);

        if(uname.startsWith("Darwin")) {

            return "MacOS";

        }

        // TODO godboutj 2019-07-30, Add other *nix check here

        return "Linux";

    }

    return "Windows";

}

 

def IsMacOS() {

    return GetOS() == "MacOS";

}

 

def IsLinux() {

    return GetOS() == "Linux";

}

 

def IsWindows() {

    return GetOS() == "Windows";

}

 

Then you can manipulate the path:

/*

* Path Manipulation

*/

def ToWindowsPath(path) {

    return path.replace("/", "\\");

}

 

def ToUnixPath(path) {

    return path.replace("\\","/");

}

 

def ToNativePath(path) {

    if(isUnix()) {

        return ToUnixPath(path);

    }

    return ToWindowsPath(path);

}

 

This allow for very simple scripts and make it bearable to work with the Jenkins API.

Reply all
Reply to author
Forward
0 new messages