Shell script call command line application - java

I have a Java program which I'd like to call inside a linux shell script. The Java program takes a user input from the command line.
I read somewhere that I can use echo to mimic user input as follows:
java myProgram
echo 1000
echo
However this doesn't work for me, the program is still waiting for the user input. Is there something I'm doing wrong? I can't imagine this is a difficult task.

You can use echo, but in a pipeline.
echo 1000 | java myProgram
If you want to send a file, you can use cat:
cat file.txt | java myProgram

Why not just pass in the value as an argument
java myProgram 1000

I think you should find the process id of your java process and then write to its /proc directory.
Say the id of the Java process is 4321, then output to
/proc/4321/fd/0

Related

Java program exiting abnormally in Unix script

I have inherited an extract job program which is a Java program that connects to a database and produces a file from a Unix shell script. At times, I can see the Java program is terminated abnormally and starts executing the remainder of the Unix script by zipping the extract. This is causing a lot of reconciliation issues.
The code is structured as follows:
INSTANCE_NAME=1
PROCESS_NAME=benefitpayment
cd utils
FAIL=0
sh benefitpaymentprocesswithdates.sh $PROCESS_NAME $INSTANCE_NUMBER $1 $2
for job in $dPidLst
do
wait $job || let "FAIL+=1"
done
echo $FAIL
if [ "$FAIL" == "0" ];
then
echo "About to secure file..."
zip -P <password> export.txt secure.zip
...
...
else
echo "FAIL! ($FAIL)"
fi
The $dPidLst is set in the inner Unix script(benefitpaymentprocesswithdates.sh) to call a Java wrapper and is set as:
java program called to generate a file
dPidLst=`jobs -p`
In either of the successful or failure cases, this "dPidLst" is always NULL.
The dPidLst is not exported in the inner script. The script was designed in that manner.
Should dPidLst be exported back to this main program? How do I make this script fool proof in the sense, if the Java program terminates abnormally, it should not execute the remainder of the Shell script? of zipping the file.
The value of dPidLst that you set in benefitpaymentprocesswithdates.sh will not be visible in your calling script.
When you run the benefitpaymentprocesswithdates script, it runs in its own process, and that process gets its own variables.
To pass the process id list back to your script, you need to use a mechanism other than shell variables or environment variables
e.g. at the end of benefitpaymentprocesswithdates.sh, do
echo $dPidList
And when you call it instead of
sh benefitpaymentprocesswithdates.sh
do
dPidList=$(sh benefitpaymentprocesswithdates.sh)
If all it is doing is calling jobs -p, there's no reason to have it in a separate script, of course.

Accessing a coprocess outside of the bash script that creates it

So I'm using the coproc command in a script to run a java program and to feed input to it, as follows:
#!/bin/bash
echo Script started.
coproc java -jar MultiThreadedFileProcessor.jar
echo start >&${COPROC[1]}
echo Script terminated.
I'd like to be able to write another script which can pass more input to this program (e.g. a command which will tell the program to run termination routines).
Is there any way that I can access the stdin of the coprocess from another script? My current attempt at a termination script is as follows:
#!/bin/bash
echo Script started.
echo terminate >&${COPROC[1]}
echo close >&${COPROC[1]}
echo Script terminated.
This gives me an ambiguous redirect error however, I'm guessing because COPROC[1] is only defined in the script that creates the coproc.
How else, if at all, can I write a script that will accomplish my goal of passing a line to the java program?
COPROC is an array local to the first script - you will never be able to access that from another script.
On Linux, you could access /proc/$pid/fd/$n with $pid being the pid of the first script and $n being the fd stored in ${COPROC[1]}. Both have to be communicated somewhere (a pid file and likewise an "fd file"), but in that case you might better be off creating a named pipe (mkfifo) and use that instead of creating a coproc in the first place. Something like this (not tested) codes:
Script 1:
mkfifo fifoname
exec 5>fifoname
java <fifoname &
echo close >&5
Script 2:
exec 5>fifoname
echo terminate >&5
echo close >&5
What is the close command supposed to do? The java program will see
close
terminate
close
Does that make sense to the java program?

How to know what class is running in Unix?

I have a class that is being executed through a script in unix (Solaris 9). Inside of the script the class is being run like this:
java -cp $CLASSPATH myPackage.component.MyMainClass $PROPERTIES_PATH/myMainClassProperties.properties
That shell needs to be monitored in order to see whether it works correctly or it fails, and it also is going to be run parallel with a different parameter file. So, my questions are:
How can I know what class is being executed if I use top. Is that possible?**
Is there a way to uniquely identify the class so it doesn't crash when running parallel?
Will it always be shown as myPackage.component.MyMainClass in the table of processes?
When I say parallely, I refer to something like:
java -cp $CLASSPATH myPackage.component.MyMainClass $PROPERTIES_PATH/myMainClassProperties.properties
and in another window/session/job
java -cp $CLASSPATH myPackage.component.MyMainClass $PROPERTIES_PATH/mySomeOtherProperties.properties
**When I say so, is because top shows something like this:
PID USERNAME THR PRI NICE SIZE RES STATE TIME CPU COMMAND
8545 batman 47 4 10 190M 112M sleep 0:04:00 0.07% java
9022 joker 91 4 10 286M 211M sleep 0:01:00 0.09% java
You can let top tell you the complete command, that will include any arguments you pass to the VM.
Also ps will give you the complete command as well (with the matching arguments).
In my debian I can switch the displayed command with the c toggle (start top and hit c until it shows the whole command)
for ps I use the arguments -ef (but -f) alone should do for that situation.
You may want to read the output of man ps and man top
It was possible to get the info using ptree | grep java or ptree | grep MyMainClass
It lists a tree of the processes that are being executed as well as the command that is being runned in there for example:
13456 ksh
123476 java -cp java -cp /classpath/fullpath myPackage.component.MyMainClass /full/properties/path/myMainClassProperties.properties
The first line is a shell script, and inside it (next line) calls the java jar. This works for Solaris 9.
Thanks #Angelo-Neuschitzer for the heads up.

Getting execution time of a user process in Linux

How can I get the details of a process in Linux. I want the total execution time, memory map of a process. In this context the process will be a simple Java program. I only know the file name, not the process id. Any help will be appreciated
If the process is not already running, then time will print total execution time. There is both a bash builtin and a standalone command of that name, with somewhat different behaviour. But as your mention of memory maps suggests an already running process, I'll concentrate on that.
You can find a process by executable using ps -C java. If you want to know what that java binary is running, you can do things like this to find the pid:
ps -C java -o pid,time,cmd | awk '/foo\.jar/{print $1,$2}' | \
while read pid time; do
echo "PID $pid, TIME $time"
cat /proc/$pid/maps
echo ""
done
If you don't like the output format, replace the loop with something else.
Here is what this does:
-C java: Find java processes
-o pid,time,cmd: Print these fields
/foo\.jar/: Only take lines containing that regular expression
print $1,$2: Print pid and time columns
/proc/$pid/maps: Access proc file conatining the memory map
If you know only the program name, and not the process id, you first have to find out which processes (they can be many of them) are running that program.
You could use e.g. some of the below commands to find out, assuming the program name is progname:
ps auxw | grep progname
pidof progname
pgrep progname
(notice that if you are using a JVM to run some Java program the progname is always java which does not help much)
You might also use top or htop
Once you got an interesting pid, e.g. 1234, you could get more information about that process with e.g.:
ps -lw 1234
cat /proc/1234/status
cat /proc/1234/stat
cat /proc/1234/stack
cat /proc/1234/maps
cat /proc/1234/smaps
Look also in other files and directories of /proc/1234/ such as /proc/1234/fd/ and others.
The Linux kernel is telling information about processes thru /proc so you should learn more about it.
I'm planning to use some memory profiling tools such as valgrid.

Input value in Java program from shell script

I wanted to know if there is a way, from a sh script, to input value in a Java program. For example I have a program.jar. I do java -jar program.jar and it outputs:
Enter your name:
Would it be possible to write an sh script like that:
java -jar program
echo name
where name is gonna be the input for the program?
To echo data into your java program from the shell do something like this:
java -jar program<< EOF
<your-data>
EOF
In addition to #tcb 's suggestion, you can also use a standard input redirection pipe < in order to specify a file that will be the input of the program:
input.txt
name
And in the sh:
java -jar program < input.txt
Use pipes:
echo name | java -jar program
If you mean interactive input , expect is always one of the answers.

Categories

Resources