使用Go管理Java进程

huangapple go评论82阅读模式
英文:

Manage Java process with go

问题

我已经准备好了JVM和所有Java程序的依赖项。使用Java,我会这样运行:

javac HelloWorld.java
java HelloWorld

现在我想在Linux环境下使用Go的cmd包来控制这个Java程序的进程。在Go中,当你运行命令时,会得到一个PID。有了这个PID,我想在需要的时候终止Java程序,并使用相同的cmd包重新启动。只要我安装了JVM,这样做是否能正常工作?我想这样做:

cmd := exec.Command("bash", "-c", "java HelloWorld")
cmd.Start()
syscall.Kill(cmd.Process.Pid)

谢谢!

英文:

I have JVM and all dependencies for my Java program ready. With Java I would run like:

javac HelloWorld.java
java HelloWorld

Now I want to, in Linux environment, control this Java program processes using Go's cmd package. In Go, when you run command you are given the PID. With this PID, I want to terminate the Java program whenever j want and restart using the same cmd package. Would this work correctly as long as I have JVM installed? I want to do:

cmd := exec.Command("bash", "-c", " "java HelloWorld")
cmd.Start()
syscall.Kill(cmd.Process.Pid)

Thanks!

答案1

得分: 1

简而言之,是的。

作为一个测试,添加了中断处理,这样你自己的Go进程就不会终止,这将起作用:

package main

import (
	"os/exec"
	"syscall"
	"os"
	"os/signal"
	"fmt"
)

func main() {

	cmd := exec.Command("bash", "-c", "java HelloWorld")
	err := cmd.Start()
	fmt.Printf("Starting java proccess with pid %d\n", cmd.Process.Pid)
	if err != nil {
		// do something about it
	}

	c := make(chan os.Signal, 1)
	done := make(chan bool, 1)
	signal.Notify(c, os.Interrupt)
	signal.Notify(c, syscall.SIGTERM)

	go func() {
		<-c
		fmt.Printf("Sending interrupt to pid: %d\n", cmd.Process.Pid)
		syscall.Kill(cmd.Process.Pid, syscall.SIGHUP)
		done <- true
	}()
	<-done

}

伴随的Java类:

public class HelloWorld {

    public static void main(String[] args) throws Exception {
        System.out.println("Hello World from Go! But you cant see me :)");
        while (true) {
            System.out.println("you cant see this because I am outing to the STDOUT of a subshell!");
            Thread.sleep(5000);
        }
    }
}

但是这里有很多需要注意的地方。只要你的Go进程正常退出,它将向指定的Java进程发送信号(如果我猜测的话,sighup是一个自然的选择)。但是你需要确保在你自己的Go进程崩溃或者在你告诉它关闭时,你的Java应用程序无法正常关闭时,不会产生僵尸进程。将该pid保存到/tmp/文件中,并在重新启动时对其进行各种操作可能是有趣的,但你要了解自己的需求。

编辑:从另一个程序控制JVM进程可能会很棘手。你应该评估一下自己是否真的想这样做。如果你使用的是Linux,我建议你看一下你的发行版使用的SysV init/systemd/upstart/start-stop-daemon系统,如果你的伴随Java程序充当守护进程的话。

英文:

In short, yes.

As a test, with added interrupt handling so your own Go process doesn't terminate this will work:

package  main

import (
	&quot;os/exec&quot;
	&quot;syscall&quot;
	&quot;os&quot;
	&quot;os/signal&quot;
	&quot;fmt&quot;
)

func main()  {

	cmd := exec.Command(&quot;bash&quot;, &quot;-c&quot;, &quot;java HelloWorld&quot;)
	err := cmd.Start()
	fmt.Printf(&quot;Starting java proccess with pid %d\n&quot;, cmd.Process.Pid)
	if err != nil {
		// do something about it
	}

	c := make(chan os.Signal, 1)
	done := make(chan bool, 1)
	signal.Notify(c, os.Interrupt)
	signal.Notify(c, syscall.SIGTERM)

	go func() {
		&lt;-c
		fmt.Printf(&quot;Sending interrupt to pid: %d\n&quot;, cmd.Process.Pid)
		syscall.Kill(cmd.Process.Pid, syscall.SIGHUP)
		done &lt;- true
	}()
	&lt;-done

}

Companion Java class:

public class HelloWorld {

    public static void main(String[] args) throws Exception {
        System.out.println(&quot;Hello World from Go! But you cant see me :)&quot;);
        while (true) {
            System.out.println(&quot;you cant see this because I am outing to the STDOUT of a subshell!&quot;);
            Thread.sleep(5000);
        }
    }
}

But it is full of gotchas. As long as your Go process exits normally, it will send the signal you specify (sighup would be natural choice, if I'd venture a guess) to the java pid. But you need to ensure that you wont let a zombie in case your own Go process crash or in case your java application hangs on after failing to shut down cleanly when you tell it to. Saving that pid to a /tmp/ file and doing all sorts of things with it in case of a restart could be interesting, but you know your needs.

Edit: controlling a JVM process from another program might get finicky quick. You should evaluate if you really want to do that. If you are in Linux, I'd take a look at the SysV init/systemd/upstart/start-stop-daemon system your distro uses if your companion java program acts as a daemon.

huangapple
  • 本文由 发表于 2016年3月10日 09:53:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/35906190.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定