command fails from exec() but works on terminal - java

I'm trying to convert pdf to txt by using Java. I've tried Apache PDFBox but, for some weird reason, it doesn't convert the whole document. For this reason I decided to use pdftotext by executing a Runtime.getRuntime().exec() call. The problem is that, while on my terminal pdftotext works flawlessly, the exec() call gives me error code 1 (sometimes even 99).
Here's the call:
pdftotext "/home/www-data/CANEFS_TEST/Hello/ciao.pdf" "/tmp/ciao.pdf.txt"
Here's the code
private static File callPDF2Text(File input,File output){
assert input.exists();
assert Utils.getExtension(input).equalsIgnoreCase("pdf");
assert Utils.getExtension(output).equalsIgnoreCase("txt") : output.getAbsoluteFile().toString();
Process p=null;
try {
System.out.println(String.format(
PDF2TXT_COMMAND,
input.getAbsolutePath(),
output.getAbsolutePath()));
p=Runtime.getRuntime().exec(String.format(
PDF2TXT_COMMAND,
input.getAbsolutePath(),
output.getAbsolutePath()));
p.waitFor();
if (p.exitValue()!=0){
throw new RuntimeException("exit value for pdftotext is "+p.exitValue());
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return output;
}
Here's PDF2TXT_COMMAND string definition:
public static final String PDFTXT_COMMAND="pdftotext \"%s\" \"%s\"";
I know that usually these kinds of errors are caused by the permission setup. So, here 's the output of ls -l command on the Hello folder:
ls -l /home/www-data/CANEFS_TEST/Hello/
total 136
-rwxrwxr-- 1 www-data www-data 136041 mar 27 16:31 ciao.pdf
Also, note that the user creating the process is koldar, which is in the group www-data itself.
Thank you for your time and patience!

Don't use " in your format string... These chars are specially parsed by the shell and you don't use a shell to launch the command...
I can suggest you to use exec(String []) not exec(String) so that you will be able to separate each arg of your command:
String []command = new String[3];
command[0] = "pdftotext";
command[1] = input.getAbsolutePath();
command[2] = output.getAbsolutePath();
Runtime.getRuntime().exec(command);
That should work. If it doesn't, that may be a question of access rights on dir.

Related

Script works in PyCharm but not in Windows Command Line

The line of code that breaks it:
frames = [Image.open(image) for image in glob.glob(f'{frame_folder}/*.jpg')]
frame_one = frames[0]
frame_one.save("X:\\Temp Photo Holder SolidScape Right\\resized\\progressRight.gif", format="GIF", append_images=frames,
save_all=True, optimize=True, duration=33, loop=0)
The exception that gets thrown:
File "genGif.py", line 10
frames = [Image.open(image) for image in glob.glob(f'{frame_folder}/*.jpg')]
^
SyntaxError: invalid syntax
The Java that I use to call the Python:
try {
Runtime rt = Runtime.getRuntime();
String new_dir = "C:\\Users\\user\\PycharmProjects\\rightProgressGifGen\\";
rt.exec("cmd.exe /c cd \"" + new_dir + "\" & start cmd.exe /k \"python genGif.py\"");
updateProgressRightGif();
} catch (Exception e) {
updateGlobalTime();
System.out.println(e);
tweet("Exception running emailTest(). Our time is " + globalHours + ":" + globalMinutes + ":" + globalSeconds);
}
Code works in PyCharm and Idle but not command line. Just need to be able to launch the script from Java somehow.
Are you sure your running Python3
I noticed in your exec function that you've written 'python genGif.py'
On some systems I've had to specify the version e.g. 'python3 genGif.py'
It would make sense that you would get an error with the f string as they weren't implemented until python3
Using string concatenation instead of os.path.join is a bad habit in multi-OS environment. Try that:
frames = [Image.open(image) for image in glob.glob(os.path.join(frame_folder, '*.jpg')]
Should there be an "f" right after the opening parentheses in glob.glob()?

How to edit summary.csv file after jmeter load run

After running my load test Jmeter generate result onto "summary.csv".
Some urls in this file looks like:
1482255989405,3359,POST ...users/G0356GM7QOITIMGA/...
1482255989479,3310,POST ...users/HRC50JG3T524N9RN/...
1482255989488,3354,POST ...users/54QEGZB54BEWOCJJ/...
Where "...users/G0356GM7QOITIMGA/..." - its URL column.
After that I try to generate jmeter-report using this command:
jmeter -g summary.csv -o report
Howewer this action throw Out of memory exception (because of many different URLs).
So I decide to edit summary.csv in tearDown Thread Group and replace all ID to "someID" string, using BeanShell Sampler:
import java.io.*;
import org.apache.jmeter.services.FileServer;
try {
String sep = System.getProperty("line.separator");
String summaryFileDirPath = FileServer.getFileServer().getBaseDir() + File.separator;
String summaryFilePath = summaryFileDirPath + "summary.csv";
log.info("read " + summaryFilePath);
File file = new File(summaryFilePath);
BufferedReader reader = new BufferedReader(new FileReader(file));
String line;
String text = "";
while ((line = reader.readLine()) != null) {
text += line + sep;
}
reader.close();
log.info(summaryFilePath);
file.delete();
FileWriter writer = new FileWriter(summaryFileDirPath + "summary.csv", false);
writer.write(text.replaceAll("users/[A-Z0-9]*/", "users/EUCI/"));
writer.close();
} catch (Exception e) {
e.printStackTrace();
}
Result:summary.csv screen
Seems like Jmeter append some rows after tearDown Thread Group ends his work.
How can I edit summary.csv file after test run using only jmeter script?
PS: I need collect result only in summary.csv
There is a JMeter Property - jmeter.save.saveservice.autoflush, most probably you are suffering from its default value of false
# AutoFlush on each line written in XML or CSV output
# Setting this to true will result in less test results data loss in case of Crash
# but with impact on performances, particularly for intensive tests (low or no pauses)
# Since JMeter 2.10, this is false by default
#jmeter.save.saveservice.autoflush=false
You can override the value in at least 2 ways:
Add the next line to user.properties file:
jmeter.save.saveservice.autoflush=true
Pass it to JMeter via -J command-line argument like:
jmeter -Jjmeter.save.saveservice.autoflush=true -n -t ....
See Apache JMeter Properties Customization Guide article for comprehensive information on JMeter Properties and ways of working with them

How to set charset of Runtime.getRuntime().exec?

Here is my code:
Process p = Runtime.getRuntime().exec(new String[]{"bash","-c",new String(command.getBytes(),"utf-8")});
I found out that there is no use of new String(command.getBytes(),"utf-8").
How can I to set charset?
My app is a spring boot application.
The detail command is
./xxx.jar --execute "select * from xxx where a = `我`"
When I execute the command directly in the shell, it runs well, but the java code gets garbled.
I set -Dfile.encoding=UTF-8,but it is no use for me. Why?
I found out that there is no use of new String(command.getBytes(),"utf-8").
This isn't accurate. Below is an example showing different character sets (ASCII and UTF-8) to run the same command using exec(), and the output is pretty clearly affected by the character set.
This program:
takes a single input parameter,
runs touch to create two files at /tmp/charset-test/ using that input value in the filename
further, if the input is a UTF-8 value, it should create a file with the UTF-8 value in the filename
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
public class CharsetTest {
public static void main(String[] args) throws IOException {
String input = args[0];
System.out.println("input: " + input);
Charset[] charsets = {StandardCharsets.US_ASCII, StandardCharsets.UTF_8};
for (Charset charset : charsets) {
String command = "touch /tmp/charset-test/" + input + "-" + charset.toString() + ".txt";
System.out.println("command: " + command);
// this is identical to your code, but:
// - use Charsets instead of "utf-8" so I can interate; "utf-8" also works
// - skip assigning to "Process p"
Runtime.getRuntime().exec(new String[]{
"bash", "-c", new String(command.getBytes(), charset)
});
}
}
}
If I run with ASCII input "simple", it creates two files, one for each charset: "simple-US-ASCII.txt" and "simple-UTF-8.txt". This isn't all that interesting, but shows both charsets work normally with basic (ASCII) input.
% rm /tmp/charset-test/*.txt && java CharsetTest.java simple
input: simple
command: touch /tmp/charset-test/simple-US-ASCII.txt
command: touch /tmp/charset-test/simple-UTF-8.txt
% ls /tmp/charset-test
simple-US-ASCII.txt simple-UTF-8.txt
If input changes to "我", then the ASCII charset handling results in the same "garbled" output you describe ("���-US-ASCII.txt"), whereas the UTF-8 version looks good ("我-UTF-8.txt"):
% rm /tmp/charset-test/*.txt && java CharsetTest.java 我
input: 我
command: touch /tmp/charset-test/我-US-ASCII.txt
command: touch /tmp/charset-test/我-UTF-8.txt
% ls /tmp/charset-test
我-UTF-8.txt ���-US-ASCII.txt
All of this to say: your code looks fine, it's doing the right thing to pass the charset to the Runtime.exec() call. I can't say what the proper solution would be, but it's likely something with the environment (not your code).

issue with running a perl script from java

I'm trying to run a Perl script file from java code but it's not working with me. I modified the Perl script and put the arguments in it instead of passing them via java code. The script works fine when running it from the command line but it's not working inside java code, always prints "wrong"!!. I wrote another Perl script (test.pl) and it's working but the desired script doesn't?? I'm working in netbeans7.3.1 (ubuntu).
Here is my code:
package program;
import java.io.*;
//import java.lang.ProcessBuilder;
/**
*
* #author seed
*/
public class Program {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws IOException,Exception {
File input = new File("//home//seed//Downloads//MADA-3.2//sample");
FileOutputStream out = new FileOutputStream(input);
PrintWriter p = new PrintWriter(out);
String s = "قصدنا في هذا القول ذكر";
p.println(s);
p.close();
Process pro = Runtime.getRuntime().exec("perl /home/seed/Downloads/MADA+TOKAN.pl");
pro.waitFor();
if(pro.exitValue() == 0)
{
System.out.println("Command Successful");
}
else{
System.out.print("wrong");}
// TODO code application logic here
}
}
My guess is that some kind of string/path conversion issue.
I see utf8 strings in your code, maybe the path is converted to something.
The filename (MADA+TOKAN.pl) contain special char, it would be better MADAplusTOKAN.pl.
Also your string in script and in question are not the same: (MADA 3.2 != MADA-3.2)
perl MADA+TOKAN.pl config=/home/seed/Downloads/mada/MADA-3.2/config files/template.madaconfig file=/home/seed/Downloads/mada/MADA 3.2/inputfile
vs
perl MADA+TOKAN.pl config=/home/seed/Downloads/MADA-3.2/config-files/template.madaconfig file=/home/seed/Downloads/MADA-3.2/sample
It sounds like it is finding your perl script and executing it, since test.perl and MADA.perl run OK.
It does sound like the arguments being passed in to the perl script are not what was expected. Can you modify the perl script to echo all its input parameters to a file?

Can Java launch the Windows UAC?

As the title says, I'm wondering if it is possible for a program written in Java (and only java) to relaunch himself (preferably a .jar) with administrator privileges, showing in the way the native Windows UAC (in order to make it more trustable for the user), i did my homework and found out that it is possible to accomplish this using bridges between c++ and java, but i would really like to do this as a pure java project.
P.S: In the remote case that this result to be impossible, can someone show me the "easy" way to do this using another language (i mean, I've found tutorials, but they are to complicated for something I think it should not be that complicated).
P.S2: In case it is possible to accomplish this, would it work, on other platforms (OS X, Linux)
It cannot be done in pure java.
Best bet would be to write this to a file:
#echo Set objShell = CreateObject("Shell.Application") > %temp%\sudo.tmp.vbs
#echo args = Right("%*", (Len("%*") - Len("%1"))) >> %temp%\sudo.tmp.vbs
#echo objShell.ShellExecute "%1", args, "", "runas" >> %temp%\sudo.tmp.vbs
#cscript %temp%\sudo.tmp.vbs
and save it as something.bat in Windows temp directory (as we have access to this).
You would then execute this from your application using Runtime or ProcessBuilder and exit your application (System.exit(0);).
You should add an immediate start up check to your application that checks if the program has elevation, if it has proceed if not re-run the batch and exit.
Here is an example I made (this must be run when compiled as a Jar or it wont work):
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import javax.swing.JOptionPane;
/**
*
* #author David
*/
public class UacTest {
public static String jarName = "UacTest.jar", batName = "elevate.bat";
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
if (checkForUac()) {//uac is on
JOptionPane.showMessageDialog(null, "I am not elevated");
//attempt elevation
new UacTest().elevate();
System.exit(0);
} else {//uac is not on
//if we get here we are elevated
JOptionPane.showMessageDialog(null, "I am elevated");
}
}
private static boolean checkForUac() {
File dummyFile = new File("c:/aaa.txt");
dummyFile.deleteOnExit();
try {
//attempt to craete file in c:/
try (FileWriter fw = new FileWriter(dummyFile, true)) {
}
} catch (IOException ex) {//we cannot UAC muts be on
//ex.printStackTrace();
return true;
}
return false;
}
private void elevate() {
//create batch file in temporary directory as we have access to it regardless of UAC on or off
File file = new File(System.getProperty("java.io.tmpdir") + "/" + batName);
file.deleteOnExit();
createBatchFile(file);
runBatchFile();
}
private String getJarLocation() {
return getClass().getProtectionDomain().getCodeSource().getLocation().getPath().substring(1);
}
private void runBatchFile() {
//JOptionPane.showMessageDialog(null, getJarLocation());
Runtime runtime = Runtime.getRuntime();
String[] cmd = new String[]{"cmd.exe", "/C",
System.getProperty("java.io.tmpdir") + "/" + batName + " java -jar " + getJarLocation()};
try {
Process proc = runtime.exec(cmd);
//proc.waitFor();
} catch (Exception ex) {
ex.printStackTrace();
}
}
private void createBatchFile(File file) {
try {
try (FileWriter fw = new FileWriter(file, true)) {
fw.write(
"#echo Set objShell = CreateObject(\"Shell.Application\") > %temp%\\sudo.tmp.vbs\r\n"
+ "#echo args = Right(\"%*\", (Len(\"%*\") - Len(\"%1\"))) >> %temp%\\sudo.tmp.vbs\r\n"
+ "#echo objShell.ShellExecute \"%1\", args, \"\", \"runas\" >> %temp%\\sudo.tmp.vbs\r\n"
+ "#cscript %temp%\\sudo.tmp.vbs\r\n"
+ "del /f %temp%\\sudo.tmp.vbs\r\n");
}
} catch (IOException ex) {
//ex.printStackTrace();
}
}
}
Use a batch file and the runas command.
I doubt "only Java". At best you would have to have a JNI wrapper around the MSFT module. Unless just invoking the exe using ProcessBuilder counts as "only Java" -- your code to bring up the user console would be only Java but not what it invokes. IOW, Win does not come with a Java API
To relaunch your application elevated, you have to call ShellExecute or ShellExecuteEx function from Windows API and use runas verb.
You can use these API in pure Java with JNA library.
To relaunch yourself, you would have to know the full path to java.exe or javaw.exe, the command-line parameters (class path, if any, and the path to your jar). Obviously you can get this information by using Windows API.
What do you mean by remote case?
You cannot start remote elevated process this way.
You can re-launch your application elevated from a network share. Yet it won't work with mapped drives: after elevation there's no access to user's mapped drives.
No, this can't work on other platforms. UAC is a Windows feature. It's similar to sudo in Linux in some ways, so for Linux you can use sudo $pathtojava/java.exe <yourparameters>. However this won't work nicely if your application is not started from a console. Window Managers usually have wrappers which prompt for password in a GUI dialog.
Just do this with Hackaprofaw (v29). Also it was released in 2002 and started development in 1997 soooooo ye. in 2021 its on version 29.10.7 but-
if raw ram = 0
disable "featureII" program = "JAVA(math = any)"
run on "Hackaprofaw (math = v29(x))
when "featureII" disabled
end

Categories

Resources