Long Thai
Long Thai

Reputation: 817

Deal with executing Unix command which produces an endless output

Some unix command such as tail -f or starting a python web server (i.e. cherrypy) will produce an endless output, i.e. the only way to stop it is to Ctrl-C. I'm working on a scala application which execute the command like that, my implemetation is:

import scala.sys.process._
def exe(command: String): Unit = {
    command !
}

However, as the command produces an endless output stream, the application hangs there until I either terminate it or kill the process started by the command. I also try to add & at the end of the command in order to run it in background but my application still hangs.

Hence, I'm looking for another way to execute a command without hanging my application.

Upvotes: 5

Views: 1613

Answers (3)

nairbv
nairbv

Reputation: 4323

Seq("sh", "-c", "tail -f /var/log/syslog > /dev/null &") !

works for me. I think Randall's answer fails because scala is just executing the commands, and can't interpret shell operators like "&". If the command passed to scala is "sh" and the arguments are a complete shell command, we work around this issue. There also seems to be an issue with how scala parses/separates individual arguments, and using a Seq instead of single String works better for that.

The above is equivalent to the unix command:

sh -c 'tail -f /var/log/syslog > /dev/null &'

Upvotes: 2

Rex Kerr
Rex Kerr

Reputation: 167891

You can use a custom ProcessLogger to deal with output however you wish as soon as it is available.

val proc = 
  Process(command).run(ProcessLogger(line => (), err => println("Uh-oh: "+err)))

You may kill a process with the destroy method.

proc.destroy

If you are waiting to get a certain output before killing it, you can create a custom ProcessLogger that can call destroy on its own process once it has what it needs.

You may prefer to use lines (in 2.10; the name is changing to lineStream in 2.11) instead of run to gather standard output, since that will give you a stream that will block when no new output is available. Then you wrap the whole thing in a Future, read lines from the stream until you have what you need, and then kill the process--this simplifies blocking/waiting.

Upvotes: 3

Randall Schulz
Randall Schulz

Reputation: 26486

If you close the descriptor(s) from which you're reading the process' output, it will get a SIGPIPE and (usually) terminate.

If you just don't want the output, redirect to /dev/null:

command arg arg arg >/dev/null 2>&1

Addendum: This pertains only to Unix-alike systems, not Windows.

Upvotes: 0

Related Questions