I'd like to have a timeout for a pr开发者_高级运维ocess I start from Java. After the timeout, I'd like to kill the process. So far, so good. Problem is, I want to capture stderr/stdout during both normal execution and after a timeout. What happens if I kill the process with destroy()? Can I retrieve the (partial) stderr/stdout produced so far? Or are they gone?
Process handling is inherently OS-specific, I'm looking specifically at how Java handles Unix processes here.
It's unfortunate that Process
closes its streams when you call .destroy()
. I don't know why the JDK designers felt that was the right design pattern, but it certainly makes dealing with terminated processes more complicated.
It's worth noting that the InputStream
s Process
holds are instances of ProcessPipeInputStream
which actually has a drainInputStream()
method that does exactly what we'd want - it reads in any remaining bytes in the backing file descriptor and stores them in a byte buffer for us. This method is "called by the process reaper thread when the process exits", but unfortunately is not called when the process is TERM
'ed by .destroy()
.
The best you can hope for then is to jury-rig your own drainInputStream()
behavior and call that for both stdout
and stderr
before you call .destroy()
. It's still possible for some data to being written to either stream after you drain them but before .destroy()
finishes, but this will get most of it.
You should have one or two separate threads reading stdout
and stderr
(one if you merge them), apart from the thread that calls Process.exec()/waitFor()/destroy()
. The reading thread(s) will get any data that is produced up to an EOF. If you call Process.destroy()
, the EOF may happen sooner, that's all.
For any future time-travellers - Process.destroy()
indeed closes the streams as @dimo414's answer points out. However the actual termination of the process is handled by its ProcessHandle
retrieved by Process.toHandle()
which is what Process.destroy()
does before it then goes ahead and closes the streams.
So to cut a long story short, it is possible to terminate a Process
without closing the streams by doing:
process.toHandle().destroy()
精彩评论