2016-02-25 14 views
5

Um klar zu sein, durch ausführbare ich nicht wörtliche Bytes für den Prozessor bereit. Zum Beispiel wird ein Bash-Skript, das interpretiert und nicht ausführbar ist, ausführbar, wenn oben ein Shebang hinzugefügt wird, der angibt, dass das Skript von /bin/bash oder /bin/sh oder einem anderen Programm ausgeführt werden soll, das es interpretiert.Ist es möglich, jede Sprache ausführbar zu machen?

Ich frage mich, ob es möglich ist, das gleiche mit anderen Skriptsprachen zu tun? Und wenn ja, ist es wirklich so einfach wie das Hinzufügen eines Shebang, der das interpretierende Programm referenziert (d. H. #!/usr/bin/python für ein Python-Skript oder #!/usr/local/bin/node für JavaScript)?

Ich fragte mich auch, ob es möglich ist, mit Java zu tun, das technisch gesehen keine Skriptsprache ist, aber definitiv nicht ausführbar ist. Es scheint so, als wäre Java schwierig, da der Benutzer nicht die Möglichkeit hat, der kompilierten Datei einen Shebang hinzuzufügen.

Antwort

3

Sie können natürlich auch eine Datei erstellen:

#!/any/executable/program args 
...input goes here... 

Sie es mit Java tun könnten

#!/path/bin/java mainclass 
...this is System.in... 
+0

Ahh so mit Java die .class-Dateien müssen an anderer Stelle gespeichert werden und referenziert durch die ausführbare Datei noch? –

+0

Ja, das stimmt, und Sie müssen sicherstellen, dass der Klassenpfad korrekt ist, bevor Sie das ausführen. Es ist also praktischer, in der Regel ein sh-Skript zu verwenden. –

+0

Das ist interessant. Ich wusste nicht, dass du nach dem Shebang auch Argumente vermitteln kannst.Ich schätze, das ist es, was ich bekomme, wenn ich mich selbst lehre, haha. Antwort genehmigt! –

2

Nein, es ist nicht möglich, ein sie Knall auf jedem Skript zu setzen und es wird ausgeführt. Bash beruht auf der Tatsache, dass die Datei mit dem Shebang Zeilen ignoriert, die mit # beginnen. Daher funktioniert jede Skriptsprache oder jeder Byte-Code, der die erste Zeile mit dem Shebang ignorieren kann.

Wenn Ihre Sprache # nicht als Kommentar unterstützt oder ignoriert, muss die erste Zeile eine andere Skriptsprache durchlaufen, die dies ignoriert.

Das heißt, Sie können Bash-Skripte, die Inline-Blobs haben, die aufgerufen werden können. Spiele-Installer tun dies.

+0

Wie verwenden Sie ein binäres Blob in einem Bash-Skript? –

+0

zum Beispiel http://www.linuxjournal.com/content/add-binary-payload-your-shell-scripts – Alex

2

Statt viel Code zu schreiben, in Source-Form ausführbar haben Java sein, haben Sie ein paar Optionen:

Verwenden Scala! Wusstest du, dass Scala aus Java besteht? Es hat einen Interpreter und einen Compiler. Sie können ein Skript, eine Shell ausführen oder kompilieren und ausführen. Scala und Java arbeiten nahtlos zusammen. Beide kompilieren zu demselben Bytecode und laufen auf einer JVM. Ja, die Sprache würde sich komisch anfühlen, weil Scala wie eine Mischung aus Java, R und Python ist, aber die meisten Kernsprachen unverändert sind und alle Java-Pakete verfügbar sind. Gib Scala einen Versuch. Wenn Sie mit Linux arbeiten, können Sie Spark auch für eine Maschine betrachten.

Wenn Sie darauf bestehen, nur Java zu verwenden, können Sie ein hybrides Programm erstellen, das zwei Dinge erledigt (ich habe das schon einmal gemacht): Code kompilieren und ausführen. Die ausführbare Datei oder sogar ein Bash-Skript kann Quelldateien ausführen und sie ausführbar machen. Wenn Sie eine Java-Shell erstellen möchten, müssen Sie einen dynamischen Runtime-Compiler/Loader erstellen, aber Sie müssen nur das verwenden, was uns Java/Oracle bereits bietet. Stellen Sie sich vor, dass Sie die Java-Syntax aus einer Datei einfügen, in die ich eine Druckanweisung gesetzt habe. Du könntest alles da drin haben, was du willst, solange es kompiliert wird. Sehen Sie folgendes Beispiel:

package util.injection; 

import java.io.File; 
import java.io.FileWriter; 
import java.io.IOException; 
import java.io.Writer; 
import java.net.MalformedURLException; 
import java.net.URL; 
import java.net.URLClassLoader; 
import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.List; 
import java.util.Locale; 
import javax.tools.Diagnostic; 
import javax.tools.DiagnosticCollector; 
import javax.tools.JavaCompiler; 
import javax.tools.JavaFileObject; 
import javax.tools.StandardJavaFileManager; 
import javax.tools.ToolProvider; 

public class Compiler { 

    static final long t0 = System.currentTimeMillis(); 

    public static void main(String[] args) { 
     StringBuilder sb = new StringBuilder(64); 
     String packageName = "util"; 
     String className = "HelloWorld"; 
     sb.append("package util;\n"); 
     sb.append("public class HelloWorld extends " + Function.class.getName() + " {\n"); 
     sb.append(" public void test() {\n"); 
     sb.append("  System.out.println(\"Hello from dynamic function!\");\n"); 
     sb.append(" }\n"); 
     sb.append("}\n"); 
     String code = sb.toString(); 

     String jarLibraryFile = "target/myprojectname.jar"; 

     Function dynFunction = code2class(packageName, className, code, jarLibraryFile); 
     dynFunction.test(); 
    } 

    public static Function code2class(String packageName, String className, String code, String jarLibraryFile) { 
     String wholeClassName = packageName.replace("/", ".") + "." + className; 
     String fileName = wholeClassName.replace(".", "/") + ".java";//"testcompile/HelloWorld.java"; 
     File javaCodeFile = new File(fileName); 
     string2file(javaCodeFile, code); 
     Function dynFunction = null; 
     try { 

      boolean success = compile(jarLibraryFile, javaCodeFile); 

      /** 
      * Load and execute 
      * ************************************************************************************************ 
      */ 
      System.out.println("Running... " + (System.currentTimeMillis() - t0) + " ms"); 
      Object obj = load(wholeClassName); 
      // Santity check 
      if (obj instanceof Function) { 
       dynFunction = (Function) obj; 
       // Run it 
       //Edit: call dynFunction.test(); to see something 
      } 
      System.out.println("Finished... " + (System.currentTimeMillis() - t0) + " ms"); 
     } catch (IOException | ClassNotFoundException | InstantiationException | IllegalAccessException exp) { 
      exp.printStackTrace(); 
     } 
     return dynFunction; 
    } 

    public static boolean compile(String jarLibraryFile, File javaCodeFile) throws IOException { 
     /** 
     * Compilation Requirements 
     * ******************************************************************************************** 
     */ 
     System.out.println("Compiling... " + (System.currentTimeMillis() - t0) + " ms"); 
     DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>(); 
     JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 
     StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null); 

     // This sets up the class path that the compiler will use. 
     // I've added the .jar file that contains the DoStuff interface within in it... 
     List<String> optionList = new ArrayList<>(2); 
     optionList.add("-classpath"); 
     optionList.add(System.getProperty("java.class.path") + ";" + jarLibraryFile); 

     Iterable<? extends JavaFileObject> compilationUnit 
       = fileManager.getJavaFileObjectsFromFiles(Arrays.asList(javaCodeFile)); 
     JavaCompiler.CompilationTask task = compiler.getTask(
       null, 
       fileManager, 
       diagnostics, 
       optionList, 
       null, 
       compilationUnit); 
     fileManager.close(); 

     /** 
     * ******************************************************************************************* 
     * Compilation Requirements * 
     */ 
     if (task.call()) { 
      return true; 
      /** 
      * *********************************************************************************************** 
      * Load and execute * 
      */ 
     } else { 
      for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) { 
       System.out.format("Error on line %d in %s%n", 
         diagnostic.getLineNumber(), 
         diagnostic.getSource().toUri()); 
       System.out.printf("Code = %s\nMessage = %s\n", diagnostic.getCode(), diagnostic.getMessage(Locale.US)); 

      } 
     } 
     return false; 
    } 

    public static void string2file(File outputFile, String code) { 
     if (outputFile.getParentFile().exists() || outputFile.getParentFile().mkdirs()) { 

      try { 
       Writer writer = null; 
       try { 
        writer = new FileWriter(outputFile); 
        writer.write(code); 
        writer.flush(); 
       } finally { 
        try { 
         writer.close(); 
        } catch (Exception e) { 
        } 
       } 
      } catch (IOException exp) { 
       exp.printStackTrace(); 
      } 
     } 
    } 

    public static Object load(String wholeClassName) throws IllegalAccessException, InstantiationException, ClassNotFoundException, MalformedURLException { 
     // Create a new custom class loader, pointing to the directory that contains the compiled 
     // classes, this should point to the top of the package structure! 
     URLClassLoader classLoader = new URLClassLoader(new URL[]{new File("./").toURI().toURL()}); 
     // Load the class from the classloader by name.... 
     Class<?> loadedClass = classLoader.loadClass(wholeClassName); 
     // Create a new instance... 
     Object obj = loadedClass.newInstance(); 
     return obj; 
    } 

} 

..

package util.injection; 

public class Function { 

    private static final long serialVersionUID = 7526472295622776147L; 

    public void test() { 
       System.out.println("Hello from original Function!"); 
    } 

    public int getID() { 
     return -1; 
    } 

    public void apply(float[] img, int x, int y) { 

    } 

    public double dot(double[] x, double[] y) { 
      return 0; 
    } 
}