确定 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
有什么想法吗?
谢谢 费德
假设您将 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"
}
}
据我所知Jenkins只区分windows和unix,即在windows上使用bat,在unix/mac/linux上使用sh。所以你可以使用
isUnix()
,更多信息在这里,来确定你是在unix还是windows上,如果是unix,请使用sh和@Spencer Malone的答案来提供有关该系统的更多信息(如果需要)。
我找到的解决方法是
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)
}
编辑:添加了在代理中运行时返回正确答案的支持
我最初使用@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';
}
}
}
这允许在任何管道上下文中调用该函数,并在代理中运行时返回预期结果。
使用 Java 类可能不是最好的方法。我非常确定,除非它是 jenkins / groovy 插件,否则它们都在主 Jenkins JVM 线程上运行。我会研究一种 shell 方法,例如这里概述的方法:https://stackoverflow.com/a/8597411/5505255
您可以将该脚本包装在 shell 步骤中以获取标准输出,如下所示:
def osName = sh(script: './detectOS', returnStdout: true)
调用上面概述的脚本的副本。然后让该脚本返回您想要的操作系统名称,并根据 osName var 分支逻辑。