Shell script with jar file at the end - java

I download an archive file. In the archive there will be a file that has a .sh. extension. When I opened that file with VI I found the below code in the beginning of the file:
#!/bin/sh
MYSELF=`which "$0" 2>/dev/null`
[ $? -gt 0 -a -f "$0" ] && MYSELF="./$0"
java=java
if test -n "$JAVA_HOME"; then
java="$JAVA_HOME/bin/java"
fi
exec "$java" $java_args -jar $MYSELF "$#"
exit 1
I can run the jar by doing java -jar file or `./file'.
Can someone explain me what is going on? How can you create such file?

Try by yourself the following commands. Start creating a normal jar file with any content, or use someone you have. I will name it "myjar.jar"
Next, create a file "hello.sh" with content:
#!/bin/bash
exec echo hello
now, add this file at start of a new jar file:
cat hello.sh myjar.jar > mytrick.jar
chmod 700 mytrick.jar
And finally, the interesting part, type:
./mytrick.jar
jar -tf mytrick.jar
unzip mytrick.jar
in other words, usually jar/unzip skips any content until their own header. Moreover, a shell script "ends" in a line who call "exec" (because shell interpreter is replace at this point by the command in the exec line).
However, this trick is based in a behaviour of jar/unzip probably out of standards. Note, by example, that this statement fails (has no effects):
jar -xf mytrick.jar

If the file after extracting the tar file is start-superbeam.sh try doing chmod +x start-superbeam.sh && ./start-superbeam.sh or /bin/sh ./start-superbeam.sh.
If the program has arguments, supply them after at the end. It will run java on that the superbeam.sh which as a jar file at the end.
If you need special java parameters set such as for memory size, you would set them in the environment variable java_args.
As for what's going on this is a shell script with a jar file at the end of it after the exit. To quote from ReallyExecutable Jars:
There has long been a hack known in some circles, but not widely
known, to make jars really executable, in the chmod +x sense. The hack
takes advantage of the fact that jar files are zip files, and zip
files allow arbitrary cruft to be prepended to the zip file itself
(this is how self-extracting zip files work).
As for how to create, see the accepted answer or the link.

Related

can't make a shell script to make a jar file

I try to make a simple shell script to make a jar file. The jar command combined with -C does not work with wildcards. Therefor I use a wildcard to find the files I want. Write them to a file, and loop over them.
It looks something like this:
the_classes=''
cd "$bin_folder"
tmp_dir=$(mktemp -d -t java_sucks)
find "imui/core/" -type f -name "IMUI_Widget_Agent*.class" >"$tmp_dir/classes.txt"
while IFS="" read -r p || [ -n "$p" ]
do
the_classes="${the_classes} -C '$bin_folder' '$p'"
done < "$tmp_dir/classes.txt"
Using the above I complete the command:
cmd='jar cfm build/IMUI_Widget_Agent.jar'
cmd="${cmd} \"$bin_folder/imui/core/IMUI_Widget_Agent_MANIFEST.MF\" $the_classes"
printf "\n\n\ncmd\n\n\n"
echo $cmd
Now if I copy and paste this command to execute it works!
But I want to avoid the manual labour of doing the copy and paste by hand every time.
Now I have:
eval "$("$cmd")"
But I get an error File name too long. No matter what I try, every fix I do creates a new problem. I have been working 6 hours now to make this script.
What would be a good step forward?
Since you cd "$bin_folder" you don't actually need -C "$bin_folder":
#!/bin/bash
shopt -s globstar
cd "$bin_folder"
jar cfm build/IMUI_Widget_Agent.jar \
imui/core/IMUI_Widget_Agent_MANIFEST.MF \
imui/core/**/IMUI_Widget_Agent*.class
However, if you still want to add them as part of a larger script, you can easily and robustly build your command in an array:
#!/bin/bash
shopt -s globstar
cmd=(jar cfm build/IMUI_Widget_Agent.jar imui/core/IMUI_Widget_Agent_MANIFEST.MF)
cd "$bin_folder"
for file in imui/core/**/IMUI_Widget_Agent*.class
do
cmd+=(-C "$bin_folder" "$file")
done
echo "About to execute: "
printf "%q " "${cmd[#]}"
echo
"${cmd[#]}"
Alternatively, you can simply do eval "$cmd" with your code, which is equivalent to echo and copy-pasting. However, be aware that this is fragile and error prone because it requires careful escaping of the filenames which you're not currently doing.

creating jar using -C flag

I am trying to create a Jar file from command line using -C flag, but every time it returns a help screen.
I am giving following command.
user#ubuntu:~/CDH/JAVA_WORKSPACE/JAVA-SETUP$ jar cvfm ./build/jar/Setup.jar MANIFEST -C build/classes/com/demo/Setup.class
If I remove -C command then it archives fine.
But if -C flag is there, then it always returns jar help page.
Am I doing something wrong here?
Your command line option is:
-C build/classes/com/demo/Setup.class
The jar tools wants the directory name to follow the -C and then the file. You need two words to follow "-C" like this:
-C build/classes/com/demo Setup.class

Ubuntu script to compile multiple java files?

I understand the command would be javac file_name.java but how would I put together a shell script which could compile several java files?
I was also thinking about copying the files, which I presume I just use cp and absolute file path referencing.
Create a .sh file and add the following contents. Make the file as executable and run it.
(Specify the complete path along with the file name)
#! /bin/sh
javac sample.java
Try this script: compile_java_files.sh
#!/bin/sh
typeset -r JAVA_FILES_DIR=$(cd full_path_to_java_files 2>/dev/null ; pwd) # JAVA FILES DIRECTORY
LOG_DIR="/tmp/java_compilation/logs" # Create this dir or use another one
for java_file in `ls $JAVA_FILES_DIR`;
do
javac $java_file
return_status=`echo $?`
if [ $return_status -ne 0 ]
then
echo "Failed to compile $java_file" >> $LOG_DIR/$java_file.ERR
exit 1
fi
done
Then run your script(don't forget to specify the path to the directory that contain java files):
chmod +x compile_java_files.sh
./compile_java_files.sh

Remove file from *.jar, using script

I have next package structure
webService.ear -- dependency.jar -- some.class
Can I remove some.class from .ear using cmd script and bash script?
Solution:
I wrote cmd script for this:
call unzip target\webService.ear -d tmp
call zip -d target\tmp\dependency.jar \com\mypackage1\MyClass1.class
call zip -d target\tmp\dependency.jar \com\mypackage2\MyClass2.class
call jar cvfM target\webService.ear -C tmp .
May be, this will be helpful for someone
There is no option to the jar command to remove entries.
However, the jar format is processable with zip tools, so you should be able to use a command-line zip (GNU zip, for instance) to remove members.

Using Bash to automate creation of test outputs

I have a java program that I am trying to generate 3 outputs for, and then rename them depending on what the input file was originally called.
The problem is that only the input file is being moved. I think this might be an issue regarding relative file commands.
Here is my script. (Also, I'm open to suggestions on making this script better looking. I'm a bash newbie.)
#!/bin/bash
########################################################
#This script compiles Main, then attempts to run each #
#test case. After running a test case, it renames the #
#testcase and moves it to a new directory. #
########################################################
#echo `pwd` <---- This was used for testing. pwd is correct
#Gets contents of "tests" directory, stores them into the array
#without the file extension.
list=(`ls tests| sed 's/\.txt$//g'`)
#Compiles Main.java
cd ./src
javac Main.java
cd '../'
mv -f src/*.class bin #*/ (formatting fix)
#Runs Main for each test case, then renames and moves the test cases.
for filename in ${list[#]}
do
echo 1 > input.txt
echo tests/$filename.txt >> input.txt
cd ./bin # Why do I need to cd to make this work?
java bin/Main < input.txt
cd ../
mv -f input.txt "scriptout/'$filename'_input.txt"
mv -f "tests/output.txt" "scriptout/'$filename'_output.txt"
mv -f "tests/listing.txt" "scriptout/'$filename'_listing.txt"
mv -f "src/intermediate.txt" "scriptout/'$filename'_intermediate.txt"
done
You have single quotes around your variable names. Since they're inside double quotes, the variables will be expanded but the single quotes will be included in the filenames. Try this:
mv -f input.txt "scriptout/${filename}_input.txt"
The braces will protect the variable name from being combined with following characters.
You can do this:
list=(tests/*)
list=("${list[#]##*/}") # strip dirname
list=("${list[#]%.*}") # strip extension
These will prevent errors if there are spaces in any of the filenames.
Use indenting to make your script more readable:
for ...
do
command
done
In general, you should avoid using relative directories and use a variable as a base for an absolute directory:
basedir=/path/to/base
do_something $basedir/test/filename
mv $basedir/subdir1/file1 $basedir/subdir2
This can also make it so you don't have to use cd as much.
Are you getting any error messages? Try using set -x to turn on tracing and set +x to turn it off. Place those before and after particular sections of code so you can see what's happening in that area.

Categories

Resources