Java equivalent of perror in C - java

I hope to execute a bash script and obtain normal output or error message. I know for C we have erron or perror to get the number of exit code and the corresponding message. Whether or not there is an equivalent for Java. If not, how could we achieve the same task as in C?

If you start your process like this:
Process p = Runtime.getRuntime().exec("<command>");
The the error code is return like this:
int error_code = p.waitFor();

You're confusing things.
The exit status from a process, out to bash, Java or whatever environment started it, is not the same thing as the values of errno, that can be printed by perror(). The latter are errors for individual system calls, which are clearly at a much lower level.
The exit status of a process can be whatever, there's no standard for that since it's usually just pass/fail, the detailed level is typically coverered by the program itself.
See, for instance, the exit status of GNU grep:
Normally, the exit status is 0 if selected lines are found and 1 otherwise. But the exit status is 2 if an error occurred [...].
That's very high-level, and doesn't tell you what error occured inside grep, just that overall, it failed.

Related

Expect Programming: How to expect exactly what is prompted?

I am asking this question particularly for an Expect implementation in Java. However, I would like to know general suggestions as well.
In Expect programming, is it possible to expect exactly what is prompted after spawning a new process?
For example, instead of expecting some pattern or a fixed string, isn't it better to just expect what is prompted. I feel this should be really helpful at times(especially when there's no conditional sending).
Consider the sample java code here that uses JSch and Expect4j java libraries to do ssh and execute list of commands(ls,pwd,mkdir testdir) on the remote machine.
My question here is why is it necessary to specify a pattern for the prompt? Is it not possible it to get the exact prompt from Channel itself and expect it?
I've programmed in "expect" and in "java".
I think you misunderstand what "expect" basically does. It doesn't look for exact items prompted after spawning a new process.
An expect program basically consists of:
Something that reads the terminal
A set of patterns (typically regular expressions), coupled to a blocks of code.
So, when a new process is spawned, there's a loop that looks something like this
while (terminal.hasMoreText()) {
buffered_text += terminal.readInput();
for (Pattern pattern : patterns) {
if (pattern.matches(buffered_text)) {
String match = pattern.getMatch(buffered_text);
bufferedText.removeAllTextBefore(match);
bufferedText.removeText(match);
pattern.executeBlock();
}
}
}
Of course, this is a massive generalization. But it is close enough to illustrate that expect itself doesn't "exactly expect" anything after launching a process. The program provided to the expect interpreter (which primarily consists of patterns and blocks of code to execute when the patterns match) contains the items which the interpreter's loop will use to match the process's output.
This is why you see some pretty odd expect scripts. For example, nearly everyone "expects" "ogin:" instead of "Login:" because there's little consistency on whether the login prompt is upper or lower case.
You don't have to expect anything. You're free to just send commands immediately and indiscriminately.
It's considered good practice to only reply to specific prompts so that you don't accidentally ruin something by saying the wrong thing at the wrong time, but you're entirely free to ignore this.
The main consideration is that while your normal flow might be:
$ create-backup
$ mkdir latest
$ mv backup.tar.gz latest
With no expectations and just blindly writing input, you can end up with this:
$ create-backup
Disk full, cleanup started...
Largest file: precious-family-memories.tar (510MB)
[R]emove, [S]ave, [A]bort
Invalid input: m
Invalid input: k
Invalid input: d
Invalid input: i
Removing file...
$ latest
latest: command not found
$ mv backup.tar.gz latest
whereas a program that expects $ before continuing would just wait and eventually realize that things are not going according to plan.
A few commands are sensitive to timing (e.g. telnet), but other than that you can send commands whenever you want, with or without waiting for anything at all.

Calling JAR from Python

I have the code below:
from subprocess import Popen, PIPE, STDOUT
p = Popen(['java', '-jar', 'action.jar'], stdin=PIPE, stdout=PIPE, stderr=STDOUT)
stdout1, stderr1 = p.communicate(input=sample_input1)
print "Result is", stdout1
p = Popen(['java', '-jar', 'action.jar'], stdin=PIPE, stdout=PIPE, stderr=STDOUT)
stdout2, stderr2 = p.communicate(input=sample_input2)
print "Result is", stdout2
Loading the jar takes a lot of time and is very inefficient. Is there any way to avoid reloading it the second time, in the second line p = Popen(...), i.e. just loading it once in the beginning and continue using that instance? I tried to remove the second line unsuccessfully, Python complains:
"ValueError: I/O operation on closed file".
Is there any solution to this? Thanks!
communicate() waits for the process to terminate, so that explains the error you're getting -- the second time you call it, the process isn't running any more.
It really depends on how that JAR was written, and the kind of input it expects. If it supports executing its action more than once based on input, and if you can reformat your input that way, then it would work. If the JAR does its thing once and terminates, there's not much you can do.
If you don't mind writing a bit of Java, you can add a wrapper around the classes in action.jar that takes both your sample inputs in turn and passes them to the code in the jar.
You can save on the cost of starting up the Java Virtual Machine, using a tool like Nailgun.

JVM: how are exit codes of the java executable defined?

I'm looking for a definition of possible exit codes of the java executable:
(How) can I tell whether the exit code is of the executed Java process or of the VM itself?
Example: On Windows, java -badoption returns 1; java Main with Main being a valid class may return 1 as well.
Are there any VM options I could use to make exit codes more meaningful? E.g. to distinguish between both types of exit codes?
If I know that the exit code is not from my Java process (which only returns 0), what do non-zero exit codes mean?
On Windows, I'm frequently seeing -1 and 1. As these are reported through an automated bug-reporting facility, I can't see any error messages. I only have the exit code and need to interpret it.
Are the exit codes platform-dependent?
Meaning of Exit Codes (in general)
ISO/IEC 9899 (Programming Languages: C), ISO/IEC 9945 (IEEE 1003, POSIX)
There is nothing which is specifically defined for Java / JVM. The meaning of these exit codes is defined by ISO/IEC 9899 (Programming Languages: C, for example 7.20.4.3 The exit function of ISO/IEC 9899:TC3), ISO/IEC 9945 (IEEE 1003, POSIX) and similar specifications, and it's always like this:
0 means success
Any other value means failure
This is used by shell environments (sh, bash, cmd.exe, make etc. etc.) to determine whether a program exited successfully (0) or there was an error (not 0).
It is strongly recommended to use only 0 for success. Programs which use values other than 0 for success cause headache to the authors of shell scripts, Makefiles and alike.
It's up to the individual program to define additional semantics of different failure values. However, I think -1 is not such a good idea. The best thing would be to use EXIT_SUCCESS and EXIT_FAILURE, however, these definitions from <stdlib.h> have no corresponding counterparts in Java. ISO/IEC 9899:2011 does not describe how EXIT_FAILURE and EXIT_SUCCESS should be defined. However, it defines 0 as having the same semantics as EXIT_SUCCESS, and I do not know of any system which does something else than the following, which therefore is the best thing a Java programmer can assume:
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1
So, I'd use 0 for success, 1 for failure, and values distinct from 1 if it is important to differentiate between different types of failure. A good example is the grep command. From its man page (GNU grep):
EXIT STATUS
The exit status is 0 if selected lines are found, and 1 if not found. If an error occurred the exit status is 2. (Note: POSIX error handling code should check for '2' or greater.)
I'd not use -1 because it sets all bits, and depending on the environment, -1 might actually accidentally generate additonal bogus information, like claiming that signals were raised and alike. Actually, to be portable, the exit code should be within the range [0..127], unless you really really really know what you're doing.
For example, on most POSIX systems, the exit code will be truncated to 8 bits, and the semantics of an exit code above 127 is that the exit was caused by a signal.
BSD
BSD has tried to supply a few more exit codes, which are available in /usr/include/sysexits.h (man page). They are like this:
64: command line usage error
65: data format error
66: cannot open input
67: addressee unknown
68: host name unknown
69: service unavailable
70: internal software error
71: system error (i.e. can't fork)
72: critical OS file missing
73: can't create (user) output file
74: input/output error
75: temp failure; user is invited to retry
76: remote error in protocol
77: permission denied
78: configuration error
In the absence of any other meaningful standard, I think the best thing we can do is use them.
Interpretation of JVM-generated exit values
JVM on POSIX
On UNIX, you can obtain the signal by masking out the lower 7 bits (subtract 128) from the exit value, which in most shells can be queried using $?.
SIGTERM -> VM: 143 SIGTERM
SIGSEGV -> VM: 134 SIGABRT (because the VM handles SIGSEGV to write the hs_err file and then calls abort()).
Comparison to "normal" programs:
SIGSEGV -> prog: 139 SIGSEGV
This behavior is not explicitly specified for the JVM, it is just the normal expected behavior of programs in a POSIX environment. Even the SIGABRT instead of SIGSEGV is more or less expected, given that the JVM wants to handle SIGSEGV on its own, writing a more specific crash dump than a normal core file.
JVM on Windows
TODO

Exit value from java.lang.Process#waitFor()

The method waitFor() returns an integer value which is the return code. The value 0 indicates normal termination. But what are the meanings of other return codes? I am getting an exit value 11. What does that mean? And where all the exit value codes are documented?
These values are arbitrary and up to the specific program to define. You should refer to documentation or source code of the program that is outputting this exit code.
The program return value depends on program. There is no standard for return values apart from zero meaning OK.
You have to contact author of the program or consult documentation.
Every application defines it's own exit codes. E.g. you have to look up the documentation of the application that you started using java.lang.Process. The only common thing they all have is that any other value than 0 is an error.
In the unix world on the other hand there are certain conventions, that many main stream utilities follow, but there are no guarantees.
Any value other than non-zero value indicates Abnormal termination. There is no particular rule as to what values indicate what conditions. Read the documentation for the process that you are calling.
0 --> Normal termination
!=0 --> Abnormal Termination
I have seen conversions happen of the nature that can convert intended negative error codes to convert as follows -
Error code –> -2001 -> Signed Decimal to Binary conversion -> 111111111111100000101111 -> Here 00101111 last 8 bit is picked up and converted back to Decimal – 47 !!

running external program in java

If I am running external program(batch file) from java then, What I need to do:
if (process.exitValue() == 0) {//means executed successfully ???
Can't the return value be something else and batch executed successfully.
Is that the only way to check??
I'm a bit confused by your wording, but by convention, [exitValue()](http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Process.html#exitValue()) returns 0 upon a successful execution. This is, as far as I know, the only way to check.
EDIT:
I suppose you could use [getErrorStream()](http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Process.html#getErrorStream()) - I assume it'll be blank if there are no errors in the process...
Pick one from here
You could read the output stream ( or the error stream ) and interpret it
The exit code of the batch process will be defined by that process but generally an exit code of 0 is defined as successful and a non zero value indicates that something went wrong. In your batch file you can set the return code by calling:
EXIT /B %ERROR_CODE%
%ERROR_CODE% is the number that will be returned as the exit code.
On Linux, your program can return any status you want. By convention 0 means success.
For example, if you execute a shell script, the return status will be the return status of the last command executed in your script.
In many programs 0 is is success, negative numbers are errors and positive numbers are warnings. Of course this is just a convention and it all depends on what convention was followed. In most programming languages you can define an exit code for a program and that is what is picked up.
In Java System.exit(n)
In C main is defined as int main(int argc, char* argv[]) and the return from main is the return from the program.

Categories