groovy "...".execute() works on windows but fails on linux - linux

while this line works fine on windows on my linux box it returns exit code 1.
"gnuplot -e \"set output '${imageFile.toString()}'; filename='${dataFile.toString()}'; ${args}\" \"${plotFile.toString()}\"".execute()
But if I execute just this from the terminal everything works.
gnuplot -e "set output '/tmp/hrp-current.jpg'; filename='/tmp/a731265b-3736-4bb9-acf4-b92c1a09b999.csv'; " "/tmp/hrp/build/groovy/../gnuplot/hrp-current.gnuplot"
What am I missing here? It somehow has to do with the fact that gnuplot writes to a file because `some_command > some.file" also fails on linux with exit code 1 while it would work fine on windows.

.execute() on a String just splits on whitespace. You also don't need to quote the params for execution (you need to that for the shell). So execute an list of params instead:
["gnuplot", "-e", "set output '${imageFile.toString()}'; filename='${dataFile.toString()}'; ${args}", plotFile.toString()].execute()

Indeed it is some file writing issue so I need gnuplot to pipe its outout to stdout and then consume it from my groovy script where I read the outputstream and then save it to a file:
def out = new ByteArrayOutputStream()
def err = new ByteArrayOutputStream()
process.waitForProcessOutput(out, err)

Related

How to exclude $ from process builder String parameter, to execute a shell command

I am trying to escape the "$" symbol when executing a echo $! command in java.
static def execSync(String command) throws Exception {
log.info("exec(" + command + ")")
String[] splited = command.split("\\s+")
def listCommand = Arrays.asList(splited)
ProcessBuilder processBuilder = new ProcessBuilder()
processBuilder.command(listCommand)
return processBuilder.start()
}
execSync("echo \$!") // returns $! when i'd like a pid
I have identified the problem to be in the command that is executed (ie: the code above) and not from my way of getting the stdout of the command (outputstream blabla). If your are absolutely sure it's not, i'll show more.
When i execute on my system (centOs 7) "echo $!" i obviously get a pid, for instance : 2626.
I would mostly like to know if there is a way to do a "echo $!" like on the system with a string in my function ? (regex or other stuff)
Otherwise,
ProcessBuilder.start returns a Process but doesn't seem to have a method to get the pid, only exitReturn, out/in/error stream... Since I execute the previous command with the method shown above, i though i could get the pid with a linux command.
So, is there a way to get the pid of the previous process ? (not realy what i seek but i can manage if there is no other way)
I'm stuck with java 8, when java 9 has a method "getPid"
If you .execute() or use the ProcessBuilder directly, you can not directly use shell features. It just allows to spawn processes with arguments. You have to start a shell and make it execute your shell "script" (command). E.g.
def listCommand = ["/bin/sh", "-c", command]

os.system(cmd) call fails with redirection operator

My Python 3.7.1 script generates a fasta file called
pRNA.sites.fasta
Within the same script, I call following system command:
cmd = "weblogo -A DNA < pRNA.sites.fasta > OUT.eps"
os.system(cmd)
print(cmd) #for debugging
I am getting the following error message and debugging message on the command line.
Error: Please provide a multiple sequence alignment
weblogo -A DNA < pRNA.sites.fasta > OUT.eps
"OUT.eps" file is generated but it's emtpy. On the other hand, if I run the following 'weblogo' command from the command line, It works just find. I get proper OUT.eps file.
$ weblogo -A DNA<pRNA.sites.fasta>OUT.eps
I am guessing my syntax for os.system call is wrong. Can you tell me what is wrong with it? Thanks.
Never mind. It turned out to be that I was not closing my file, "pRNA.sites.fasta" before I make system call that uses this file.

How to get mongo shell output(three dot) for unterminated command

When type a unterminated command in a mongo shell, it will return three dots indicating need more input to complete this command like below:
> db.test.find(
... {
...
I am using nodejs child_process.spawn to create a mongo shell process and listen on its output. I can get the standard and error output from the mongo shell but I can't get the ... output. Below is my nodejs code:
const shell = spawn('mongo', params);
shell
.stdout
.on('data', (data) => {
winston.debug('get output ' + data);
});
shell
.stderr
.on('data', (data) => {
const output = data + '';
winston.error('get error output ', data);
});
I run below code to send command on the shell:
shell.stdin.write('db.test.find(');
I wander why I can't get the ... output on above method. Is it a special output?
EDIT1
I tried to use node-pty and pty.js. They can get the ... output but they mix the input and output data together. It is not possible to separate them.
I also tried to use stdbuf and unbuffer to disable buffer but it still doesn't work.
It seems that nodejs child_process doesn't work well with interactive command.
Your code doesn't include anything that writes to the stdin of your child process so I would be surprised if you got the ellipsis that indicates incomplete command when in fact you don't send any command at all - incomplete or otherwise.
That having been said, many command line utilities behave differently when they discover a real terminal connected to their stdin/stdout. E.g. git log will page the results when you run it directly but not when you pipe the results to some other command like git log | cat so this may also be the case here.
This can also have to do with the buffering - if your stream is line-buffered then you won't see any line that is not ended with a newline right away.
The real question is: do you see the > prompt? Do you send any command to the mongo shell?
Scritping interactive CLI tools can be tricky. E.g. see what I had to do to test a very simple interactive program here:
https://github.com/rsp/rsp-pjc-c01/blob/master/test-z05.sh#L8-L16
I had to create two named pipes, make sure that stdin, stderr and stdout are not buffered, and then use some other tricks to make it work. It is a shell script but it's just to show you an example.

STDOUT does not work programmatically via Groovy API

Using espeak command to generate an audio
espeak "Hello Mr. Toumi" --stdout > /tmp/audio123.wav
When i run this command using terminal , it works fine .
Prepare now in API for this command in Grails Service
#EspeakService.groovy
File speak(String message){
Process pr='espeak "'+message+'" --stdout > '+filePath(message);
pr.waitFor()
return new File(filePath(message));
}
When i run : espeakService.speak('Hello Mr. Toumi') , there is no file generated and also no error message displayed .
Any idea : Why does it not work programmatically ?
Java's external process execution mechanism is not a shell and doesn't support redirection using > like that. You should use a ProcessBuilder and do the redirection with that:
ProcessBuilder pb = new ProcessBuilder("espeak", message, "--stdout")
File out = new File(filePath(message))
pb.redirectOutput(out)
pb.redirectError(ProcessBuilder.Redirect.INHERIT)
pb.start().waitFor()
return out
redirections like > are done by shell. either use ['sh', '-c', 'espeak ...'].execute(). or just pick up the stdout from the process, which would save you from dealing with a file. e.g.
def p = "echo -n 666".execute()
p.waitFor()
assert p.in instanceof InputStream
assert p.in.text == "666"

capture process output in Groovy

I have a Groovy script that recurses through a directory looking for .png files, and invokes pngquant (a command-line utility) on each of. The output of pngquant should be printed on the terminal. The relevant code is:
def command = "pngquant -f -ext .png"
root.eachFileRecurse(groovy.io.FileType.FILES) {File file ->
if (file.name.endsWith('.png')) {
println "Compressing file: $file"
def imgCommand = "$command $file.absolutePath"
Process pngquantCmd = imgCommand.execute()
pngquantCmd.consumeProcessOutput(System.out, System.err)
}
}
The script works fine, but once all the files have been processed, it seems that stout is still being redirected, because the command-prompt never appears unless I kill the process with Ctrl + C. Do I need to somehow "undo"
pngquantCmd.consumeProcessOutput(System.out, System.err)
or is there a better way to redirect the output of this process to the console? I guess I could solve this problem simply by adding System.exit(0), but this doesn't seem like the right solution. The problem only occurs on Linux.
Instead of
pngquantCmd.consumeProcessOutput(System.out, System.err)
Which will start a couple of threads to read the outputs and plough on regardless of the process' situation, you should try
pngquantCmd.waitForProcessOutput(System.out, System.err)
Which will redirect the process output and then wait for it to finish before moving on :-)
You can also do
Process pngquantCmd = imgCommand.execute();
def output= pngquantCmd.text;
println("Output : " + output);

Resources