如何确定 Jenkins 管道中的当前操作系统

问题描述 投票:0回答:5

确定 Jenkins 管道当前运行的操作系统的方法是什么?

上下文:我正在构建一个共享的 Jenkins 管道脚本,该脚本应该在所有平台(Windows、OSX、Linux)上运行,并在每个平台上执行不同的操作。

我尝试过类似的事情:

import org.apache.commons.lang.SystemUtils

if (SystemUtils.IS_OS_WINDOWS){
   bat("Command")
}
if (SystemUtils.IS_OS_MAC){
   sh("Command")
}
if (SystemUtils.IS_OS_LINUX){
   sh("Command")
}

但即使它在Windows或Mac上运行

node
它总是进入
SystemUtils.IS_OS_LINUX
分支

我尝试了这样的快速管道。

node('windows ') {
     println ('## OS ' + System.properties['os.name'])
}
node('osx ') {
     println ('## OS ' + System.properties['os.name'])
}
node('linux') {
     println ('## OS ' + System.properties['os.name'])
}

每个节点都在具有正确操作系统的机器上正确运行,但所有节点都打印

## OS Linux

有什么想法吗?

谢谢 费德

grails jenkins jenkins-pipeline
5个回答
22
投票

假设您将 Windows 作为唯一的非 Unix 平台,您可以使用管道函数

isUnix()
uname
来检查您所在的 Unix 操作系统:

def checkOs(){
    if (isUnix()) {
        def uname = sh script: 'uname', returnStdout: true
        if (uname.startsWith("Darwin")) {
            return "Macos"
        }
        // Optionally add 'else if' for other Unix OS  
        else {
            return "Linux"
        }
    }
    else {
        return "Windows"
    }
}

17
投票

据我所知Jenkins只区分windows和unix,即在windows上使用bat,在unix/mac/linux上使用sh。所以你可以使用

isUnix()
更多信息在这里,来确定你是在unix还是windows上,如果是unix,请使用sh和@Spencer Malone的答案来提供有关该系统的更多信息(如果需要)。


3
投票

我找到的解决方法是

try{
   sh(script: myScript, returnStdout: true)
 }catch(Exception ex) {
    //assume we are on windows
   bat(script: myScript, returnStdout: true)
 }

或者不使用

try/catch
的更优雅的解决方案是使用
env.NODE_LABELS
。假设您已正确标记所有节点,您可以编写这样的函数

def isOnWindows(){
    def os = "windows"
    def List nodeLabels  = NODE_LABELS.split()
    for (i = 0; i <nodeLabels.size(); i++) 
    {
        if (nodeLabels[i]==os){
        return true
        }
   }
    return false
 }

然后

if (isOnWindows()) {
    def osName = bat(script: command, returnStdout: true)   
} else {
    def osName = sh(script: command, returnStdout: true)
}

3
投票

编辑:添加了在代理中运行时返回正确答案的支持

我最初使用@fedterzi答案,但我发现它有问题,因为它导致了以下崩溃:

org.jenkinsci.plugins.workflow.steps.MissingContextVariableException: Required context class hudson.Launcher is missing

尝试在管道外部调用

isUnix()
时(例如分配变量)。我通过结合对 Java 系统属性的检查来解决这个问题,并在实际执行节点中测试
uname
的输出以确定操作系统:

def getOs()
{
    // Determine if I'm running in the Built-In node
    def nodeName = env.NODE_NAME;
    if (nodeName == null || nodeName == 'master' || nodeName == 'built-in')
    {
        // If so determine the OS using JDK system properties 
        String osname = System.getProperty('os.name');
        if (osname.startsWith('Windows'))
            return 'windows';
        else if (osname.startsWith('Mac'))
            return 'macos';
        else if (osname.contains("nux"))
            return 'linux';
        else
            throw new Exception("Unsupported os: ${osname}");
    }
    else
    {
        if (isUnix())
        {
            // https://stackoverflow.com/a/51059743/213871
            def uname = sh(script:"uname", returnStdout: true).trim();
            if (uname.startsWith('Darwin'))
                return 'macos';
            else if (uname.contains("Linux"))
                return 'linux';
            else
                throw new Exception("Unsupported os: ${uname}");
        }
        else
        {
            return 'windows';
        }
    }
}

这允许在任何管道上下文中调用该函数,并在代理中运行时返回预期结果。


0
投票

使用 Java 类可能不是最好的方法。我非常确定,除非它是 jenkins / groovy 插件,否则它们都在主 Jenkins JVM 线程上运行。我会研究一种 shell 方法,例如这里概述的方法:https://stackoverflow.com/a/8597411/5505255

您可以将该脚本包装在 shell 步骤中以获取标准输出,如下所示:

def osName = sh(script: './detectOS', returnStdout: true)

调用上面概述的脚本的副本。然后让该脚本返回您想要的操作系统名称,并根据 osName var 分支逻辑。

© www.soinside.com 2019 - 2024. All rights reserved.