在Java中启动Shell脚本并在退出

时间:2016-05-11 13:26:34

标签: linux bash shell processing

我需要一些特殊的设置来控制LED墙。可悲的是,我无法真正改变我使用的编程语言。我的设置如下:

处理(一些疯狂的java分叉...)草图在引导过程后启动。 Processing Sketch扫描文件夹中的子文件夹(可以启动的其他草图并控制LED墙)并启动Web服务器。服务器呈现包含所有已扫描文件夹的列表。单击“Web服务器”通过ProcessBuilder启动选定的Sketch。 Processing Sketch看起来像这样:

import http.*;
import java.util.*;
import java.lang.*;

SimpleHTTPServer server;
String prog = "";
int ExitValue = 1;
ProcessBuilder preparedsketch;
Process runningsketch;

void setup() {
  SimpleHTTPServer.useIndexHtml = false;
  server = new SimpleHTTPServer(this);
  TemplateFileHandler templateHandler = new ResultFiles("index.ftl");
  server.createContext("", templateHandler);
}


class ResultFiles extends TemplateFileHandler {
  public ResultFiles(String templateFileName) {
    super(templateFileName);
  }
  void createMap() {
    Map<String, String> params = queryToMap();
    if (params.containsKey("prog")) {
      if (params.get("prog").equals(prog)) {
        println("Has not changed");
      } else {
        println("PrevProcess: " + runningsketch);
        if (runningsketch != null) {
          println("Killing: " + runningsketch);
          runningsketch.destroy();
        }
        prog = params.get("prog");
        try {
          runningsketch = new ProcessBuilder("/Users/kessleml/dev/pixelpusher/base/processing-quit.sh", "--sketch=/Users/kessleml/dev/pixelpusher/base/sketches/pixelpusher_colourcycle_halloween", "--run").start();
          // runningsketch = new ProcessBuilder("/usr/local/bin/processing-java", "--force", "--sketch=" + sketchPath("sketches/" + prog + "/"), "--no-java", "--run").start();
        } catch (IOException ex) {
          println(ex);
        }
        println("ProjChagned: " + prog);
        println("NewProcess: " + runningsketch);
      }
    }

    File files = new File(sketchPath("sketches"));
    String[] fileslist = files.list();
    addVariable("files", fileslist);
    addVariable("selectedprog", prog);
  }
}

到目前为止一切都有效。但是,当然我想关闭一个正在运行(和循环)的草图,如果我改变(点击网站上的其他草图)。问题是:

当我通过runninngsketch = new ProcessBuilder("Path/To/ProcessingCLI", "--sketch=Path/To/Selected/Sketch", "--run").start();启动选定的草图时,会启动多个流程。原因是ProcessingCLI文件:

#!/bin/sh

# Prevents processing-java from stealing focus, see:
# https://github.com/processing/processing/issues/3996.
OPTION_FOR_HEADLESS_RUN=""
for ARG in "$@"
do
    if [ "$ARG" = "--build" ]; then
        OPTION_FOR_HEADLESS_RUN="-Djava.awt.headless=true"
    fi
done

cd "/Applications/Processing.app/Contents/Java" && /Applications/Processing.app/Contents/PlugIns/jdk1.8.0_74.jdk/Contents/Home/jre/bin/java -Djna.nosys=true $OPTION_FOR_HEADLESS_RUN -cp "ant-launcher.jar:ant.jar:core.jar:jna.jar:pde.jar:core/library/core.jar:core/library/gluegen-rt-natives-linux-amd64.jar:core/library/gluegen-rt-natives-linux-armv6hf.jar:core/library/gluegen-rt-natives-linux-i586.jar:core/library/gluegen-rt-natives-macosx-universal.jar:core/library/gluegen-rt-natives-windows-amd64.jar:core/library/gluegen-rt-natives-windows-i586.jar:core/library/gluegen-rt.jar:core/library/jogl-all-natives-linux-amd64.jar:core/library/jogl-all-natives-linux-armv6hf.jar:core/library/jogl-all-natives-linux-i586.jar:core/library/jogl-all-natives-macosx-universal.jar:core/library/jogl-all-natives-windows-amd64.jar:core/library/jogl-all-natives-windows-i586.jar:core/library/jogl-all.jar:modes/java/mode/antlr.jar:modes/java/mode/classpath-explorer-1.0.jar:modes/java/mode/com.ibm.icu.jar:modes/java/mode/JavaMode.jar:modes/java/mode/jdi.jar:modes/java/mode/jdimodel.jar:modes/java/mode/jdtCompilerAdapter.jar:modes/java/mode/jsoup-1.7.1.jar:modes/java/mode/org.eclipse.core.contenttype.jar:modes/java/mode/org.eclipse.core.jobs.jar:modes/java/mode/org.eclipse.core.resources.jar:modes/java/mode/org.eclipse.core.runtime.jar:modes/java/mode/org.eclipse.equinox.common.jar:modes/java/mode/org.eclipse.equinox.preferences.jar:modes/java/mode/org.eclipse.jdt.core.jar:modes/java/mode/org.eclipse.osgi.jar:modes/java/mode/org.eclipse.text.jar:modes/java/mode/org.netbeans.swing.outline.jar" processing.mode.java.Commander "$@"

所以ProcessBuilder启动了三个进程:一个sh-process启动两个Java-Children-Processes。当我使用runningsketch.destroy()时,它只会杀死sh进程。这两个Java进程继续运行。 (不确定这是否也是因为这个错误:http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4770092因为我在MacOS Yosemite上开发。最终的产品应该在Linux机器上运行。)

我的解决方案是编写一个新的sh脚本,通过trap杀死所有孩子:

#!/bin/sh

OPTION_FOR_HEADLESS_RUN=""

function killAllChildren {
    kill -9 -$(ps -o pgid= $$ | grep -o '[0-9]*')
}

trap killAllChildren SIGTERM SIGKILL
# trap "trap - SIGTERM && kill -- $$" SIGINT SIGTERM EXIT

cd "/Applications/Processing.app/Contents/Java"

/Applications/Processing.app/Contents/PlugIns/jdk1.8.0_74.jdk/Contents/Home/jre/bin/java -Djna.nosys=true $OPTION_FOR_HEADLESS_RUN -cp "ant-launcher.jar:ant.jar:core.jar:jna.jar:pde.jar:core/library/core.jar:core/library/gluegen-rt-natives-linux-amd64.jar:core/library/gluegen-rt-natives-linux-armv6hf.jar:core/library/gluegen-rt-natives-linux-i586.jar:core/library/gluegen-rt-natives-macosx-universal.jar:core/library/gluegen-rt-natives-windows-amd64.jar:core/library/gluegen-rt-natives-windows-i586.jar:core/library/gluegen-rt.jar:core/library/jogl-all-natives-linux-amd64.jar:core/library/jogl-all-natives-linux-armv6hf.jar:core/library/jogl-all-natives-linux-i586.jar:core/library/jogl-all-natives-macosx-universal.jar:core/library/jogl-all-natives-windows-amd64.jar:core/library/jogl-all-natives-windows-i586.jar:core/library/jogl-all.jar:modes/java/mode/antlr.jar:modes/java/mode/classpath-explorer-1.0.jar:modes/java/mode/com.ibm.icu.jar:modes/java/mode/JavaMode.jar:modes/java/mode/jdi.jar:modes/java/mode/jdimodel.jar:modes/java/mode/jdtCompilerAdapter.jar:modes/java/mode/jsoup-1.7.1.jar:modes/java/mode/org.eclipse.core.contenttype.jar:modes/java/mode/org.eclipse.core.jobs.jar:modes/java/mode/org.eclipse.core.resources.jar:modes/java/mode/org.eclipse.core.runtime.jar:modes/java/mode/org.eclipse.equinox.common.jar:modes/java/mode/org.eclipse.equinox.preferences.jar:modes/java/mode/org.eclipse.jdt.core.jar:modes/java/mode/org.eclipse.osgi.jar:modes/java/mode/org.eclipse.text.jar:modes/java/mode/org.netbeans.swing.outline.jar" processing.mode.java.Commander "$@"

但不知何故,这也不起作用。即使启动新的sh-script并将例如SIGTERM发送到已启动的sh-process,也不会破坏两个Java-Processes,也不会破坏sh-process。

1 个答案:

答案 0 :(得分:1)

我找到了解决方案:

Java发送SIGTERM信号,因此我必须捕获此信号。但java /处理文件不是问题,sh脚本没有按预期工作。

我必须在我的脚本中添加& wait。否则SIGTERM无法被困(参见这篇文章:https://apple.stackexchange.com/questions/123631/why-does-a-shell-script-trapping-sigterm-work-when-run-manually-but-not-when-ru)。

杀戮过程也没有成功。我必须杀死所有的孩子,sh-script本身但不是sh-script的父进程(在这个用例中是webserver等)。所以我写了一个函数来查找所有子进程并杀死它们。 kill -9 -$(ps -o pgid= $$ | grep -o '[0-9]*')之类的东西没有用,因为它们杀死了整棵树。最后,sh文件看起来像这样:

#!/bin/sh

function killAllChildren {
    getChild $$
    pkill -TERM -P $$
}

function getChild() {
    cpids=`pgrep -P $1|xargs`
    for cpid in $cpids;
    do
        kill -15 $cpid
        getChild $cpid
    done
}

trap killAllChildren SIGUSR1 SIGTERM SIGKILL EXIT

cd "/Applications/Processing.app/Contents/Java"

/Applications/Processing.app/Contents/PlugIns/jdk1.8.0_74.jdk/Contents/Home/jre/bin/java -Djna.nosys=true -cp "ant-launcher.jar:ant.jar:core.jar:jna.jar:pde.jar:core/library/core.jar:core/library/gluegen-rt-natives-linux-amd64.jar:core/library/gluegen-rt-natives-linux-armv6hf.jar:core/library/gluegen-rt-natives-linux-i586.jar:core/library/gluegen-rt-natives-macosx-universal.jar:core/library/gluegen-rt-natives-windows-amd64.jar:core/library/gluegen-rt-natives-windows-i586.jar:core/library/gluegen-rt.jar:core/library/jogl-all-natives-linux-amd64.jar:core/library/jogl-all-natives-linux-armv6hf.jar:core/library/jogl-all-natives-linux-i586.jar:core/library/jogl-all-natives-macosx-universal.jar:core/library/jogl-all-natives-windows-amd64.jar:core/library/jogl-all-natives-windows-i586.jar:core/library/jogl-all.jar:modes/java/mode/antlr.jar:modes/java/mode/classpath-explorer-1.0.jar:modes/java/mode/com.ibm.icu.jar:modes/java/mode/JavaMode.jar:modes/java/mode/jdi.jar:modes/java/mode/jdimodel.jar:modes/java/mode/jdtCompilerAdapter.jar:modes/java/mode/jsoup-1.7.1.jar:modes/java/mode/org.eclipse.core.contenttype.jar:modes/java/mode/org.eclipse.core.jobs.jar:modes/java/mode/org.eclipse.core.resources.jar:modes/java/mode/org.eclipse.core.runtime.jar:modes/java/mode/org.eclipse.equinox.common.jar:modes/java/mode/org.eclipse.equinox.preferences.jar:modes/java/mode/org.eclipse.jdt.core.jar:modes/java/mode/org.eclipse.osgi.jar:modes/java/mode/org.eclipse.text.jar:modes/java/mode/org.netbeans.swing.outline.jar" processing.mode.java.Commander "$@" & wait