How do I get java to exit when piped to head
Asked Answered
H

2

19

I have a java process which prints out a lot of text. Sometimes I just want to see a bit of the text. With normal programs I can just do:

$ myprog | head

I'll just see 10 lines of output from myprog and it will exit immediately. But with java, if I do:

$ java MyClass | head

I get the first 10 lines of output, but the java process won't exit until it's done with all of its processing. It's like java doesn't care that stdout (System.out) is gone and the head process is dead and gone.

All other programs either exit silently, like cat:

$ cat /etc/group | head
root:x:0:
daemon:x:1:
bin:x:2:
sys:x:3:
adm:x:4:
tty:x:5:
disk:x:6:
lp:x:7:
mail:x:8:
news:x:9:

Or exit with a broken pipe error/exception, like python:

$ python -c 'while True: print "hi"' | head
hi
hi
hi
hi
hi
hi
hi
hi
hi
hi
Traceback (most recent call last):
  File "<string>", line 1, in <module>
IOError: [Errno 32] Broken pipe

How can get java to raise an exception when calling System.out.println() when I pipe output to something like head? I'd love to be able to do something like:

try {
    while(true) {
        System.out.println("hi");
    }
} catch(BrokenPipeException e) {
    // exit gracefully
}
Hoopen answered 27/7, 2012 at 20:52 Comment(2)
SIGPIPE is sent to the java process in this case, but I'm not sure what java does with it. If you could check if the JVM has received a sigpipe and die, it should work.Secessionist
Java does special things with signals and I know from other issues that it's next to impossible to set a java program up to trap signals.Hoopen
C
1

If you don't like the .checkError() method from Sascha's answer and would rather receive exceptions you can use

OutputStream stream = new FileOutputStream(FileDescriptor.out);

You lose the PrintStream specific functions. In my case, they weren't relevant and this approach was easier than building a bunch of hacky checks.

Note that this will not behave if you've redirected the System.out via System.setOut, as FileDescriptor.out will point to the original output descriptor, not your redirected one.

Consonantal answered 16/6, 2014 at 5:52 Comment(0)
S
12

i'm using checkError()

From PrintStream-API-Docu:

Unlike other output streams, a PrintStream never throws an IOException; instead, exceptional situations merely set an internal flag that can be tested via the checkError method.

so try somthing like this:

        while(!System.out.checkError()) {
            System.out.println("hi");
        }
Scapegrace answered 27/7, 2012 at 21:11 Comment(1)
Thanks for the heads up on the docs. I had been looking everywhere for something like that, but for some reason glossed right over the top level description. That's super annoying, and it seems like it would be inefficient to call checkError every single time rather than just a try-catch.Hoopen
C
1

If you don't like the .checkError() method from Sascha's answer and would rather receive exceptions you can use

OutputStream stream = new FileOutputStream(FileDescriptor.out);

You lose the PrintStream specific functions. In my case, they weren't relevant and this approach was easier than building a bunch of hacky checks.

Note that this will not behave if you've redirected the System.out via System.setOut, as FileDescriptor.out will point to the original output descriptor, not your redirected one.

Consonantal answered 16/6, 2014 at 5:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.