Java에서 Unix 명령을 실행하는 것은 매우 간단합니다.
Runtime.getRuntime().exec(myCommand);
그러나 Java 코드에서 Unix 쉘 스크립트를 실행할 수 있습니까? 그렇다면 Java 코드 내에서 쉘 스크립트를 실행하는 것이 좋습니다.
Java에서 Unix 명령을 실행하는 것은 매우 간단합니다.
Runtime.getRuntime().exec(myCommand);
그러나 Java 코드에서 Unix 쉘 스크립트를 실행할 수 있습니까? 그렇다면 Java 코드 내에서 쉘 스크립트를 실행하는 것이 좋습니다.
답변:
실제로 Process Builder를 살펴보십시오 . 실제로 이런 종류의 것을 위해 만들어졌습니다.
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();
Apache Commons exec 라이브러리 도 사용할 수 있습니다 .
예 :
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");
}
}
추가 참조를 위해 Apache Doc 에서도 예제를 제공합니다 .
OutputStream
에 대한 DefaultExecuter
사용 DefaultExecuter.setStreamHandler
에서 캡처 출력 방법 OutputStream
. 자세한 내용은이 스레드를 참조하십시오 . 명령의 출력을 캡처하는 방법 ...
Java 에서 쉘 스크립트를 실행하는 것이 Java의 정신에 있지 않다고 말하고 싶습니다 . Java는 크로스 플랫폼이어야하며 쉘 스크립트를 실행하면 사용이 UNIX로만 제한됩니다.
그렇게 말하면 Java 내에서 쉘 스크립트를 실행할 수 있습니다. 나열된 구문과 정확히 동일한 구문을 사용합니다 (내가 직접 시도하지는 않았지만 쉘 스크립트를 직접 실행 해보십시오. 그래도 작동하지 않으면 쉘 자체를 실행하고 스크립트를 명령 행 매개 변수로 전달하십시오) .
switches
와 if
자바 코어 라이브러리와 함께 제공되는 사람들의 최선의 노력에도 불구하고 서로 다른 플랫폼에서 동일 작동하지 않습니다 뉘앙스를 모두 해결하기 위해 문을.
나는 당신이 자신의 질문에 대답했다고 생각합니다.
Runtime.getRuntime().exec(myShellScript);
좋은 습관인지에 관해서는 Java로 할 수없는 쉘 스크립트로 무엇을하려고합니까?
그렇습니다. 이것은 나를 위해 일했다.
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());
}
}
여기 내 예가 있습니다. 이해하기를 바랍니다.
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(isLinux()){
Runtime.getRuntime().exec(new String[] {"/bin/sh", "-c", filePath}, null);
}else if(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;
}
절대 경로를 하드 코딩하지 않으려면 루트 디렉토리에있는 스크립트를 찾아서 실행하는 다음 방법을 사용할 수 있습니다.
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!");
}
}
ZT 프로세스 실행 프로그램 라이브러리는 아파치 코 몬즈 Exec에서의 대안입니다. 명령 실행, 출력 캡처, 시간 초과 설정 등의 기능이 있습니다.
아직 사용하지 않았지만 합리적으로 잘 정리되어 있습니다.
문서의 예 : 명령 실행, stderr를 로거로 펌핑하여 UTF8 문자열로 출력을 리턴합니다.
String output = new ProcessExecutor().command("java", "-version")
.redirectError(Slf4jStream.of(getClass()).asInfo())
.readOutput(true).execute()
.outputUTF8();
이 문서에는 Commons Exec에 비해 다음과 같은 장점이 있습니다.
다음은 Java에서 Unix bash 또는 Windows bat / cmd 스크립트를 실행하는 방법의 예입니다. 스크립트에서 인수를 전달하고 스크립트에서 출력을 수신 할 수 있습니다. 이 메소드는 임의의 수의 인수를 허용합니다.
public static void runScript(String path, String... args) {
try {
String[] cmd = new String[args.length + 1];
cmd[0] = path;
int count = 0;
for (String s : args) {
cmd[++count] = args[count - 1];
}
Process process = Runtime.getRuntime().exec(cmd);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
try {
process.waitFor();
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
while (bufferedReader.ready()) {
System.out.println("Received from script: " + bufferedReader.readLine());
}
} catch (Exception ex) {
System.out.println(ex.getMessage());
System.exit(1);
}
}
유닉스 / 리눅스에서 실행할 때 경로는 유닉스와 같아야하며 ( '/'를 구분 기호로 사용) Windows에서 실행할 때는 '\'를 사용하십시오. Hier는 임의의 수의 인수를 받고 모든 인수를 두 배로 만드는 bash 스크립트 (test.sh)의 예입니다.
#!/bin/bash
counter=0
while [ $# -gt 0 ]
do
echo argument $((counter +=1)): $1
echo doubling argument $((counter)): $(($1+$1))
shift
done
전화 할 때
runScript("path_to_script/test.sh", "1", "2")
유닉스 / 리눅스에서 출력은 다음과 같습니다.
Received from script: argument 1: 1
Received from script: doubling argument 1: 2
Received from script: argument 2: 2
Received from script: doubling argument 2: 4
Hier는 간단한 cmd Windows 스크립트 test.cmd로 여러 입력 인수를 계산합니다.
@echo off
set a=0
for %%x in (%*) do Set /A a+=1
echo %a% arguments received
Windows에서 스크립트를 호출 할 때
runScript("path_to_script\\test.cmd", "1", "2", "3")
출력은
Received from script: 3 arguments received
다른 프로그램처럼 실행할 수도 있습니다. 스크립트에 적절한 #이 있는지 확인하십시오! (she-bang) 행을 스크립트의 첫 번째 행으로 사용하고 파일에 대한 실행 권한이 있는지 확인하십시오.
예를 들어, bash 스크립트 인 경우 #! / bin / bash를 스크립트의 맨 위에두고 chmod + x도 입력하십시오.
또한 좋은 습관 인 경우, 특히 Java의 경우는 아니지만 큰 스크립트를 이식하는 데 많은 시간을 절약하고 추가 비용을 지불하지 않으면 시간을 절약하십시오.) 스크립트를 작성하고 장기적인 할 일 목록에 Java로 포팅하십시오.
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();
}
이것은 늦은 답변입니다. 그러나 미래 개발자를 위해 Spring-Boot 응용 프로그램에서 쉘 스크립트를 실행하려면 많은 노력을 기울여야한다고 생각했습니다.
나는 Spring-Boot에서 일하고 있었고 Java 응용 프로그램에서 실행할 파일을 찾을 수 없어서 던졌습니다 FileNotFoundFoundException
. 파일을 resources
디렉토리 에 보관하고 pom.xml
응용 프로그램이 다음과 같이 시작되는 동안 파일을 검색하도록 설정해야 했습니다.
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
<include>**/*.sh</include>
</includes>
</resource>
</resources>
error code = 13, Permission Denied
. 그런 다음이 명령을 실행하여 파일을 실행 가능하게 만들어야했습니다.chmod u+x myShellScript.sh
마지막으로 다음 코드 스 니펫을 사용하여 파일을 실행할 수 있습니다.
public void runScript() {
ProcessBuilder pb = new ProcessBuilder("src/main/resources/myFile.sh");
try {
Process p;
p = pb.start();
} catch (IOException e) {
e.printStackTrace();
}
}
누군가의 문제를 해결하기를 바랍니다.
리눅스 용
public static void runShell(String directory, String command, String[] args, Map<String, String> environment)
{
try
{
if(directory.trim().equals(""))
directory = "/";
String[] cmd = new String[args.length + 1];
cmd[0] = command;
int count = 1;
for(String s : args)
{
cmd[count] = s;
count++;
}
ProcessBuilder pb = new ProcessBuilder(cmd);
Map<String, String> env = pb.environment();
for(String s : environment.keySet())
env.put(s, environment.get(s));
pb.directory(new File(directory));
Process process = pb.start();
BufferedReader inputReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedWriter outputReader = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
BufferedReader errReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
int exitValue = process.waitFor();
if(exitValue != 0) // has errors
{
while(errReader.ready())
{
LogClass.log("ErrShell: " + errReader.readLine(), LogClass.LogMode.LogAll);
}
}
else
{
while(inputReader.ready())
{
LogClass.log("Shell Result : " + inputReader.readLine(), LogClass.LogMode.LogAll);
}
}
}
catch(Exception e)
{
LogClass.log("Err: RunShell, " + e.toString(), LogClass.LogMode.LogAll);
}
}
public static void runShell(String path, String command, String[] args)
{
try
{
String[] cmd = new String[args.length + 1];
if(!path.trim().isEmpty())
cmd[0] = path + "/" + command;
else
cmd[0] = command;
int count = 1;
for(String s : args)
{
cmd[count] = s;
count++;
}
Process process = Runtime.getRuntime().exec(cmd);
BufferedReader inputReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedWriter outputReader = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
BufferedReader errReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
int exitValue = process.waitFor();
if(exitValue != 0) // has errors
{
while(errReader.ready())
{
LogClass.log("ErrShell: " + errReader.readLine(), LogClass.LogMode.LogAll);
}
}
else
{
while(inputReader.ready())
{
LogClass.log("Shell Result: " + inputReader.readLine(), LogClass.LogMode.LogAll);
}
}
}
catch(Exception e)
{
LogClass.log("Err: RunShell, " + e.toString(), LogClass.LogMode.LogAll);
}
}
그리고 사용을 위해;
ShellAssistance.runShell("", "pg_dump", new String[]{"-U", "aliAdmin", "-f", "/home/Backup.sql", "StoresAssistanceDB"});
또는
ShellAssistance.runShell("", "pg_dump", new String[]{"-U", "aliAdmin", "-f", "/home/Backup.sql", "StoresAssistanceDB"}, new Hashmap<>());