问题
Supposedly jjs is the Java 8 version of nashorn, ready for shell-scripting. However when I write a file with execute permission as:
#!/usr/bin/jjs
arguments.forEach(function(v,i,a){print(v);});
Running it produces some not so ideal shell-scripting behavior:
$./file.js
$./file.js one two
java.io.IOException: one is not a file
$./file.js -- one two
one
two
$./file.js file.js -- one two # what were they thinking
one
two
one
two
$
So, I don't ever want this script I'm writing to allow for the arbitrary interpretation of a file after it runs, maybe I should use --
in the shebang like:
#!/usr/bin/jjs --
arguments.forEach(function(v,i,a){print(v);});
But this gets less useful:
$./file.js
jjs>^D
$./file.js one two
jjs>^D
$./file.js -- one two
jjs>
Yes, being dropped into a REPL prompt is exactly what I thought should not happen.
How am I supposed to make it possible to execute a script with arguments that are passed directly and not interpreted by jjs itself such that I can get behavior like:
$./file.js one two
one
two
$
回答1:
The example works as expected in the JDK 9 version of Nashorn. I'll take care of backporting the required patches so they can appear in one of the upcoming 8u releases.
Update: the required changes are backported to the 8u stream, but it is not clear at what point there will be a release. The early access releases of JDK 9 available from https://jdk9.java.net/download/ have the shebang feature, and also other extensions, such as piping support for the $EXEC builtin.
回答2:
While waiting for the changes to be backported, I wrote a script to overcome the problem. My jvm is installed in the folder /usr/lib/jvm/jdk1.8.0_101, so I created the following script:
/usr/lib/jvm/jdk1.8.0_101/bin/jjs/bin/jjs-cp.sh:
#!/bin/bash
CP=
if [[ $1 = "--lib="* ]]; then
LIB_FOLDERS=${1:6}
shift
LIB_FOLDERS=$(echo $LIB_FOLDERS | tr ":" "\n")
for FOLDER in $LIB_FOLDERS; do
if [[ $FOLDER = "!"* ]]; then
CP="$CP:${FOLDER:1}"
else
if [ -d $FOLDER ]; then
JARS=$(find "$FOLDER" -type l -o -type f -name "*.jar")
for JAR in $JARS; do
CP="$CP:$JAR"
done
fi
fi
done
if [ -n $CP ]; then
CP=${CP:1}
fi
fi
SCRIPT_FILE="$1"
shift
if [ -n $CP ]; then
/usr/lib/jvm/jdk1.8.0_101/bin/jjs -cp "$CP" $SCRIPT_FILE -- $@
else
/usr/lib/jvm/jdk1.8.0_101/bin/jjs $SCRIPT_FILE -- $@
fi
Then, in my test.js script I can write:
#!/usr/lib/jvm/jdk1.8.0_101/bin/jjs-cp.sh --lib=!.:<full path to classpath folder 1>:<full path to classpath folder 2>
var console = {
log: function(msg) {
java.lang.System.out.println(msg);
}
};
console.log('Hello, world!');
arguments.forEach(console.log);
var MyClass = Java.type('com.acme.MyClass'); // load a class from a jar in the classpath
console.log(MyClass.class); // prints "class com.acme.MyClass"
And I can execute my script with this command line:
~$ ./test.js one two
来源:https://stackoverflow.com/questions/37096520/writing-a-jjs-shebanged-script-that-accepts-just-arguments