我写了一个支持交互式命令的程序。我使用
java.util.Scanner
作为输入。
该程序也可以在后台运行,在这种情况下,不需要扫描仪。所以我想检查一下程序是否在后台运行。
事实上,当我使用
nohup java -jar my.jar &
时,扫描仪会抛出异常:
Exception in thread "main" java.util.NoSuchElementException: No line found
有了这个异常,我就可以知道这个程序正在后台运行。这不是问题。
但是,当我使用
java -jar my.jar &
时,程序就停止并显示:
[1]+ Stopped java -jar my.jar
没有抛出异常。就这样停了。
这是一个演示代码。您可以轻松地重现它。
import java.util.NoSuchElementException;
import java.util.Scanner;
public class ScannerTest {
public static void main(String[] args) {
new Thread(() -> {
while (true) {
System.out.println("I'm still working!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
return;
}
}
}).start();
System.out.println("Hi~");
try (Scanner scanner = new Scanner(System.in)) {
String s = scanner.nextLine();
System.out.println("s = " + s);
} catch (NoSuchElementException e) {
System.out.println("I'm running in the background!");
}
System.out.println("Bye~");
}
}
所以我的问题是,如何在java代码中识别这种情况?如何防止它“停止”?
终于我自己找到了办法。当使用
java -jar my.jar &
并显示“已停止”消息时,实际上会抛出 SIGTTIN
信号。
所以我们可以为这个信号注册一个
sun.misc.SignalHandler
。就像这样:
public class MySignalHandler implements SignalHandler {
public static void register() {
// The returne value (i.e. the default handler) should be
// ignored or the "Stopped" will still be shown.
Signal.handle(new Signal("TTIN"), new MySignalHandler());
}
private boolean handled;
private MySignalHandler() {
handled = false;
}
@Override
public void handle(Signal sig) {
if (!handled) {
// SIGTTIN may be thrown several times in a row.
// But we only need to handle it once.
handled = true;
System.err.println("SIGTTIN!");
System.exit(1);
}
}
}
现在程序将打印日志并退出(而不是“停止”)。
但我仍然没有找到一种方法来保持程序运行而不是让它退出。