2012-10-13 12 views
8

Possible Duplicate:
Executing a shell script inside a jar file. How to extract?Java Script Shell Execute spakowany w JAR

Mam skrypt pakowane w moim pliku JAR w ramach pakietu 'silnik'.

W moim programie używam polecenia powłoki, używając Process i ProcessBuilder. Wszystko działa dobrze.

Jeśli określę ścieżkę do skryptu powłoki na moim komputerze, program działa poprawnie. Jeśli jednak mam zapakować skrypt do mojego JAR, a dostęp do niego tak:

scriptLocation = this.getClass().getResource("/engine/shell-script.sh").toString(); 

i uruchomić program, a następnie pojawia się następujący błąd:

java.io.IOException: Cannot run program "file:/Users/USERNAME/Desktop/Application-Name.jar!/engine/shell-script.sh": error=2, No such file or directory 
    at java.lang.ProcessBuilder.start(ProcessBuilder.java:460) 
    at java.lang.Runtime.exec(Runtime.java:593) 
    at java.lang.Runtime.exec(Runtime.java:431) 
    at java.lang.Runtime.exec(Runtime.java:328) 
    at engine.Download$1.run(Download.java:39) 
    at java.lang.Thread.run(Thread.java:680) 
Caused by: java.io.IOException: error=2, No such file or directory 
    at java.lang.UNIXProcess.forkAndExec(Native Method) 
    at java.lang.UNIXProcess.<init>(UNIXProcess.java:53) 
    at java.lang.ProcessImpl.start(ProcessImpl.java:91) 
    at java.lang.ProcessBuilder.start(ProcessBuilder.java:453) 
    ... 5 more 

Zaczynam myśleć, że to nie może zrobić, bardzo chciałbym dostarczyć ten skrypt powłoki jako część aplikacji, czy można to zrobić?

Z góry dziękuję wszystkim.

======== UPDATE ==========

I w końcu rozwiązać ten problem. Shell nie może wykonywać skryptów w pakiecie JAR, nie chodzi o Javę, ale o powłokę. Naprawiłem to, wykonując następujące czynności:

Java ma metodę createTempFile() (z opcją usunięcia pliku po zakończeniu aplikacji), wywołaj to i zapisz plik w pakiecie JAR, do którego chcesz uzyskać dostęp do tego pliku tymczasowego. Następnie masz skrypt powłoki w lokalnym systemie plików i jesteś w stanie wykonać skrypt.

Odpowiedz

4

Its nie o Javie, jej o powłoce. O ile mi wiadomo, interpreter powłoki nie może wykonywać skryptów znajdujących się w pliku zip. Masz tutaj kilka opcji:

  1. Przeczytaj skrypt powłoki jako plik tekstowy z poziomu programu java. utworzyć plik czasową (w temp dir lub inne stosowne miejsce i skopiować zawartość tam pliku. A następnie wywołać interpreter powłoki z tego skryptu skroniowej. wierzę jej najlepszym podejściem

  2. Od słoik jest zip, możesz rozpakować go z poziomu powłoki, znaleźć skrypt i wykonać powłokę.Znowu jest to bardziej niezręczne i raczej błędne, ale pod względem technicznym powinno działać.

  3. Jeśli w swoim skrypcie nie masz elementów o niskim poziomie, możesz rozważyć przepisanie logiki na groovy (być może znajdziesz użyteczny projekt groosh). Następnie wywołaj groovy kod z pamięci, a nie z pliku.

Cóż, jestem z pomysłów, If I were you, chciałbym wdrożyć pierwsze rozwiązanie :) powodzenia i mam nadzieję, że to pomoże

+0

Dziękuję za odpowiedź, zobaczę, jak mogę wyodrębnić skrypt powłoki z pliku jar do tymczasowej lokalizacji, a następnie wydobyć ją stamtąd, czy wiesz, jak mogę zrobić to lub znać jakieś linki? Dzięki za odpowiedź! – Cristian

+0

Jak już wspomniałem w innym miejscu, możesz to zrobić: rozpakować -p JARFILE SCRIPTFILE | grzmotnąć. To zasadniczo rozpakuje plik ze słoika, ale w rzeczywistości nie tworzy pliku. – Jay

3

Najprostszym rozwiązaniem jest wypakowanie skryptu powłoki do tymczasowej lokalizacji i wykonanie jej z tego miejsca.

Możesz utworzyć tymczasowy plik w Javie, dzwoniąc pod numer File.createTempFile(String, String).

Inną rzeczą, którą możesz ewentualnie zrobić, to przekazanie zawartości skryptu, załadowanego ze swojego słoika, jako standardowego wejścia powłoki.

W uproszczeniu, gdybym miał archiwum a.zip zawierającego skrypt a.sh, to byłoby to wykonać:

$ unzip -p a.zip a.sh | bash 

Z programu Java, można wykonać następujące czynności:

import java.io.*; 
class Test{ 

    public static void main(String[]args) throws Exception { 

    StringBuilder sb = new StringBuilder(); 

    // You're not strictly speaking executing a shell script but 
    // rather programatically typing commands into the shell 
    // sb.append("#!/bin/bash\n"); 
    sb.append("echo Hello world!\n"); 
    sb.append("cd /tmp\n"); 
    sb.append("echo current directory: `pwd`\n"); 

    // Start the shell 
    ProcessBuilder pb = new ProcessBuilder("/bin/bash"); 
    Process bash = pb.start(); 

    // Pass commands to the shell 
    PrintStream ps = new PrintStream(bash.getOutputStream()); 
    ps.println(sb); 
    ps.close(); 

    // Get an InputStream for the stdout of the shell 
    BufferedReader br = new BufferedReader(
     new InputStreamReader(bash.getInputStream())); 

    // Retrieve and print output 
    String line; 
    while (null != (line = br.readLine())) { 
     System.out.println("> "+line); 
    } 
    br.close(); 

    // Make sure the shell has terminated, print out exit value 
    System.out.println("Exit code: " + bash.waitFor()); 

    } 

} 
+0

Wolałbym nie kopiować plików do systemu użytkownika, w jaki sposób chciałbym przekazać zawartość skryptu do użycia w programie? – Cristian

+0

Moim zdaniem bardzo interesujące rozwiązanie, dziękuję za udostępnienie –

0

ja zwykle po prostu zrobić ...

$ jar xf myapp.jar run.sh && ./run.sh && rm run.sh 

... które można wywołać z Runtime.exec(), jeśli to konieczne.

+0

Byłoby dobrze, gdyby plik JAR został uruchomiony z wiersza poleceń, ale jest to działający plik JAR – Cristian

+0

Wykonanie go za pomocą Runtime.exec() powinno być w stanie obejść to, choć jest to wprawdzie brzydkie. – rich