2011-07-19 12 views
8

staram się osiągnąć dwie rzeczy:Jak wykonać UNIX poprzez Windows/Cygwin używając Java

  1. Używam Cygwin na Windows7 do wykonywania moich poleceń powłoki UNIX i muszę zautomatyzować proces pisząc aplikacja Java. Już wiem, jak używać powłoki systemu Windows przez Javę, używając "klasy procesowej" i Runtime.getRuntime().exec("cmd /c dir"). Muszę być w stanie zrobić to samo z poleceniami unix: tj. ls -la i tak dalej. Na co powinienem zaglądać?

  2. Czy istnieje sposób na zapamiętanie stanu muszli? wyjaśnienie: kiedy używam: Runtime.getRuntime().exec("cmd /c dir"), zawsze otrzymuję listę mojego katalogu domowego. Jeśli wykonam Runtime.getRuntime().exec("cmd /c cd <some-folder>"), a następnie ponownie zrobię Runtime.getRuntime().exec("cmd /c dir"), nadal otrzymam listę mojego katalogu domowego. Czy istnieje sposób, aby powiedzieć procesowi, aby pamiętał jego stan, jak zwykła powłoka?


Wydaje się, że linia poleceń bash proponowany przez Paulo nie działa:

C:\cygwin\bin>bash -c ls -la 
-la: ls: command not found 

Mam problemy ze zorientowaniem się szczegóły techniczne.

To jest mój kod:

p = Runtime.getRuntime().exec("C:\\cygwin\\bin\\bash.exe -c ls -la"); 
reader2 = new BufferedReader(new InputStreamReader(p.getInputStream())); 
line = reader2.readLine(); 

line kończy się o wartość null.


Dodałem to do mojego bash_profile:

#BASH 
export BASH_HOME=/cygdrive/c/cygwin 
export PATH=$BASH_HOME/bin:$PATH 

Dodałem także następujące:

Właściwości systemu -> Zaawansowane -> Zmienne Środowiska -> użytkownik variebales -> zmienna: BASH, wartość: c:\cygwin\bin

Jeszcze nic ...

Jeśli jednak wykonam to zamiast tego, działa!

p = Runtime.getRuntime().exec("c:\\cygwin\\bin\\ls -la ~/\"Eclipse_Workspace/RenameScript/files copy\""); 
+0

Dobra, zobaczmy. Bezpośrednie wykonanie 'ls.exe' wydaje się działać, jeśli damy właściwą ścieżkę. –

+0

ok, jak mogę sprawić, aby bash rozpoznał go przy użyciu argumentu -c? –

+0

Myślę, że podczas wykonywania z '-c', nie wykonuje twojego' .bashrc'. Możesz spróbować ustawić ścieżkę z argumentem 'envp' na' exec'. (Dodam do mojej odpowiedzi.) –

Odpowiedz

8

1. Wywołanie polecenia UNIX:

Wystarczy zadzwonić do powłoki Unix (np bash dostarczane z Cygwin) zamiast cmd.

bash -c "ls -la" 

powinien zrobić.Oczywiście, jeśli polecenie jest zewnętrzny program, można po prostu nazwać to bezpośrednio:

ls -la 

Uruchamiając ten z Jawy, najlepiej jest skorzystać z wariantu, która pobiera tablicę ciągów, a następnie don” t mieć Java niech to przeanalizować, aby zobaczyć gdzie zacząć i przestać argumenty:

Process p = 
    Runtime.getRuntime().exec(new String[]{"C:\\cygwin\\bin\\bash.exe", 
              "-c", "ls -la"}, 
           new String[]{"PATH=/cygdrive/c/cygwin/bin"}); 

komunikat o błędzie w swoim przykładzie (ls: command not found) wydaje się wskazywać, że bash nie można znaleźć komendy ls. Może musisz umieścić go w zmiennej PATH (zobacz powyżej, aby dowiedzieć się, jak to zrobić z Java).

Być może zamiast nazwy /cygdrive/c/cygwin/bin, prawą nazwą katalogu będzie /usr/bin.

(Wszystko jest nieco skomplikowane tu konieczności most między Unix i Windows konwencje wszędzie).

ls prosta komenda można nazwać tak:

Process p = Runtime.getRuntime().exec(new String[]{"C:\\cygwin\\bin\\ls.exe", "-la"}); 

2. Wywoływanie wielokrotność polecenia:

Istnieją zasadniczo dwa sposoby wywoływania wielu poleceń w jednej powłoce:

  • przekazywanie ich wszystkich na raz do powłoki; lub
  • przekazywanie ich interaktywnie do powłoki.

Dla pierwszego sposobu, należy podać wielu poleceń w nagłówku opcji -c oddzielonych ; lub \n (nowa linia) w następujący sposób:

bash -c "cd /bin/ ; ls -la" 

lub Java (dostosowania powyższym przykładzie):

Process p = 
    Runtime.getRuntime().exec(new String[]{"C:\\cygwin\\bin\\bash.exe", 
              "-c", "cd /bin/; ls -la"}, 
           new String[]{"PATH=/cygdrive/c/cygwin/bin"}); 

Tutaj powłoka przetworzy wiersz polecenia jako i wykona go jako skrypt. Jeśli zawiera wiele poleceń, wszystkie zostaną wykonane, jeśli powłoka z jakiegoś powodu nie zakończyła się z jakiegoś powodu (jak polecenie exit). (Nie jestem pewien, czy Windows cmd działa w podobny sposób. Proszę przetestuj i zgłoś.)

Zamiast podawać bash (lub cmd lub inną powłokę, której używasz) polecenia na linii poleceń , możesz je przekazać przez strumień wejściowy Procesu.

  • Powłoka rozpoczęła się w trybie „wejścia” (np jednego który dostał ani opcji -c ani argument powłoki pliku skryptu) będzie czytać dane ze strumienia i zinterpretować pierwszej linii jako polecenie (lub kilku z nich) .
  • Następnie wykona to polecenie. Samo polecenie może odczytać więcej danych ze strumienia, jeśli chce.
  • Następnie powłoka odczyta następną linię, zinterpretuje ją jako polecenie i wykona.
  • (W niektórych przypadkach powłoka musi odczytać więcej niż jedną linię, na przykład dla długich ciągów lub złożonych poleceń, takich jak if lub loop.)
  • To będzie działać aż do końca strumienia (na przykład stream.close() u twojego boku) lub wykonania jawnej komendy exit (lub innych powodów do wyjścia).

Tutaj byłoby przykładem na to:

Process p = Runtime.getRuntime().exec(new String[]{"C:\\cygwin\\bin\\bash.exe", "-s"}); 
InputStream outStream = p.getInputStream(); // normal output of the shell 
InputStream errStream = p.getInputStream(); // error output of the shell 
// TODO: start separate threads to read these streams 

PrintStream ps = new PrintStream(p.getOutputStream()); 
ps.println("cd /bin/"); 
ps.println("ls -la"); 
ps.println("exit"); 
ps.close(); 
+0

Proszę umieścić kod w swoim pytaniu (jest przycisk edycji), nie można go odczytać jako komentarza. –

+0

Ponadto, myślę, że nie potrzebujesz 'mintty', ponieważ nie chcesz terminalu - zamiast tego bezpośrednio wywołaj' bash.exe'. –

+0

Oryginalny wpis edytowany! Nie rozumiem także, jak działa komentowanie komentarzy w "StackOverflow" –

1

Nie trzeba cygwin tutaj. Istnieje kilka czystych bibliotek Java implementujących protokół SSH. Użyj ich. BTW rozwiążą twój drugi problem. Otworzysz sesję i wykonasz polecenie przy użyciu tej samej sesji, więc stan powłoki zostanie automatycznie zachowany.

Jednym z przykładów może być JSch.

+0

SSH nie pomoże wykonać poleceń powłoki uniksowej w oknie Windows. –

+0

javadocs jscha nie działają i nie mogę znaleźć zależności. czy mógłbyś mi pomóc? co się dzieje w moim pliku pom.xml? –

+0

@Martin: JSch nie jest emulacją unixową w Javie, jest implementacją klienta SSH. Możesz użyć tego do połączenia się z serwerem (zwykle innym komputerem), który następnie musi mieć serwer SSH i powłokę. –

Powiązane problemy