STDOUT does not work programmatically via Groovy API - linux

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"

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]

groovy "...".execute() works on windows but fails on 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)

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);

Show output of a perl script in linux

I am using a web interface written in php that runs a perl script in a linux environment.It passes parameters(username,password,...) to the script . I want to view the output of the script without interfering with the process. Note that the script in his turn also passes data and excutes another program.
The script contains print commands like
if( $# ){
print "Error :".$#."\n";
print "skip...\n"; }
else{
}
I just want to view these results from the shell, also it would do it if i can save into a txt file .
thanks a lot!
Run the Perl program from the shell to see the output from print.
$ perl theprogram
⋮
Error : blah blah
skip...
⋮
Redirect STDOUT to save it into a file.
$ perl theprogram > theprogram.log
These are the very basics of shell usage, you already should know all this if you are a programmer. If not, read a Unix book for beginners.

Execute shell commands using popen in c++

I need to be able to execute some shell commands such as moving to the right directory where I have some files I need to decode and then decoding them using another command. I read some stuff about using popen but I didnt really understand how to use it for executing multiple commands.
Any pointers will be greatly appreciated :)
Thanks
FILE *pf;
char command[150];
char data[512];
// Execute a process listing
sprintf(command, "cd");
pf = _popen(command,"r");
sprintf(command, "cd Test_copy");
pf = _popen(command,"r"); */
sprintf(command, "java -jar Tool.jar -b x.fit x.csv");
pf = _popen(command,"r");
if(!pf){
fprintf(stderr, "Could not open pipe for output.\n");
return;
}
// Grab data from process execution
fgets(data, 512 , pf);
// Print grabbed data to the screen.
fprintf(stdout, "-%s-\n",data);
if (_pclose(pf) != 0)
fprintf(stderr," Error: Failed to close command stream \n");
Use ShellExecute to play with files (open with default application etc.). Use system to run shell commands.
No, don't. That would be like using a sledgehammer to knock on a door. Furthermore, it is "evil": http://www.cplusplus.com/forum/articles/11153/

Resources