2009-02-08 28 views
119

Việc chạy lệnh Unix từ Java khá đơn giản.Làm thế nào để chạy tập lệnh shell Unix từ mã Java?

Runtime.getRuntime().exec(myCommand); 

Nhưng có thể chạy tập lệnh shell Unix từ mã Java không? Nếu có, nó sẽ là một thực hành tốt để chạy một kịch bản shell từ bên trong mã Java?

+3

Mọi thứ trở nên thú vị nếu tập lệnh trình bao đó tương tác. – ernesto

+0

biến myCommand là gì?nếu có, sau đó nó sẽ không hoạt động, phương thức exec yêu cầu String [] và đối số, xem bên dưới trả lời của tôi, nó hoạt động hoàn hảo –

+0

http://stackoverflow.com/questions/525212/how-to-run-unix-shell-script -from-java-code/37327025 # 37327025 –

Trả lời

21

Tôi nghĩ rằng bạn đã trả lời câu hỏi của riêng bạn với

Runtime.getRuntime().exec(myShellScript); 

Như để cho dù đó là thực hành tốt ... những gì bạn đang cố gắng để làm với một kịch bản shell mà bạn không thể làm với Java?

+0

Tôi đã đối mặt với một tình huống tương tự mà tôi cần phải rsync một vài tệp trên các máy chủ khác nhau khi một điều kiện nhất định xảy ra trong mã java của tôi. Có cách nào khác tốt hơn không? –

23

Tôi có thể nói rằng không phải là theo tinh thần của Java để chạy tập lệnh shell từ Java. Java có nghĩa là nền tảng chéo, và chạy một kịch bản lệnh shell sẽ giới hạn việc sử dụng nó chỉ với UNIX.

Với điều đó đã nói, chắc chắn có thể chạy tập lệnh shell từ bên trong Java. Bạn sẽ sử dụng chính xác cú pháp mà bạn đã liệt kê (tôi chưa tự thử nó, nhưng hãy thử thực thi kịch bản lệnh shell trực tiếp, và nếu nó không hoạt động, hãy thực thi shell, chuyển kịch bản vào như một tham số dòng lệnh) .

+37

Có, nhưng theo nhiều cách mà "tinh thần của Java" hoặc "viết một lần chạy ở khắp mọi nơi" thần chú là một huyền thoại anyway. – BobbyShaftoe

+12

Có gì huyền bí về nó? –

+6

"viết một lần chạy ở khắp mọi nơi" là lập trình viên ... – Spider

1

Có thể, chỉ cần thực thi nó như bất kỳ chương trình nào khác. Chỉ cần đảm bảo tập lệnh của bạn có đúng #! (she-bang) là dòng đầu tiên của tập lệnh và đảm bảo có quyền thực thi trên tệp.

Ví dụ: nếu đó là tập lệnh bash đặt #!/Bin/bash ở đầu tập lệnh, cũng chmod + x.

Cũng giống như nếu thực hành tốt, không có, đặc biệt đối với Java, nhưng nếu nó giúp bạn tiết kiệm rất nhiều thời gian để chuyển một kịch bản lớn, và bạn không được trả thêm tiền để làm điều đó;) thời gian, thực hiện kịch bản và đưa porting vào Java trên danh sách cần làm dài hạn của bạn.

153

Bạn thực sự nên xem Process Builder. Nó thực sự được xây dựng cho loại điều này.

ProcessBuilder pb = new ProcessBuilder("myshellScript.sh", "myArg1", "myArg2"); 
Map<String, String> env = pb.environment(); 
env.put("VAR1", "myValue"); 
env.remove("OTHERVAR"); 
env.put("VAR2", env.get("VAR1") + "suffix"); 
pb.directory(new File("myDir")); 
Process p = pb.start(); 
+0

Có thực hành tốt để gọi tập lệnh từ JAVA không? Bất kỳ vấn đề hiệu suất nào? – kautuksahni

+0

Lưu ý rằng bạn có thể cần phải chỉ định chương trình/bin/bash hoặc sh để thực thi tập lệnh bên trong tùy thuộc vào cấu hình của Java (xem https://stackoverflow.com/questions/25647806/running-shell-script-from-external- directory-no-such-file-or-directory) –

0

Chỉ cần cùng một điều mà Solaris 5.10 nó hoạt động như ./batchstart.sh này có một trick tôi không biết nếu hệ điều hành của bạn chấp nhận nó sử dụng \\. batchstart.sh để thay thế. Dấu gạch chéo kép này có thể hữu ích.

2

Đối với tôi tất cả mọi thứ phải đơn giản. Để chạy tập lệnh chỉ cần thực thi

new ProcessBuilder("pathToYourShellScript").start(); 
8

Có thể làm như vậy. Điều này làm việc cho tôi.

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 

import org.omg.CORBA.portable.InputStream; 

public static void readBashScript() { 
     try { 
      Process proc = Runtime.getRuntime().exec("/home/destino/workspace/JavaProject/listing.sh /"); //Whatever you want to execute 
      BufferedReader read = new BufferedReader(new InputStreamReader(
        proc.getInputStream())); 
      try { 
       proc.waitFor(); 
      } catch (InterruptedException e) { 
       System.out.println(e.getMessage()); 
      } 
      while (read.ready()) { 
       System.out.println(read.readLine()); 
      } 
     } catch (IOException e) { 
      System.out.println(e.getMessage()); 
     } 
    } 
0

Tôi nghĩ rằng với

System.getProperty("os.name"); 

Kiểm tra hệ điều hành trên có thể quản lý Scrips vỏ/bash nếu như được hỗ trợ. nếu cần phải tạo mã di động.

16

Bạn cũng có thể sử dụng Apache Commons exec library.

Ví dụ:

package testShellScript; 

import java.io.IOException; 
import org.apache.commons.exec.CommandLine; 
import org.apache.commons.exec.DefaultExecutor; 
import org.apache.commons.exec.ExecuteException; 

public class TestScript { 
    int iExitValue; 
    String sCommandString; 

    public void runScript(String command){ 
     sCommandString = command; 
     CommandLine oCmdLine = CommandLine.parse(sCommandString); 
     DefaultExecutor oDefaultExecutor = new DefaultExecutor(); 
     oDefaultExecutor.setExitValue(0); 
     try { 
      iExitValue = oDefaultExecutor.execute(oCmdLine); 
     } catch (ExecuteException e) { 
      System.err.println("Execution failed."); 
      e.printStackTrace(); 
     } catch (IOException e) { 
      System.err.println("permission denied."); 
      e.printStackTrace(); 
     } 
    } 

    public static void main(String args[]){ 
     TestScript testScript = new TestScript(); 
     testScript.runScript("sh /root/Desktop/testScript.sh"); 
    } 
} 

Để tham khảo thêm, Một ví dụ được đưa ra trên Apache Doc cũng có.

+0

Tôi có thể chạy điều này trong Windows không? – bekur

+0

@KisHanSarsecHaGajjar chúng ta cũng có thể thu được kết quả từ shellscript và hiển thị nó trong java ui. Tôi muốn biết là nó có thể làm như vậy –

+0

@KranthiSama Bạn có thể đặt 'OutputStream' cho' DefaultExecuter' bằng cách sử dụng phương thức 'DefaultExecuter.setStreamHandler' để nắm bắt đầu ra trong' OutputStream'. Vui lòng tham khảo chủ đề này để biết thêm thông tin: [Làm thế nào tôi có thể nắm bắt đầu ra của lệnh ...] (http://stackoverflow.com/a/6295923/1686291) –

1
String scriptName = PATH+"/myScript.sh"; 
    String commands[] = new String[]{scriptName,"myArg1", "myArg2"}; 

    Runtime rt = Runtime.getRuntime(); 
    Process process = null; 
    try{ 
     process = rt.exec(commands); 
     process.waitFor(); 
    }catch(Exception e){ 
     e.printStackTrace(); 
    } 
2

Đây là ví dụ của tôi. Hy vọng nó có ý nghĩa.

public static void excuteCommand(String filePath) throws IOException{ 
    File file = new File(filePath); 
    if(!file.isFile()){ 
     throw new IllegalArgumentException("The file " + filePath + " does not exist"); 
    } 
    if(this.isLinux()){ 
     Runtime.getRuntime().exec(new String[] {"/bin/sh", "-c", filePath}, null); 
    }else if(this.isWindows()){ 
     Runtime.getRuntime().exec("cmd /c start " + filePath); 
    } 
} 
public static boolean isLinux(){ 
    String os = System.getProperty("os.name"); 
    return os.toLowerCase().indexOf("linux") >= 0; 
} 

public static boolean isWindows(){ 
    String os = System.getProperty("os.name"); 
    return os.toLowerCase().indexOf("windows") >= 0; 
} 
2

Thư viện ZT Process Executor là một thay thế cho Apache Commons Exec. Nó có chức năng để chạy lệnh, bắt đầu ra, cài đặt thời gian chờ, v.v.

Tôi chưa sử dụng, nhưng có vẻ được ghi chép hợp lý.

Ví dụ từ tài liệu: Thực thi lệnh, bơm stderr vào trình ghi nhật ký, trả về kết quả dưới dạng chuỗi UTF8.

String output = new ProcessExecutor().command("java", "-version") 
    .redirectError(Slf4jStream.of(getClass()).asInfo()) 
    .readOutput(true).execute() 
    .outputUTF8(); 

tài liệu của nó sẽ liệt kê những ưu điểm sau trên Commons Exec:

  • Cải thiện xử lý dòng
    • đọc/ghi vào suối
    • Chuyển hướng stderr stdout
  • Cải thiện việc xử lý thời gian chờ
  • Cải thiện việc kiểm tra mã thoát
  • Cải thiện API
    • Một tàu đối với trường hợp sử dụng khá phức tạp
    • Một lót để có được đầu ra quá trình vào một String
    • Truy cập vào Process đối tượng sẵn
    • Hỗ trợ cho các quá trình không đồng bộ (Tương lai)
  • Cải thiện khai thác gỗ với SLF4J API
  • Hỗ trợ cho nhiều quy trình
2

Vâng, đó là có thể, và bạn đã trả lời nó! Về thực tiễn tốt, tôi nghĩ tốt hơn là khởi chạy lệnh từ các tệp và không trực tiếp từ mã của bạn. Vì vậy, bạn phải làm cho Java thực thi danh sách các lệnh (hoặc một lệnh) trong một tệp .bat, .sh, .ksh ... hiện có. Dưới đây là một ví dụ về thực hiện một danh sách các lệnh trong một tập tin "MyFile.sh":

String[] cmd = { "sh", "MyFile.sh", "\pathOfTheFile"}; 
    Runtime.getRuntime().exec(cmd); 
2

Để tránh phải hardcode một đường dẫn tuyệt đối, bạn có thể sử dụng các phương pháp sau đây sẽ tìm và thực thi kịch bản của bạn nếu nó nằm trong thư mục gốc của bạn.

public static void runScript() throws IOException, InterruptedException { 
    ProcessBuilder processBuilder = new ProcessBuilder("./nameOfScript.sh"); 
    //Sets the source and destination for subprocess standard I/O to be the same as those of the current Java process. 
    processBuilder.inheritIO(); 
    Process process = processBuilder.start(); 

    int exitValue = process.waitFor(); 
    if (exitValue != 0) { 
     // check for errors 
     new BufferedInputStream(process.getErrorStream()); 
     throw new RuntimeException("execution of script failed!"); 
    } 
} 
Các vấn đề liên quan