簡體   English   中英

如何使用 Java 通過 Windows/cygwin 執行 unix 命令

[英]How to execute unix commands through Windows/cygwin using Java

我正在嘗試完成兩件事:

  1. 我在 Windows7 上運行 cygwin 來執行我的 unix shell 命令,我需要通過編寫 Java 應用程序來自動化該過程。 我已經知道如何通過 Java 使用 windows shell 和Runtime.getRuntime().exec("cmd /c dir") 我需要能夠對 unix 命令執行相同的操作:即: ls -la等等。 我應該調查什么?

  2. 有沒有辦法記住外殼的 state? 解釋:當我使用: Runtime.getRuntime().exec("cmd /c dir")時,我總是得到我的主目錄的列表。 如果我執行Runtime.getRuntime().exec("cmd /c cd <some-folder>")然后再次執行Runtime.getRuntime().exec("cmd /c dir") ,我仍然會得到列表我的主文件夾。 有沒有辦法告訴進程記住它的 state,就像普通的 shell 一樣?


Paŭlo 提出的bash命令行似乎不起作用:

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

我無法弄清楚技術細節。

這是我的代碼:

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

line最終具有 null 值。


我將此添加到 my.bash_profile 中:

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

我還添加了以下內容:

系統屬性 -> 高級 -> 環境變量 -> 用戶變量 -> 變量: BASH ,值: c:\cygwin\bin

依然沒有...

但是,如果我改為執行此操作,它會起作用!

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

1、調用unix命令:

您只需調用您的 unix shell(例如隨 cygwin 交付的 bash)而不是cmd

bash -c "ls -la"

應該做。 當然,如果你的命令是一個外部程序,你可以直接調用它:

ls -la

從 Java 開始時,最好使用帶有字符串數組的變體,因為這樣你就沒有 Java 讓它解析以查看 ZDBC11CAA5BDA99F77E6FB4DABD882E7D 的開始和停止位置:

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

您的示例中的錯誤消息( ls: command not found )似乎表明您的 bash 找不到ls命令。 也許您需要將它放入 PATH 變量中(參見上面的 Java 執行此操作的方法)。

也許不是/cygdrive/c/cygwin/bin ,正確的目錄名稱應該是/usr/bin

(這里的一切都有些復雜,因為必須在 Unix 和 Windows 約定之間架起橋梁。)

簡單的ls命令可以這樣調用:

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

2.調用多個命令:

在一個 shell 中調用多個命令基本上有兩種方法:

  • 一次將它們全部傳遞給 shell; 或者
  • 以交互方式將它們傳遞給 shell。

對於第一種方式,只需將多個命令作為-c選項的參數,用;分隔。 \n (換行符),如下所示:

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

或來自 Java(改編上面的例子):

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

此處 shell 會將命令行解析為,並將其作為腳本執行。 如果它包含多個命令,它們都將被執行,如果 shell 由於某種原因之前沒有以某種方式退出(如exit命令)。 (我不確定 Windows cmd是否以類似的方式工作。請測試並報告。)

Instead of passing the bash (or cmd or whatever shell you are using) the commands on the command line, you can pass them via the Process' input stream.

  • 以“輸入模式”啟動的 shell(例如,既沒有-c選項也沒有 shell 腳本文件參數)將從 ZF7B44CFAFD5C52223D5498196C8A2E7B 讀取輸入並將第一行解釋為命令行。
  • 然后它將執行此命令。 如果需要,該命令本身可能會從 stream 讀取更多輸入。
  • 然后 shell 將讀取下一行,將其解釋為命令,然后執行。
  • (在某些情況下,shell 必須讀取不止一行,例如對於長字符串或組合命令,如 if 或循環。)
  • 這將 go 開啟,直到 stream 結束(例如 stream.close() 在您身邊)或執行顯式exit命令(或退出的其他一些原因)

這是一個例子:

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();

您在這里不需要 cygwin。 有幾個純 Java 庫實現了 SSH 協議。 使用它們。 順便說一句,他們將解決您的第二個問題。 您將打開 session 並使用相同的 session 執行命令,因此 shell Z9ED39E2EA9314258A 將自動保留。

一個例子是JSch

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM