I have code like below
ProcessBuilder pb = new ProcessBuilder("bash", "-c",
" awk -f awkfile " + " file2 " + file1);
p = pb.start();
p.waitFor();
p.destroy();
pb = new ProcessBuilder("bash", "-c",
" awk -f awkfile " + " file3 " + outFile);
p = pb.start();
p.waitFor();
p.destroy();
pb = new ProcessBuilder("bash", "-c",
" awk -f awkfile " + " file4 " + outFile);
p = pb.start();
p.waitFor();
p.destroy();
awkfile has the contents
FILENAME==ARGV[1] {vals[$1FS$2FS$3] = ",Y"; next}
!($1FS$2FS$3 in vals) {vals[$1FS$2FS$3] = ",N"}
{$(NF+1) = vals[$1FS$2FS$3]; print > "outFile"}
The first ProcessBuilder runs fine.The outFile has complete output (I commented out the remaining code and tested). When I include the second ProcessBuilder or third processbuilder then the outFile is incomplete.
Is this a space issue or a memory issue.
I do not how to find the total space allocated to my home directory.
The du command results are below
du -s /home/xxxxx
19172 /home/xxxxx
the df command results are below
df -k /home/xxxxx
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/mapper/rootvg-homelv 2064208 193068 1766296 10% /home
Is the available above 1766296 for the entire /home directory or just for my home directory /home/xxxxx
Can you please guide me as to how to get past this issue.
Unless quotas are enabled, you can go upto the max of what is available on your filesystem.
du -s reports the disk usage for the entire directory. I prefer the "du -sh /home/xxxx" which should report it in Mbytes, Kbytes etc.,
df -k (I prefer df -h) says how much free space is available on the entire disk (or volume) on which the filesystem is present. Note that this may include the home directories of all users.
If quotas are enabled, then you can use quota -v to see what your quotas are on each filesystem.
Looks like what you are trying to do is:
take the 3 fields from the first file
print out the lines from the second file with a ",Y" ending if it (the 3 fields in the second file) is also found in the first file.
or
print out the lines from the second file with a ",N" ending if it (the 3 fields in the second file) is not present in the first file.
I wonder if you are using the same name for the output file as your input file. You do not say what the value of the outFile variable is in your pb. If you are trying to read and write from the same file, then the output will indeed be indeterminable.
If you are trying to get all common lines from files file1, file2, file3, file4, then i would use something like:
ProcessBuilder pb = new ProcessBuilder("bash", "-c",
" awk -f awkfile " + " file2 " + file1);
p = pb.start();
p.waitFor();
p.destroy();
// rename the outFile to something different. eg. outfile2.
File of= new File("outFile");
File of2= new File("outFile2");
of.renameTo(of2);
pb = new ProcessBuilder("bash", "-c",
" awk -f awkfile " + " file3 " + "outFile2");
p = pb.start();
p.waitFor();
p.destroy();
// rename the outFile to something different. eg. outfile2. again.
of= new File("outFile");
of2= new File("outFile2");
of.renameTo(of2);
pb = new ProcessBuilder("bash", "-c",
" awk -f awkfile " + " file4 " + "outFile2");
p = pb.start();
p.waitFor();
p.destroy();
Related
I have written a JavaFX program that runs a python script that uses google console search api to get data. It works fine before I deploy it as a standalone program (.exe). After I install the program it runs fine until I click the button that runs the script; it does nothing.
After the button is clicked it succesfully checks if the python is installed or not, after that the problem occurs when it tries the run the script. I have specified the path like this, "./src/com/fortunamaritime/" and I think this might be the problem.
private static final String ANALYTICS_PATH ="./src/com/fortunamaritime/";
inside the method
//set up the command and parameter
String[] cmd = new String[3];
cmd[0] = "python";
cmd[1] = "analytics.py";
cmd[2] = "https://fortunamaritime.com.tr";
String command = cmd[0] + " " + cmd[1] + " " + cmd[2] + " " +
startDate + " " + endDate;
ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/c", "cd " + new
File(ANALYTICS_PATH).getAbsolutePath() + " && " + command);
builder.redirectErrorStream(true);
Process p = builder.start();
I have redirected console output to a .txt file to see what was happening and there's only one line that said "system cannot find the path specified".
I have switched from absolute path to relative path and it produced this error:
The filename, directory name, or volume label syntax is incorrect.
I also printed this line to console
this.getClass().getResource("/com/fortunamaritime/analytics.py")
and the result is:
jar:file:/D:/IdeaProjects/FortunaWebTracker/out/artifacts/FortunaWebTracker/FortunaWebTracker.jar!/com/fortunamaritime/analytics.py
Is it possible to access the inside of the jar file and run the script from there via cmd through stripping parts of this URL?
Copy the script to a (maybe temporary) file and run it from that file.
You can get the script as InputStream with Main.class.getResourceAsStream(String resc) (relative to main) or Main.class.getClassLoader().getResourceAsStream(String resc) (relative to root)
You may use java.nio.file.Files#createTempFile(String,String and delete that file on exit.
You can also copy the script into the user home or relative to the exe (and don't delete it).
For example, you could do this:
File dir=new File("./resc");
if(!dir.exists()) {
dir.mkdirs();
}
File analyticsFile=new File(dir,"analytics.py");
if(!analyticsFile.exists()) {
/*
* alternative:
* this.getClass().getResourceAsStream("com/fortunamaritime/analytics.py")
*/
try(InputStream analyticsIn = this.getClass().getClassLoader().getResourceAsStream("analytics.py")){
Files.copy(analyticsIn, analyticsFile.toPath());
}
}
/*
* alternative: String command=String.join(" ",new String[]{"python",analyticsFile.getAbsolutePath(),"https://fortunamaritime.com.tr"});
*/
String command="python "+analyticsFile.getAbsolutePath()+" https://fortunamaritime.com.tr";
/*
* alternative (without error redirection): Process p=Runtime.getRuntime().exec(command);
*/
ProcessBuilder builder = new ProcessBuilder(command);
builder.redirectErrorStream(true);
Process p=builder.start();
I have solved my problem.
Here's the code sample first, explanation will follow;
String path = new
File(Main.class.getProtectionDomain().getCodeSource().getLocation()
.toURI()).getPath();
path=path.substring(0,path.length()-21);
// set up the command and parameter
String[] cmd = new String[3];
cmd[0] = "python";
cmd[1] = "analytics.py";
cmd[2] = "https://fortunamaritime.com.tr";
String command0="jar xf FortunaWebTracker.jar" +
"com/fortunamaritime/analytics.pycom/fortunamaritime/client_secrets.json" +
" com/fortunamaritime/webmasters.dat";
String command1 = cmd[0] + " " + cmd[1] + " " + cmd[2] + " " + startDate + " " +
endDate;
ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/c", "cd " + path + " && " +
command0+"&&"+"cd "+path+"\\com\\fortunamaritime"+" && "+command1);
builder.redirectErrorStream(true);
Process p = builder.start();
My first mistake was to use absolute path, and the second problem arose when I got the path I wanted via:
File(Main.class.getProtectionDomain().getCodeSource().getLocation()
.toURI()).getPath();
//Jar's name is 21 characters long, minus that and I get the directory path
path=path.substring(0,path.length()-21);
The second problem was unpacking elements inside the jar so I used this command in cmd:
jar xf FortunaWebTracker.jar
com/fortunamaritime/analytics.py
com/fortunamaritime/client_secrets.json
com/fortunamaritime/webmasters.dat
then I could get it to work.
Hey all I am trying to change directories and then run my command with parameters.
final String path = "\\Local// Apps\\IBM\\SDP\\scmtools\\eclipse";
final String command = "scm help";
final String dosCommand = "cmd /c \"" + path + "\"" + command;
final Process process = Runtime.getRuntime().exec(dosCommand);
final InputStream in = process.getInputStream();
int ch;
while((ch = in.read()) != -1) {
System.out.print((char)ch);
}
It runs without errors but outputs nothing. However, this is what shows up after it finishes:
<terminated, exit value: 0>C:\Local Apps\IBM\SDP\jdk\bin\javaw.exe (Jul 22, 2019, 11:21:37 AM)
The expected output should be:
So am I doing this correctly?
AS suggested by Andreas
Process p = null;
ProcessBuilder pb = new ProcessBuilder("scm.exe");
pb.directory(new File("C:/Local Apps/IBM/SDP/scmtools/eclipse"));
p = pb.start();
I get the following error:
Cannot run program "scm.exe" (in directory "C:\Local Apps\IBM\SDP\scmtools\eclipse"): CreateProcess error=2, The system cannot find the file specified
You should use ProcessBuilder instead of Runtime.exec, e.g.
Process proc = new ProcessBuilder("scm.exe", "help")
.directory(new File("C:\\Local Apps\\IBM\\SDP\\scmtools\\eclipse"))
.inheritIO()
.start();
proc.waitFor(); // optional
You can also go through the command interpreter if needed, e.g. if the command is a script (.bat or .cmd file):
Process proc = new ProcessBuilder("cmd", "/c", "scm", "help")
.directory(new File("C:\\Local Apps\\IBM\\SDP\\scmtools\\eclipse"))
.inheritIO()
.start();
proc.waitFor();
The inheritIO() means that you don't need to process the commands output. It will be sent to the console, or wherever Java's own output would go.
is there a limit of commands on a ProcessBuilder?
I have this array of commands:
protected String[] cmd = {
"dism /mount-wim /wimfile:boot.wim /index:2 /mountdir:mount",
"dism /image:mount /add-driver:\"driver\" /recurse",
"dism /unmount-wim /mountdir:mount /commit",
"dism /mount-wim /wimfile:install.wim /index:" + formPanel.getOsIndex() + " /mountdir:mount"
};
And this is my ProcessBuilder:
ProcessBuilder pb = new ProcessBuilder(
"cmd.exe", "/c", cmd[0] + " && " + cmd[1] + " && " + cmd[2] + " && " + cmd[3] + " && " + cmd[1] + " && " + cmd[2]
);
But when I run it it says '&& was unexpected at this time'. When I change the processbuilder to this:
ProcessBuilder pb = new ProcessBuilder(
"cmd.exe", "/c", cmd[0] + " && " + cmd[1] + " && " + cmd[2]
);
Then it works fine.
So my question is basically just if there's a sort of limit of how many commands a single processbuilder can pass?
Here's the whole segment of my SwingWorker method:
#Override
protected Integer doInBackground() {
try {
ProcessBuilder pb = new ProcessBuilder(
"cmd.exe", "/c", cmd[0] + " && " + cmd[1] + " && " + cmd[2] + " && " + cmd[3] + " && " + cmd[1] + " && " + cmd[2]
);
pb.directory(new File(formPanel.workspaceDir.toString()));
pb.redirectErrorStream(true);
Process p = pb.start();
String s;
BufferedReader stdout = new BufferedReader(new InputStreamReader(p.getInputStream()));
while((s = stdout.readLine()) != null && !isCancelled()) {
publish(s);
System.err.println(s);
}
if(!isCancelled()) {
status = p.waitFor();
}
p.getInputStream().close();
p.getOutputStream().close();
p.getErrorStream().close();
p.destroy();
} catch(IOException | InterruptedException ex) {
ex.printStackTrace(System.err);
}
return status;
}
I'm starting to wonder if there's something wrong with the actual code, not the commands.
I think the limit you have to take into account first is the limit of a command itselft (then ProcessBuilder) which is different if you're on Windows or Unix.
For Windows, according to "Command prompt (Cmd. exe) command-line string limitation" documentation :
On computers running Microsoft Windows XP or later, the maximum length
of the string that you can use at the command prompt is 8191
characters. On computers running Microsoft Windows 2000 or Windows NT
4.0, the maximum length of the string that you can use at the command prompt is 2047 characters.
This limitation applies to the command line, individual environment
variables (such as the PATH variable) that are inherited by other
processes, and all environment variable expansions. If you use Command
Prompt to run batch files, this limitation also applies to batch file
processing.
For Unix, I suggest you to refer to the following Stackoverflow question which is resolved now :
Maximum number of Bash arguments != max num cp arguments?
Also, you should take account of limit size of an array in Java which is described into the following Stackoverflow question :
Do Java arrays have a maximum size?
I think the whole command that you sent might be too long for cmd.exe as you use the executable there did you considered using Runtime.exec(); or something like this ?
List<String> commands = new ArrayList<>();
final ProcessBuilder builder = new ProcessBuilder();
commands.add("dism /mount-wim /wimfile:boot.wim /index:2 /mountdir:mount");
And so on, additionaly im not sure if you can have whitespaces here, or you need to add everything as a seperate command.
builder.command(commands);
builder.directory(new File(workingDir));
process = builder.start();
public void VerifyFiles(File dir) throws IOException{
File[] files = dir.listFiles();
for (File file : files) {
//Check if directory
if (file.isDirectory()) {
//Recursively call file list function on the new directory
VerifyFiles(file);
} else {
try {
ProcessBuilder builder = new ProcessBuilder(
"cmd.exe", "/c", "cd \" C:\\Users\\e843778\\Documents\\NetBeansProjects\\EncryptedFiles\" && C:\\Program Files\\PGP Corporation\\PGP Desktop");
builder.redirectErrorStream(true);
Process p = builder.start();
Runtime rt = Runtime.getRuntime();
String query2 = "cmd /c pgpnetshare -v " + "\"" + file + "\"";
Process proc = rt.exec(query2);
proc.waitFor();
System.out.println("Executing for: " + file);
BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line = "";
String s1 ="";
while ((line = in.readLine()) != null)
{
System.out.println(line);
if(line.contains("All files and folders are encrypted"))
s1+=line;
}
System.out.println(s1);
}
I have to run a pgpnetshare command for all the files in a given directory using command prompt. For that, first i need to change my current directory to other directory. But i was not able to change the directory with the below code. I have checked all the previous answered questions in Stackoverflow.com. But none of them helped me.Please verify the code and please let me know if it needs any corrections. Thanks in advance!!.
That should work:
Process process=Runtime.getRuntime().exec(query2,
null, new File("directory path"));
From the documentation:
Process exec(String[] cmdarray, String[] envp, File dir)
Executes the specified command and arguments in a separate process with the specified environment and working directory.
You can always create a .bat file and execute that instead.
you should use using file.getAbsolutePath()
like
String query2 = "cmd /c pgpnetshare -v " + "\"" + file.getAbsolutePath() + "\"";
This is a part of my code to copy files from local to a remote machine
try {
Process cpyFileLocal = Runtime.getRuntime().exec("scp " + rFile+"*.csv" + " root#" + host + ":" + lFile);
InputStream stderr = cpyFileLocal.getErrorStream();
InputStreamReader isr = new InputStreamReader(stderr);
BufferedReader br = new BufferedReader(isr);
String line = null;
System.out.println("<ERROR>");
while ((line = br.readLine()) != null) {
System.out.println(line);
}
System.out.println("</ERROR>");
int exitVal = cpyFileLocal.waitFor();
System.out.println("Process exitValue: " + exitVal);
System.out.println("...." + cpyFileLocal.exitValue());
System.out.println("SCP COMMAND "+"scp "+rFile+"*.csv" +" root#"+host+":"+lFile);
System.out.println("Sending complete...");
} catch (Exception ex) {
ex.printStackTrace();
}
the output is...
<ERROR>
/opt/jrms/rmsweb/transfer/cn00/outgoing/*.csv: No such file or directory
</ERROR>
Process exitValue: 1
....1
SCP COMMAND scp /opt/jrms/rmsweb/transfer/cn00/outgoing/*.csv root#10.50.1.29:/opt/jrms/transfer/incoming/
but when I run the command in terminal on the local machine, it works fine
and when I run ll the files are there
-rwxr-xr-x 1 freddie freddie 140 Apr 22 09:13 gc00cn00150420092629.csv*
-rwxr-xr-x 1 freddie freddie 105 Apr 22 09:13 gc00cn00150420122656.csv*
Any help please
If you are using java 7 and above you should use ProcessBuilder instead of Runtime.getRuntime().exec() and in the ProcessBuilder you can specipied the execution directory:
ProcessBuilder pb = new ProcessBuilder("scp", rFile+"*.csv", "root#" + host + ":" + lFile);
Map<String, String> env = pb.environment();
env.put("VAR1", "myValue");
env.remove("OTHERVAR");
env.put("VAR2", env.get("VAR1") + "suffix");
pb.directory("directory where the csv files located");
Process p = pb.start();
When you run command with in bash with wildcards like * in it, bash will expand that command and in your case, replaces *.csv with list of files terminating with .csv, but in your java program, this won't happen.
According to this answer, you can do following:
Use file.listFiles() to get the list of files
Use file.getName().contains(string) to filter them if needed
Iterate over the array and perform scp or do it with whole list
or with thanks to #James Anderson comment add sh before scp in your command.
According to this, you should try:
Process cpyFileLocal = Runtime.getRuntime().exec(new String[] {"/bin/sh","-c", "scp " + rFile+"*.csv" + " root#" + host + ":" + lFile});
I tested with /bin/sh and /bin/bash, both copied the files over successfully