วิธีตรวจหา OS ปัจจุบันจาก Gradle


106

ฉันพบคำตอบเกี่ยวกับวิธีการใช้ Groovy:

การตรวจจับแพลตฟอร์ม (Window หรือ Linux) โดย Groovy / Grails :

if (System.properties['os.name'].toLowerCase().contains('windows')) {
    println "it's Windows"
} else {
    println "it's not Windows"
}

มีวิธีที่ดีกว่า?


นั่นคือสิ่งที่ฉันใช้โดยไม่มีtoLowerCase().contains()ส่วนเพราะฉันแค่ต้องการชื่อ
Kevin Welker

คุณยังสามารถรับเวอร์ชัน OS ได้ด้วยSystem.getProperty('os.arch')
Kevin Welker

13
"WINDOWS".toLowerCase()ขึ้นอยู่กับโลแคลและจะส่งคืนwındows(สังเกต i แบบไม่มีจุด) บนเครื่องที่โลแคลเป็นภาษาตุรกี ใช้toLowerCase(Locale.ROOT)แทนเพื่อให้อยู่ในด้านที่ปลอดภัย
Matthias Braun

คำตอบ:


130

จริงๆแล้วฉันดูโครงการ Gradle และสิ่งนี้ดูสะอาดขึ้นเล็กน้อยเนื่องจากใช้โครงสร้างที่มีอยู่ของ Ant :

import org.apache.tools.ant.taskdefs.condition.Os

task checkWin() << {
    if (Os.isFamily(Os.FAMILY_WINDOWS)) {
        println "*** Windows "
    }
}

ฉันพบสิ่งนี้ในสาขา Gradle ต่อไปนี้และดูเหมือนว่าจะทำงานได้ดี gradle / gradle-core / สาขา / RB-0.3 / build.gradle


8
ได้รับการเตือน Os.isFamily (Os.FAMILY_UNIX) จะคืนค่า true ทั้งสำหรับ unix และ mac (ในขณะที่ Os.isFamily (Os.FAMILY_MAC) ก็ใช้ได้เช่นกัน
shabunc

3
โปรดระวังว่านี่เป็นระบบปฏิบัติการจริง ๆ และไม่ได้บอกว่าไม่มีอะไรเกี่ยวกับการเริ่มต้นเชลล์เชลล์ (เช่นอาจเป็น Mingw, Cygwin หรือ bash shell อื่น ๆ ) ดังนั้นโปรดใช้ความระมัดระวังหากคุณใช้เพื่ออ่านตัวแปรสภาพแวดล้อมสิ่งเหล่านี้อาจไม่ใช่สิ่งที่คุณคาดหวัง
estani

2
@shabunc มีทางออกที่ดีกว่าโดยใช้ org.gradle.internal.os.OperatingSystem
Peter Kahn

task checkWin() << {ทำไมคุณถึงต้องการมัน? คุณสามารถเขียนif (Os.isFamily(Os.FAMILY_WINDOWS)) { println "*** WINDOWS " }
user25

ยังดีกว่าที่จะใช้org.gradle.internal.os.OperatingSystemและif (OperatingSystem.current() == OperatingSystem.WINDOWS)(ถ้าเราพูดถึง Gradle ทำไมไม่ใช้การใช้งานของตนเอง)
25

75

การอัปเดตกลางปี ​​2020 : ยังอยู่ในระหว่างการฟักตัว:

OperatingSystem os = org.gradle.nativeplatform.platform.internal.DefaultNativePlatform.currentOperatingSystem; 

การอัปเดตต้นปี 2019 : current()ลบออก

org.gradle.nativeplatform.platform.OperatingSystem.getDisplayName()

org.gradle.nativeplatform.platform.OperatingSystem.isLinux()

เก็บไว้ในใจว่ามันยังคงบ่มแม้ว่า

การอัปเดตกลางปี ​​2018 : เช่นเดียวกับที่กล่าวไว้ในความคิดเห็นตอนนี้คลาสนี้ถูกย้ายไปยังแพ็คเกจอื่นดังนั้นควรใช้org.gradle.nativeplatform.platform.OperatingSystem.current()


ในช่วงกลางปี ​​2015 คำตอบของ Peter Kahn ยังคงใช้ได้ การเปิดใช้งานโปรไฟล์ตามสภาพแวดล้อมยังคงเป็นสิ่งที่ทำได้ง่ายกว่าใน Maven แต่โปรดจำไว้ว่าorg.apache.tools.ant.taskdefs.condition.Os.isFamilyไม่เป็นเอกสิทธิ์ในแง่ที่ว่าหากส่งคืนค่าจริงด้วยพารามิเตอร์หนึ่งพารามิเตอร์นั้นไม่จำเป็นต้องหมายความว่าจะส่งคืนค่าเท็จสำหรับพารามิเตอร์อื่น ตัวอย่างเช่น:

import org.apache.tools.ant.taskdefs.condition.Os
task detect {
    doLast {
        println(Os.isFamily(Os.FAMILY_WINDOWS))
        println(Os.isFamily(Os.FAMILY_MAC))
        println(Os.isFamily(Os.FAMILY_UNIX))
    }
}

มันจะกลับมาเป็นจริงทั้งสำหรับOs.FAMILY_MACและOs.FAMILY_UNIXบน MacOS โดยปกติแล้วจะไม่ใช่สิ่งที่คุณต้องการในการสร้างสคริปต์

มีอีกวิธีหนึ่งในการบรรลุสิ่งนี้โดยใช้ Gradle 2+ API ได้แก่ :

import org.gradle.internal.os.OperatingSystem;

task detect {
    doLast {
        println(OperatingSystem.current().isMacOsX())
        println(OperatingSystem.current().isLinux())
    }
}

ตรวจสอบเอกสารสำหรับอินเทอร์เฟซorg.gradle.nativeplatform.platform.OperatingSystem ควรกล่าวถึงว่าอินเทอร์เฟซนี้มีเครื่องหมายบ่มเพาะคำอธิบายประกอบนั่นคือ "คุณลักษณะนี้กำลังดำเนินการอยู่และอาจเปลี่ยนแปลงได้ตลอดเวลา" เนมสเปซ "ภายใน" ในการใช้งานยังช่วยให้เรามีคำใบ้ว่าเราควรใช้สิ่งนี้โดยรู้ว่าสิ่งนี้สามารถเปลี่ยนแปลงได้

แต่โดยส่วนตัวแล้วฉันจะใช้วิธีนี้ แค่เขียนคลาส wrapper จะดีกว่าเพื่อไม่ให้ยุ่งเหยิงเผื่อว่าจะมีอะไรเปลี่ยนแปลงในอนาคต


8
มีการเปลี่ยนแปลงหรือไม่? การใช้ Gradle 2.5 OperatingSystemดูเหมือนจะไม่มี.current()
Ross Drew

6
คำนึงถึงแพ็คเกจภายใน:org.gradle.internal.os.OperatingSystem.current()
Brian

@danblack คุณจะได้รับอินสแตนซ์OperatingSystemได้current()อย่างไร?
TWiStErRob

1
พบหนึ่ง: OperatingSystem os = org.gradle.nativeplatform.platform.internal.DefaultNativePlatform.currentOperatingSystem; หวังว่าจะมีคนสาธารณะ @PeterNiederwieser
TWiStErRob

เนื่องจาก Mac OS, Windows และ Linux ไม่ใช่ระบบปฏิบัติการเพียงระบบเดียวจึงเป็นการดีถ้ารวม z / OS แม้ว่าจะอยู่ในช่วงเวลาสั้น ๆ แต่การเลือกที่จะไม่เลือกคนอื่นก็สามารถทำได้
John Czukkermann

18

เราสามารถแยกความแตกต่างของสภาพแวดล้อมการสร้างระหว่าง Linux, Unix, Windows และ OS X - ในขณะที่ Gradle nativeplatform.platform.OperatingSystemทำให้สภาพแวดล้อมเป้าหมายแตกต่างกัน(รวมถึงFreeBSDและSolaris )

import org.gradle.internal.os.OperatingSystem

String osName = OperatingSystem.current().getName();
String osVersion = OperatingSystem.current().getVersion();
println "*** $osName $osVersion was detected."

if (OperatingSystem.current().isLinux()) {
    // Consider Linux.
} else if (OperatingSystem.current().isUnix()) {
    // Consider UNIX.
} else if (OperatingSystem.current().isWindows()) {
    // Consider Windows.
} else if (OperatingSystem.current().isMacOsX()) {
    // Consider OS X.
} else {
    // Unknown OS.
}

นอกจากนี้ยังสามารถใช้งาน Ant (ที่มา ):

import org.apache.tools.ant.taskdefs.condition.Os

task checkWin() << {
    if (Os.isFamily(Os.FAMILY_WINDOWS)) {
        // Consider Windows.
    }
}

8

หรือคุณสามารถกำหนด osName เป็นสตริง ...

import org.gradle.internal.os.OperatingSystem

switch (OperatingSystem.current()) {
    case OperatingSystem.LINUX:
        project.ext.osName = "Linux";
        break;
    case OperatingSystem.MAC_OS:
        project.ext.osName = "macOS";
        break;
    case OperatingSystem.WINDOWS:
        project.ext.osName = "Windows";
        break;
}

... และใช้ในภายหลัง - เพื่อรวมไลบรารีดั้งเดิมเช่น:

run {
    systemProperty "java.library.path", "lib/$osName"
}

แต่จะไม่เปลี่ยนแปลงอะไรเนื่องจาก OperatingSystem ทำงานเหมือนกับโค้ดของคุณ:

public static OperatingSystem forName(String os) {
    String osName = os.toLowerCase();
    if (osName.contains("Windows")) {
        return WINDOWS;
    } else if (osName.contains("mac os x") || osName.contains("darwin") || osName.contains("osx")) {
        return MAC_OS;
    } else if (osName.contains("sunos") || osName.contains("solaris")) {
        return SOLARIS;
    } else if (osName.contains("linux")) {
        return LINUX;
    } else if (osName.contains("freebsd")) {
        return FREE_BSD;
    } else {
        // Not strictly true
        return UNIX;
    }
}

ที่มา: https://github.com/gradle/gradle/blob/master/subprojects/base-services/src/main/java/org/gradle/internal/os/OperatingSystem.java

แก้ไข:

คุณสามารถทำเช่นเดียวกันสำหรับสถาปัตยกรรม:

project.ext.osArch = OperatingSystem.current().getArch();
if ("x86".equals(project.ext.osArch)) {
    project.ext.osArch = "i386";
}

และ:

run {
    systemProperty "java.library.path", "lib/$osName/$osArch"
}

โปรดทราบว่า getArch () จะส่งคืน:

  • "ppc" บน PowerPC
  • "amd64" บน 64b
  • "i386" หรือ "x86" บน 32b

getArch () จะส่งคืน "x86" บน Solaris หรือ "i386" สำหรับแพลตฟอร์มอื่น ๆ

แก้ไข 2:

หรือหากคุณต้องการหลีกเลี่ยงการนำเข้าใด ๆ คุณสามารถทำได้ด้วยตัวเอง:

def getOsName(project) {
    final String osName = System.getProperty("os.name").toLowerCase();

    if (osName.contains("linux")) {
        return ("linux");
    } else if (osName.contains("mac os x") || osName.contains("darwin") || osName.contains("osx")) {
        return ("macos");
    } else if (osName.contains("windows")) {
        return ("windows");
    } else if (osName.contains("sunos") || osName.contains("solaris")) {
        return ("solaris");
    } else if (osName.contains("freebsd")) {
        return ("freebsd");
    }
    return ("unix");
}

def getOsArch(project) {
    final String osArch = System.getProperty("os.arch");

    if ("x86".equals(osArch)) {
        return ("i386");
    }
    else if ("x86_64".equals(osArch)) {
        return ("amd64");
    }
    else if ("powerpc".equals(osArch)) {
        return ("ppc");
    }
    return (osArch);
}

สถาปัตยกรรมไม่ได้รับการร้องขอ - และการสร้างล้อขึ้นมาใหม่นั้นไร้ประโยชน์ นี่อาจเป็นความชอบส่วนบุคคล แต่โปรแกรมเมอร์ส่วนใหญ่จะใช้การนำเข้าเมื่อใดก็ตามที่สามารถใช้การนำเข้าได้ (โดยใช้เฟรมเวิร์ก แต่ไม่ได้ใช้งานอาจสร้างโค้ดที่ซ้ำกันเท่านั้น)
Martin Zeitler

7

Gradle ไม่มี API สาธารณะสำหรับตรวจจับระบบปฏิบัติการ ดังนั้นos.คุณสมบัติของระบบจึงเป็นทางออกที่ดีที่สุดของคุณ


4

ฉันไม่ชอบตรวจจับ OS ใน Gradle ผ่านคุณสมบัติหรืองาน Ant และOperatingSystemคลาสนี้ไม่มีcurrent()เมธอดอีกต่อไป

ดังนั้นในความคิดของฉันวิธีที่สะอาดที่สุดในการตรวจจับระบบปฏิบัติการคือ:

นำเข้า DefaultNativePlatform:

import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform

จากนั้นใช้DefaultNativePlatformในงานของคุณ:

if (DefaultNativePlatform.getCurrentOperatingSystem().isWindows()) {
   println 'Windows'
}

โปรดทราบว่าวิธีนี้ไม่เหมาะเนื่องจากใช้ Gradle internal API

ได้รับการทดสอบด้วย Gradle 4.10

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.