Spark/Gradle - 在build.gradle中获取IP地址以用于启动主服务器和工作服务器

Jim*_*hse 2 groovy master gradle build.gradle apache-spark

我在基本层面上理解了build.gradle构建脚本的各种移动部分,但是很难将它们捆绑在一起.

在Apache Spark独立模式下,只需尝试在build.gradle的同一个框中启动master和worker.(稍后将使用$ SPARK_HOME/sbin/start-slaves调用masterIP的正确参数进行扩展.)

问题:如何将我的IP地址分配给Groovy/build.gradle中的变量,以便将其传递给Exec任务中的命令?我们希望这可以在几台不同的开发机器上运行.

我们有一个(我认为相当标准)/ etc/hosts配置,其FQDN和主机名分配给127.0.1.1.驱动程序可以解决这个问题,但启动主机和主机名的从机不是一个选项,我需要IP地址.

我在尝试:

task getMasterIP (type: Exec){
    // declare script scope variable using no def or
    executable "hostname"
    args += "-I"

    // need results of hostname call assigned to script scope variable
    sparkMasterIP = <resultsOfHostnameCall>
}

// added this because startSlave stops if Master is already running
task startSlaveOnly(dependsOn:'getMasterIP', type: Exec){
    executable "/usr/local/spark/sbin/start-slave.sh"
    args += "spark://$sparkMasterIP:7077"
    doLast {
        println "enslaved"
    }
}

// now make startSlave call startSlaveOnly after the initial startMaster
task startSlave(dependsOn:'startMaster', type: Exec) {
    finalizedBy 'startSlaveOnly'
}
Run Code Online (Sandbox Code Playgroud)

当我尝试在Exec for Groovy调用的文档中建议的内容时:

task getMasterIP (type: Exec){
    // declare script scope variable using no def or
    sparkMasterIP = executable "hostname"
    args += "-I"
}
Run Code Online (Sandbox Code Playgroud)

我收到一条警告,说明无法识别可执行文件.


"关于我正在思考的更多背景"一节,不是主要问题.

谷歌搜索"build.gradle脚本范围变量"并查看前两个结果,在基本文档中我只看到一种类型的变量和要使用的ext属性.

16.4.声明变量 - 可以在构建脚本中声明两种变量:局部变量和额外属性.

但在其他Gradle文档附录B.潜在的陷阱我看到除ext属性之外的两种变量范围:

对于Gradle用户,了解Groovy如何处理脚本变量非常重要.Groovy有两种类型的脚本变量.一个具有本地范围,另一个具有脚本范围.

使用此示例用法:

String localScope1 = 'localScope1'
def localScope2 = 'localScope2'
scriptScope = 'scriptScope'
Run Code Online (Sandbox Code Playgroud)

我假设我应该使用没有"def"或类型声明的脚本范围变量.完全不同的方法完全开放,谢谢.

RaG*_*aGe 7

要获取本地IP:

//return all v4 addresses 
def getLocalIPv4() {
    def ip4s = []
    NetworkInterface.getNetworkInterfaces()
            .findAll { it.isUp() && !it.isLoopback() && !it.isVirtual() }
            .each {
        it.getInetAddresses()
                .findAll { !it.isLoopbackAddress() && it instanceof Inet4Address }
                .each { ip4s << it }
    }
    return ip4s
}

//optionally, return all ipv6 addresses
def getLocalIPv6() {
    def ip6s = []
    NetworkInterface.getNetworkInterfaces()
            .findAll { it.isUp() && !it.isLoopback() && !it.isVirtual() }
            .each {
        it.getInetAddresses()
                .findAll { !it.isLoopbackAddress() && it instanceof Inet6Address }
                .each { ip6s << it }
    }
    return ip6s
}



task printIP()<<{
    println getLocalIPv4()
    println getLocalIPv6()
}
Run Code Online (Sandbox Code Playgroud)

上面的两个函数分别返回ipv4或ipv6地址列表.您可能会注意到我正在跳过所有本地主机,未启动的接口,所有环回和虚拟接口.如果您想使用第一个ipv4地址,可以在其他地方使用它:

getLocalIPv4()[0]
Run Code Online (Sandbox Code Playgroud)

或者在你的情况下:

args += "spark:/"+ getLocalIPv4()[0] + ":7077"
Run Code Online (Sandbox Code Playgroud)

  • 从`{ip4s << it}`更改为`.each {ip4s << it.getHostAddress()}`以排除前导`/` (2认同)