Java'dan bir Unix komutu çalıştırmak oldukça basittir.
Runtime.getRuntime().exec(myCommand);
Ancak Java kodundan bir Unix kabuk betiği çalıştırmak mümkün mü? Evetse, Java kodundan bir kabuk komut dosyası çalıştırmak iyi bir uygulama olur mu?
Java'dan bir Unix komutu çalıştırmak oldukça basittir.
Runtime.getRuntime().exec(myCommand);
Ancak Java kodundan bir Unix kabuk betiği çalıştırmak mümkün mü? Evetse, Java kodundan bir kabuk komut dosyası çalıştırmak iyi bir uygulama olur mu?
Yanıtlar:
Process Builder'a gerçekten bakmalısınız . Gerçekten bu tür şeyler için üretildi.
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();
Sen kullanabilirsiniz Apache Commons exec kütüphane de.
Misal :
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");
}
}
Daha fazla referans için, Apache Doc üzerinde de bir örnek verilmiştir .
OutputStream
için DefaultExecuter
kullanarak DefaultExecuter.setStreamHandler
yakalama çıkışına yöntemi OutputStream
. Daha fazla bilgi için lütfen bu konuyu inceleyin: Bir komutun çıktısını nasıl yakalayabilirim ...
Java'dan bir kabuk betiği çalıştırmanın Java ruhu içinde olmadığını söyleyebilirim . Java, çapraz platform anlamına gelir ve bir kabuk komut dosyası çalıştırmak, kullanımını yalnızca UNIX ile sınırlar.
Bununla birlikte, Java içinden bir kabuk betiği çalıştırmak kesinlikle mümkündür. Listelediğiniz sözdiziminin aynısını kullanırsınız (kendim denemedim, ancak kabuk komut dosyasını doğrudan çalıştırmayı deneyin ve bu işe yaramazsa, komut dosyasını bir komut satırı parametresi olarak geçirerek kabuğun kendisini yürütün) .
switches
ve if
ifade yazmanızdır .
Bence kendi sorunuzu
Runtime.getRuntime().exec(myShellScript);
İyi bir uygulama olup olmadığı konusunda ... Java ile yapamayacağınız bir kabuk komut dosyası ile ne yapmaya çalışıyorsunuz?
Evet bunu yapmak mümkündür. Bu benim için işe yaradı.
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());
}
}
İşte benim örneğim. Umarım mantıklıdır.
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;
}
Evet, mümkün ve cevapladınız! İyi uygulamalar hakkında, doğrudan kodunuzdan değil, dosyalardan komut başlatmak daha iyi olur. Eğer yapmak zorunda Yani Java varolan komutları (veya tek bir komut) listesini yürütmek .bat
, .sh
, .ksh
... dosyaları. Bir dosyadaki komutların listesini yürütmeye bir örnek MyFile.sh
:
String[] cmd = { "sh", "MyFile.sh", "\pathOfTheFile"};
Runtime.getRuntime().exec(cmd);
Mutlak bir yolu kodlamak zorunda kalmamak için, komut dizenizi kök dizininizdeyse bulup yürütecek olan aşağıdaki yöntemi kullanabilirsiniz.
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!");
}
}
Bana gelince, her şey basit olmalı. Çalışan komut dosyası için yürütmeniz yeterlidir
new ProcessBuilder("pathToYourShellScript").start();
ZT yöntem Executor kütüphanesi Apache Commons Exec için bir alternatiftir. Komutları çalıştırma, çıktılarını yakalama, zaman aşımlarını ayarlama vb.
Henüz kullanmadım, ancak oldukça iyi belgelenmiş görünüyor.
Belgelerden bir örnek: Bir komutu yürütmek, stderr'i bir günlükçüye pompalamak, çıktıyı UTF8 dizesi olarak döndürmek.
String output = new ProcessExecutor().command("java", "-version")
.redirectError(Slf4jStream.of(getClass()).asInfo())
.readOutput(true).execute()
.outputUTF8();
Belgeleri Commons Exec'a göre aşağıdaki avantajları listeler:
Java'dan Unix bash veya Windows bat / cmd betiğinin nasıl çalıştırılacağı ile ilgili bir örnek. Bağımsız değişkenler kod üzerinde iletilebilir ve koddan çıktı alınabilir. Yöntem, rastgele sayıda argümanı kabul eder.
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);
}
}
Unix / Linux üzerinde çalışırken, Windows üzerinde çalışırken yol Unix benzeri (ayırıcı olarak '/' ile) olmalıdır - '\' kullanın. Hier, rastgele sayıda argüman alan ve her argümanı ikiye katlayan bir bash betiği (test.sh) örneğidir:
#!/bin/bash
counter=0
while [ $# -gt 0 ]
do
echo argument $((counter +=1)): $1
echo doubling argument $((counter)): $(($1+$1))
shift
done
Ararken
runScript("path_to_script/test.sh", "1", "2")
Unix / Linux'ta çıktı:
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, giriş argümanlarının sayısını sayan basit bir cmd Windows komut dosyası test.cmd'dir:
@echo off
set a=0
for %%x in (%*) do Set /A a+=1
echo %a% arguments received
Komut dosyasını Windows'ta çağırırken
runScript("path_to_script\\test.cmd", "1", "2", "3")
Çıktı
Received from script: 3 arguments received
Mümkün, sadece başka bir program gibi çalıştırın. Komut dosyanızın doğru # olduğundan emin olun! (she-bang) satırını komut dosyasının ilk satırı olarak ekleyin ve dosyada yürütme izinleri olduğundan emin olun.
Örneğin, bir bash betiğiyse #! / Bin / bash'ı betiğin en üstüne koyun, ayrıca chmod + x.
Ayrıca iyi bir uygulama olarak, hayır, özellikle Java için değil, ancak büyük bir komut dosyasını taşımak için çok fazla zaman kazandırırsa ve bunu yapmak için fazladan ödeme almazsanız;) zamandan tasarruf edin, komut dosyasını ekleyin ve uzun vadeli yapılacaklar listenizde bağlantı noktasını Java'ya yerleştirin.
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();
}
Bu geç bir cevap. Ancak, gelecekteki geliştiriciler için bir Spring-Boot uygulamasından yürütülecek bir kabuk komut dosyası almak için katlanmak zorunda olduğum mücadeleyi koymayı düşündüm.
Spring-Boot'da çalışıyordum ve Java uygulamamdan çalıştırılacak dosyayı bulamadım ve fırlatıyordu FileNotFoundFoundException
. Dosyayı resources
dizinde tutmak zorunda kaldım pom.xml
ve uygulama aşağıdaki gibi başlatılırken taranacak dosyayı ayarlamak zorunda kaldım .
<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
. Sonra bu komutu çalıştırarak dosyayı yürütülebilir yapmak zorunda -chmod u+x myShellScript.sh
Son olarak, dosyayı aşağıdaki kod snippet'ini kullanarak yürütebilirim.
public void runScript() {
ProcessBuilder pb = new ProcessBuilder("src/main/resources/myFile.sh");
try {
Process p;
p = pb.start();
} catch (IOException e) {
e.printStackTrace();
}
}
Umarım bu birinin problemini çözer.
linux kullanımı için
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);
}
}
ve kullanım için;
ShellAssistance.runShell("", "pg_dump", new String[]{"-U", "aliAdmin", "-f", "/home/Backup.sql", "StoresAssistanceDB"});
VEYA
ShellAssistance.runShell("", "pg_dump", new String[]{"-U", "aliAdmin", "-f", "/home/Backup.sql", "StoresAssistanceDB"}, new Hashmap<>());