当前位置: 首页 > news >正文

java调用cmdsh命令

Java调用Windows命令

Java调用CMD命令

Java调用CMD命令,轻松实现系统级操作!

java如何执行bat脚本,并监控执行结果

Java中如何执行多条shell/bat命令

Java 执行Shell脚本指令

java调用shell脚本并传递参数

java调用shell并传参

java执行shell/CMD命令

文章目录

  • Java调用CMD命令
      • 一、Java调用CMD命令的基本方法
      • 二、使用Runtime类调用CMD命令
      • 三、使用ProcessBuilder类调用CMD命令
      • 四、解决编码问题的注意事项
      • 五、Java调用CMD命令的实用技巧
  • Java调用CMD命令,轻松实现系统级操作!
    • 详解
    • 注意事项
  • Java调用Windows命令
  • [Java ProcessBuilder examples](https://mkyong.com/java/java-processbuilder-examples/)
    • 1. Ping
    • 2. Ping + Thread
    • 3. Change Directory
  • Java 执行Shell脚本指令
    • 一、介绍
    • 二、调用Shell脚本
      • 1、获取键盘输入
      • 2、构建指令
      • 3、java程序
    • 三、调试心得
      • 1、构建指令不对
      • 2、文件格式不对
    • 四、参考文献
  • 通义灵码
    • Process执行命令如何结束
    • Process执行命令如何正确关闭
    • `cmd /c` 的含义
      • 详细解释
      • 示例
    • 为什么使用 `cmd /c`
      • 总结
      • `"sh", "-c"` 的含义
      • 详细解释
      • 示例
      • 在 Java 中的使用
    • 为什么使用 `"sh", "-c"`
      • 示例代码
      • 解释
  • FFmpegShellUtils
  • ShellUtils

Java调用CMD命令

在Java开发中,有时候需要与操作系统的命令行交互,执行特定的CMD命令或脚本。然而,处理编码问题是调用CMD命令时常遇到的挑战。正确处理编码可以避免输出结果的乱码,确保程序的稳定运行。本文将介绍Java中调用CMD命令的方法,并重点解决编码问题,同时提供一些实用技巧和注意事项。

一、Java调用CMD命令的基本方法

Java通过Runtime类或ProcessBuilder类提供了调用CMD命令的能力。这两个类都允许Java程序启动一个新的进程并执行特定的命令,通过标准输入输出流进行数据交换。Runtime类适用于简单的命令执行,ProcessBuilder类则更加灵活,适用于复杂的命令和参数传递。

二、使用Runtime类调用CMD命令

Runtime类提供了exec()方法来执行CMD命令。该方法接收一个String类型的命令字符串,并返回一个Process对象,通过这个对象可以获取命令执行的结果。

示例代码:

import java.io.*;public class CmdExecutionExample {public static void main(String[] args) {try {// 调用CMD命令String command = "ipconfig";Process process = Runtime.getRuntime().exec(command);// 获取命令输出结果InputStream inputStream = process.getInputStream();BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "GBK")); // 设置编码为GBKString line;while ((line = reader.readLine()) != null) {System.out.println(line);}// 等待命令执行完成process.waitFor();} catch (IOException | InterruptedException e) {e.printStackTrace();}}
}

三、使用ProcessBuilder类调用CMD命令

ProcessBuilder类相比Runtime类更加灵活,可以通过链式调用设置命令和参数,同时还可以设置工作目录、环境变量等。

示例代码:

import java.io.*;public class CmdExecutionExample2 {public static void main(String[] args) {try {// 调用CMD命令ProcessBuilder processBuilder = new ProcessBuilder("cmd.exe", "/c", "ipconfig"); // /c参数表示执行后关闭CMD窗口processBuilder.redirectErrorStream(true); // 将错误输出流与标准输出流合并Process process = processBuilder.start();// 获取命令输出结果InputStream inputStream = process.getInputStream();BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "GBK")); // 设置编码为GBKString line;while ((line = reader.readLine()) != null) {System.out.println(line);}// 等待命令执行完成process.waitFor();} catch (IOException | InterruptedException e) {e.printStackTrace();}}
}

四、解决编码问题的注意事项

  • 输出编码:在调用CMD命令时,应确保输出流的编码与CMD命令输出的编码一致。例如,如果CMD命令输出使用GBK编码,Java程序应使用相同的编码读取输出流。
  • 输入编码:如果Java程序需要传递参数给CMD命令,应该确认参数的编码与CMD命令支持的编码一致,以避免参数乱码。

五、Java调用CMD命令的实用技巧

  • 在Windows系统中,CMD命令通常使用GBK编码输出。因此,在调用CMD命令时,常用的编码为GBK。
  • 使用ProcessBuilder类时,可以通过redirectErrorStream(true)方法将错误输出流与标准输出流合并,方便获取完整的输出信息。
  • 建议使用try-with-resources语句来关闭流资源,确保资源的及时释放。

Java调用CMD命令是实现与操作系统交互的一种重要方式。解决编码问题是调用CMD命令时必须关注的重要问题,通过设置正确的编码,可以避免输出结果的乱码,确保程序的稳定运行。在实际应用中,合理使用Runtime类或ProcessBuilder类,处理编码问题,可以实现更灵活、稳健的CMD命令调用。

Java调用CMD命令,轻松实现系统级操作!

在Java中,你可以使用Runtime.getRuntime().exec()方法来调用系统命令行(cmd)命令。这个方法允许你执行任何外部程序或命令,并可以获取其输出。

下面是一个示例代码,展示如何在Java中调用cmd命令:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;public class CmdExample {public static void main(String[] args) {try {// 构建命令String command = "cmd /c dir"; // 这里以列出当前目录为例// 执行命令Process process = Runtime.getRuntime().exec(command);// 读取命令的输出BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));String line;while ((line = reader.readLine()) != null) {System.out.println(line);}// 等待命令执行完成int exitCode = process.waitFor();System.out.println("Exited with code: " + exitCode);} catch (IOException | InterruptedException e) {e.printStackTrace();}}
}

详解

  1. 构建命令

    • String command = "cmd /c dir";:这里我们使用了Windows的cmd命令行工具,并通过/c参数告诉它执行完命令后关闭。dir是列出当前目录下的文件和文件夹的命令。
  2. 执行命令

    • Process process = Runtime.getRuntime().exec(command);:这行代码通过运行时环境执行指定的命令。返回的Process对象可以用来控制进程和获取其输出。
  3. 读取命令的输出

    • 使用BufferedReader包装InputStreamReader来读取进程的标准输出流(即命令的输出)。
    • 循环读取每一行直到没有更多输出。
  4. 等待命令执行完成

    • int exitCode = process.waitFor();:这会阻塞当前线程直到外部进程结束,并返回进程的退出值。通常,0表示正常退出,非0值表示有错误发生。
  5. 异常处理

    • 捕获并处理IOException(输入输出异常)和InterruptedException(中断异常),这些可能在执行命令或等待过程中抛出。

注意事项

  • 确保传递给exec()方法的命令字符串是正确的,并且考虑到操作系统的差异(例如,上述代码在Windows上运行,而在Linux上可能需要修改命令)。
  • 当处理外部进程时,始终考虑安全性,特别是当命令包含来自用户输入的部分时。
  • 对于更复杂的交互,可能需要使用ProcessBuilder类而不是Runtime.exec(),因为ProcessBuilder提供了更多的配置选项和更好的控制。

Java调用Windows命令

Java调用Windows命令 Java调用Windows命令主要用到两个类: java.lang.Runtime

每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。可以通过 getRuntime 方法获取当前运行时。应用程序不能创建自己的 Runtime 类实例。 java.lang.Process

ProcessBuilder.start() 和 Runtime.exec 方法创建一个本机进程,并返回 Process 子类的一个实例,该实例可用来控制进程并获取相关信息。Process 类提供了执行从进程输入、执行输出到进程、等待进程完成、检查进程的退出状态以及销毁(杀掉)进程的方法。 对于带有 Process 对象的 Java 进程,没有必要异步或并发执行由 Process 对象表示的进程。

package test;import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;/*** Java调用Windows命令测试* @author liuyazhuang**/
public class Test {public static void main(String args[]) {testWinCmd();dirOpt();}public static void testWinCmd() {System.out.println("------------------testWinCmd()--------------------");Runtime runtime = Runtime.getRuntime();System.out.println(runtime.totalMemory());System.out.println(runtime.freeMemory());System.out.println(runtime.maxMemory());System.out.println(runtime.availableProcessors());   //处理器数try {//执行一个exe文件runtime.exec("notepad");runtime.exec("C:\\Program Files\\Microsoft Office\\OFFICE11\\winword.exe c:\\test.doc");//执行批处理runtime.exec("c:\\x.bat");//执行系统命令runtime.exec("cmd /c dir ");runtime.exec("cmd /c dir c:\\");//            //-------------- 文件操作 --------------runtime.exec("cmd /c copy c:\\x.bat d:\\x.txt");   //copy并改名runtime.exec("cmd /c rename d:\\x.txt x.txt.bak"); //重命名runtime.exec("cmd /c move d:\\x.txt.bak c:\\");    //移动runtime.exec("cmd /c del c:\\x.txt.bak");          //删除//-------------- 目录操作 --------------runtime.exec("cmd /c md c:\\_test");          //删除} catch (IOException e) {e.printStackTrace();}} /*** 执行批处理文件,并获取输出流重新输出到控制台*/public static void dirOpt() {System.out.println("------------------dirOpt()--------------------");Process process;try {//执行命令process = Runtime.getRuntime().exec("c:\\x.bat");//取得命令结果的输出流InputStream fis = process.getInputStream();//用一个读输出流类去读BufferedReader br = new BufferedReader(new InputStreamReader(fis));String line = null;//逐行读取输出到控制台while ((line = br.readLine()) != null) {System.out.println(line);}} catch (IOException e) {e.printStackTrace();}}
}

Java ProcessBuilder examples

In Java, we can use ProcessBuilder to call external commands easily :

ProcessBuilder processBuilder = new ProcessBuilder();// -- Linux --// Run a shell command
processBuilder.command("bash", "-c", "ls /home/mkyong/");// Run a shell script
processBuilder.command("path/to/hello.sh");// -- Windows --// Run a command
processBuilder.command("cmd.exe", "/c", "dir C:\\Users\\mkyong");// Run a bat file
processBuilder.command("C:\\Users\\mkyong\\hello.bat");Process process = processBuilder.start();

1. Ping

1.1 Run an external ping command to ping a website 3 times, and display the output.

package com.mkyong.process;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;public class ProcessBuilderExample1 {public static void main(String[] args) {ProcessBuilder processBuilder = new ProcessBuilder();// Run this on Windows, cmd, /c = terminate after this runprocessBuilder.command("cmd.exe", "/c", "ping -n 3 google.com");try {Process process = processBuilder.start();// blocked :(BufferedReader reader =new BufferedReader(new InputStreamReader(process.getInputStream()));String line;while ((line = reader.readLine()) != null) {System.out.println(line);}int exitCode = process.waitFor();System.out.println("\nExited with error code : " + exitCode);} catch (IOException e) {e.printStackTrace();} catch (InterruptedException e) {e.printStackTrace();}}}

Output

Pinging google.com [172.217.166.142] with 32 bytes of data:
Reply from 172.217.166.142: bytes=32 time=10ms TTL=55
Reply from 172.217.166.142: bytes=32 time=10ms TTL=55
Reply from 172.217.166.142: bytes=32 time=10ms TTL=55Ping statistics for 172.217.166.142:Packets: Sent = 3, Received = 3, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:Minimum = 10ms, Maximum = 10ms, Average = 10msExited with error code : 0

2. Ping + Thread

In above example 1.1, the process.getInputStream is “blocking”, it is better to start a new Thread for the reading process, so that it won’t block other tasks.

package com.mkyong.process;import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;public class ProcessBuilderExample2 {public static void main(String[] args) {ExecutorService pool = Executors.newSingleThreadExecutor();ProcessBuilder processBuilder = new ProcessBuilder();// Run this on Windows, cmd, /c = terminate after this runprocessBuilder.command("cmd.exe", "/c", "ping -n 3 google.com");try {Process process = processBuilder.start();System.out.println("process ping...");ProcessReadTask task = new ProcessReadTask(process.getInputStream());Future<list<string>> future = pool.submit(task);// no block, can do other tasks hereSystem.out.println("process task1...");System.out.println("process task2...");List<string> result = future.get(5, TimeUnit.SECONDS);for (String s : result) {System.out.println(s);}} catch (Exception e) {e.printStackTrace();} finally {pool.shutdown();}}private static class ProcessReadTask implements Callable<list<string>> {private InputStream inputStream;public ProcessReadTask(InputStream inputStream) {this.inputStream = inputStream;}@Overridepublic List<string> call() {return new BufferedReader(new InputStreamReader(inputStream)).lines().collect(Collectors.toList());}}}

Output

process ping...
process task1...
process task2...Pinging google.com [172.217.166.142] with 32 bytes of data:
Reply from 172.217.166.142: bytes=32 time=11ms TTL=55
Reply from 172.217.166.142: bytes=32 time=10ms TTL=55
Reply from 172.217.166.142: bytes=32 time=10ms TTL=55Ping statistics for 172.217.166.142:Packets: Sent = 3, Received = 3, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:Minimum = 10ms, Maximum = 11ms, Average = 10ms

3. Change Directory

3.1 Change to directory C:\\users and run external dir command to list out all the files.

package com.mkyong.process;import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;public class ProcessBuilderExample3 {public static void main(String[] args) {ProcessBuilder processBuilder = new ProcessBuilder();processBuilder.command("cmd.exe", "/c", "dir");processBuilder.directory(new File("C:\\users"));// can also run the java file like this// processBuilder.command("java", "Hello");try {Process process = processBuilder.start();BufferedReader reader =new BufferedReader(new InputStreamReader(process.getInputStream()));String line;while ((line = reader.readLine()) != null) {System.out.println(line);}int exitCode = process.waitFor();System.out.println("\nExited with error code : " + exitCode);} catch (IOException e) {e.printStackTrace();} catch (InterruptedException e) {e.printStackTrace();}}}

Output

 Volume in drive C has no label.Volume Serial Number is CE5B-B4C5Directory of C:\users//...

Java 执行Shell脚本指令

一、介绍

有时候我们在Linux中运行Java程序时,需要调用一些Shell命令和脚本。而Runtime.getRuntime().exec()方法给我们提供了这个功能,而且Runtime.getRuntime()给我们提供了以下几种exec()方法:

Process exec(String command)   
在单独的进程中执行指定的字符串命令。   Process exec(String[] cmdarray)   
在单独的进程中执行指定命令和变量。   Process exec(String[] cmdarray, String[] envp)   
在指定环境的独立进程中执行指定命令和变量。   Process exec(String[] cmdarray, String[] envp, File dir)   
在指定环境和工作目录的独立进程中执行指定的命令和变量。   Process exec(String command, String[] envp)   
在指定环境的单独进程中执行指定的字符串命令。   Process exec(String command, String[] envp, File dir)   
在有指定环境和工作目录的独立进程中执行指定的字符串命令。

其中,其实cmdarray和command差不多,同时如果参数中如果没有envp参数或设为null,表示调用命令将在当前程序执行的环境中执行;如果没有dir参数或设为null,表示调用命令将在当前程序执行的目录中执行,因此调用到其他目录中的文件和脚本最好使用绝对路径。各个参数的含义:

  1. cmdarray: 包含所调用命令及其参数的数组。
  2. command: 一条指定的系统命令。
  3. envp: 字符串数组,其中每个元素的环境变量的设置格式为name=value;如果子进程应该继承当前进程的环境,则该参数为 null。
  4. dir: 子进程的工作目录;如果子进程应该继承当前进程的工作目录,则该参数为 null。

细心的读者会发现,为了执行调用操作,JVM会启一个Process,所以我们可以通过调用Process类的以下方法,得知调用操作是否正确执行:

abstract  int waitFor()   
导致当前线程等待,如有必要,一直要等到由该 Process 对象表示的进程已经终止。

二、调用Shell脚本

1、获取键盘输入

BufferedReader reader = null;try{reader \= new BufferedReader(new InputStreamReader(System.in));System.out.println("请输入IP:");String ip \= reader.readLine();

上述指令基本很常见:

1、创建读入器:BufferReader

2、将数据流载入BufferReader,即InputStreamReader

3、将系统输入载入InputStreamReader中

4、然后利用reader获取数据。

2、构建指令

shell运行脚本指令为 sh **.sh args,其实这个格式与java格式相同。

我的脚本为:

#!/bin/sh
#根据进程名杀死进程
echo "This is a $call"
if [ $# -lt 2 ]
thenecho "缺少参数:procedure_name和ip"exit 1
fiecho "Kill the $1 process"
PROCESS=`ps -ef|grep $1|grep $2|grep -v grep|grep -v PPID|awk '{ print $2}'`
for i in $PROCESS
doecho "Kill the $1 process [ $i ]" 
done

其实所有准备若当,就是无法读取里面的数据,执行shell指令,原因就是:

注意事项:

1.shell脚本必须有执行权限,比如部署后chmod -R 777 /webapps

2.shell文件,必须是UNIX格式,ANSI编码格式,否则容易出问题(可以用notepad++,编辑->文档格式转换,格式->转为ANSI格式(UNIX格式)

3、java程序

/*** @author :dongbl* @version :* @Description:* @date :9:19 2017/11/14*/
public class TestBash {public static void main(String [] args){BufferedReader reader = null;try{reader = new BufferedReader(new InputStreamReader(System.in));System.out.println("请输入IP:");String ip = reader.readLine();String bashCommand = "sh "+ "/usr/local/java/jdk1.8.0_121/lib/stopffmpeg.sh" + " ffmpeg " + ip;
//            String bashCommand = "chmod 777 " + "/usr/local/java/jdk1.8.0_121/lib/stopffmpeg.sh" ;
//            String bashCommand = "kill -9" + ip;System.out.println(bashCommand);Runtime runtime = Runtime.getRuntime();Process pro = runtime.exec(bashCommand);int status = pro.waitFor();if (status != 0){System.out.println("Failed to call shell's command ");}BufferedReader br = new BufferedReader(new InputStreamReader(pro.getInputStream()));StringBuffer strbr = new StringBuffer();String line;            while ((line = br.readLine())!= null){                strbr.append(line).append("\n");}String result = strbr.toString();System.out.println(result);}catch (IOException ec){ec.printStackTrace();}catch (InterruptedException ex){ex.printStackTrace();}}
}

其中文件路径为绝对路径,这点需要注意。

三、调试心得

在调试shell脚本执行过程中,反了几个错

1、构建指令不对

1、开始指令为:

 String bashCommand = "/usr/local/java/jdk1.8.0\_121/lib/stopffmpeg.sh "+ " ffmpeg " + ip;
程序报错,权限不足。
2、此时修改为:
String bashCommand = "chmod 777 "+"/usr/local/java/jdk1.8.0\_121/lib/stopffmpeg.sh "+ " ffmpeg " + ip;

记住一定注意空格(格式)但此时依然无法指定脚本指令。3、在发现格式不对后,修改后,还是不行,此时指令为:

String bashCommand = "sh "+ "/usr/local/java/jdk1.8.0\_121/lib/stopffmpeg.sh" + " ffmpeg " + ip;

2、文件格式不对

这是无法读取内容的关键原因,因为sh文件是在Windows系统下生成的,所以需要将格式修改为linux格式的,即(UNIX格式)

此时网上程序可以了,然后看到指令不同,修改指令即可以了。

最后终于调通了,看来格式经验不足啊

四、参考文献

1、java调用shell脚本并传递参数

2、JAVA调用Shell脚本

转载于:https://www.cnblogs.com/polly333/p/7832540.html

本文转自 https://blog.csdn.net/weixin_30892889/article/details/97217607,如有侵权,请联系删除。

通义灵码

Process执行命令如何结束

在 Java 中使用 Process 执行外部命令时,可以通过以下几种方法来结束进程:
1、调用 Process.destroy() 方法

  • 这个方法会强制终止进程。适用于需要立即停止进程的情况。

2、调用 Process.destroyForcibly() 方法:

  • 这个方法会尝试更加强制地终止进程。通常在 destroy() 方法无效时使用。

3、等待进程自然结束: 使用 Process.waitFor() 方法等待进程自然结束。

  • 这个方法会阻塞当前线程,直到进程结束。

4、读取进程的输出流和错误流:

  • 确保进程的输出流和错误流被正确读取,否则进程可能会因为缓冲区满而挂起。
import java.io.BufferedReader;
import java.io.InputStreamReader;public class ProcessExample {public static void main(String[] args) {try {// 创建进程Process process = Runtime.getRuntime().exec("your-command-here");// 读取进程的输出流和错误流StreamGobbler outputGobbler = new StreamGobbler(process.getInputStream(), "OUTPUT");StreamGobbler errorGobbler = new StreamGobbler(process.getErrorStream(), "ERROR");outputGobbler.start();errorGobbler.start();// 等待进程结束int exitCode = process.waitFor();System.out.println("Process exited with code: " + exitCode);// 如果需要强制终止进程// process.destroy();// process.destroyForcibly();} catch (Exception e) {e.printStackTrace();}}
}class StreamGobbler extends Thread {private InputStream inputStream;private String type;public StreamGobbler(InputStream inputStream, String type) {this.inputStream = inputStream;this.type = type;}@Overridepublic void run() {try {BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));String line;while ((line = reader.readLine()) != null) {System.out.println(type + ": " + line);}} catch (IOException e) {e.printStackTrace();}}
}

Process执行命令如何正确关闭

在 Java 中使用 Process 执行外部命令时,正确关闭进程非常重要,以确保资源被释放并且不会留下僵尸进程。以下是一些最佳实践和步骤,确保 Process 被正确关闭:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;public class ShellUtils {public static void executeCommand(String command) {Process process = null;try {// 创建进程process = Runtime.getRuntime().exec(command);// 读取进程的输出流和错误流StreamGobbler outputGobbler = new StreamGobbler(process.getInputStream(), "OUTPUT");StreamGobbler errorGobbler = new StreamGobbler(process.getErrorStream(), "ERROR");outputGobbler.start();errorGobbler.start();// 等待进程结束int exitCode = process.waitFor();System.out.println("Process exited with code: " + exitCode);} catch (Exception e) {e.printStackTrace();} finally {// 尝试终止进程if (process != null) {if (process.isAlive()) {process.destroy();if (process.isAlive()) {process.destroyForcibly();}}// 如果仍然无法终止,使用操作系统的命令if (process.isAlive()) {terminateProcessGroup(process);}}}}private static void terminateProcessGroup(Process process) {try {// 获取进程的 PIDString pid = getProcessId(process);if (pid != null) {// 终止进程组String osName = System.getProperty("os.name").toLowerCase();if (osName.contains("windows")) {// Windows 系统Runtime.getRuntime().exec("taskkill /F /T /PID " + pid);} else {// Unix 系统Runtime.getRuntime().exec("kill -9 -" + pid);}}} catch (IOException e) {e.printStackTrace();}}private static String getProcessId(Process process) {try {Field field = process.getClass().getDeclaredField("pid");field.setAccessible(true);return field.get(process).toString();} catch (NoSuchFieldException | IllegalAccessException e) {e.printStackTrace();}return null;}
}class StreamGobbler extends Thread {private InputStream inputStream;private String type;public StreamGobbler(InputStream inputStream, String type) {this.inputStream = inputStream;this.type = type;}@Overridepublic void run() {try {BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));String line;while ((line = reader.readLine()) != null) {System.out.println(type + ": " + line);}} catch (IOException e) {e.printStackTrace();} finally {try {inputStream.close();} catch (IOException e) {e.printStackTrace();}}}
}

cmd /c 的含义

cmd /c 是 Windows 命令行中的一个选项,用于执行指定的命令并立即返回控制权。具体来说:

  • cmd:启动 Windows 命令解释器(命令提示符)。
  • /c:表示执行指定的命令后立即退出命令提示符。

详细解释

  1. cmd

    • 启动 Windows 命令提示符(Command Prompt)。
    • 这是一个命令行解释器,用于执行各种命令和脚本。
  2. /c

    • 指定命令提示符在执行完指定的命令后立即退出。
    • 语法格式为 cmd /c <command>,其中 <command> 是你希望执行的具体命令。

示例

假设你有一个命令 dir,用于列出当前目录下的文件和文件夹。你可以使用 cmd /c dir 来执行这个命令:

cmd /c dir

这条命令会启动命令提示符,执行 dir 命令,然后立即退出命令提示符。

为什么使用 cmd /c

  1. 命令组合

    • 有时需要组合多个命令或使用命令行的特殊功能(如管道、重定向等),cmd /c 可以帮助实现这一点。
  2. 兼容性

    • 在某些情况下,直接执行某些命令可能会遇到路径或环境变量的问题,使用 cmd /c 可以确保命令在正确的环境中执行。
  3. 立即退出

    • 使用 /c 选项可以确保命令执行完毕后立即退出命令提示符,不会阻塞当前的 Java 进程。

总结

cmd /c 是一个非常有用的命令行选项,特别是在需要执行复杂命令或组合命令时。在你的代码中,它确保 ffmpeg 命令在一个独立的命令提示符窗口中运行,并且在命令执行完毕后立即退出,不会阻塞当前的 Java 进程。

"sh", "-c" 的含义

"sh", "-c" 是在 Unix/Linux 系统中用于启动 shell 并执行指定命令的参数。具体来说:

  • sh:启动 Bourne shell(或兼容的 shell,如 Bash)。
  • -c:表示执行指定的命令字符串,然后退出 shell。

详细解释

  1. sh

    • sh 是 Unix/Linux 系统中的一个命令行解释器,通常指的是 Bourne shell(Bourne shell 的文件通常是 /bin/sh)。
    • 它可以执行脚本文件或命令行中的命令。
  2. -c

    • -csh 的一个选项,表示从命令行参数中读取命令字符串并执行。
    • 语法格式为 sh -c <command>,其中 <command> 是你希望执行的具体命令。

示例

假设你有一个命令 ls,用于列出当前目录下的文件和文件夹。你可以使用 sh -c ls 来执行这个命令:

sh -c "ls"

这条命令会启动一个 shell,执行 ls 命令,然后退出 shell。

在 Java 中的使用

在你的代码中,"sh", "-c" 用于启动 shell 并执行指定的命令。这样可以确保命令在 shell 环境中正确解析和执行,特别是当命令包含特殊字符或需要环境变量时。

String[] commandList = new String[]{"sh", "-c", "your-command-here"};

为什么使用 "sh", "-c"

  1. 命令组合

    • 有时需要组合多个命令或使用 shell 的特殊功能(如管道、重定向等),sh -c 可以帮助实现这一点。
  2. 环境变量

    • 使用 sh -c 可以确保命令在正确的 shell 环境中执行,包括环境变量的设置。
  3. 立即退出

    • 使用 -c 选项可以确保命令执行完毕后立即退出 shell,不会阻塞当前的 Java 进程。

示例代码

以下是一个示例,展示了如何在 Java 中使用 "sh", "-c" 来执行命令:

import java.io.BufferedReader;
import java.io.InputStreamReader;public class CmdExecutionExample2 {public static void main(String[] args) {String[] commandList = new String[]{"sh", "-c", "ls"};try {Process process = new ProcessBuilder(commandList).start();// 读取进程的输出流和错误流StreamGobbler stdout = new StreamGobbler(process.getInputStream(), "stdout");StreamGobbler errout = new StreamGobbler(process.getErrorStream(), "errout");stdout.start();errout.start();// 等待进程结束int exitCode = process.waitFor();System.out.println("退出码: " + exitCode);} catch (Exception e) {e.printStackTrace();}}static class StreamGobbler extends Thread {private InputStream inputStream;private String type;public StreamGobbler(InputStream inputStream, String type) {this.inputStream = inputStream;this.type = type;}@Overridepublic void run() {try {BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));String line;while ((line = reader.readLine()) != null) {System.out.println(type + ": " + line);}} catch (IOException e) {e.printStackTrace();} finally {try {inputStream.close();} catch (IOException e) {e.printStackTrace();}}}}
}

解释

  1. 创建进程
    使用 ProcessBuilder 创建一个进程,命令列表为 {"sh", "-c", "ls"}

  2. 读取输出流和错误流
    使用 StreamGobbler 类分别读取进程的输出流和错误流,确保缓冲区不会满。

  3. 等待进程结束
    使用 process.waitFor() 等待进程自然结束,并获取退出码。

通过这些步骤,可以确保命令在 shell 环境中正确执行,并且进程的输出和错误流被正确读取。

FFmpegShellUtils

public class FFmpegShellUtils {// 测试时可以配合命令: tasklist|findstr "ffmpeg", taskkill /f /pid <ffmpeg进程id> , obs拉流 一起观察这个现象public static void main(String[] args) {//  报错: Cannot run program "...": CreateProcess error=2, 系统找不到指定的文件// String[] commandList = new String[]{"ffmpeg -f gdigrab -i desktop -vcodec libx264 -f flv rtmp://192.168.134.3:8002/flv/test"};// 这样写15s后无法结束ffmpeg进程// String[] commandList = new String[]{"cmd", "/c" , "ffmpeg -f gdigrab -i desktop -vcodec libx264 -f flv rtmp://192.168.134.3:8002/flv/test"};// 这样写15s后无法结束ffmpeg进程// String[] commandList = new String[]{"cmd", "/c" , "ffmpeg", "-f", "gdigrab", "-i", "desktop", "-vcodec", "libx264", "-f", "flv", "rtmp://192.168.134.3:8002/flv/test"};// 这样写只是输出了ffmpeg的版本号// String[] commandList = new String[]{"ffmpeg", " -f gdigrab -i desktop -vcodec libx264 -f flv rtmp://192.168.134.3:8002/flv/test"};// 这样可以正常启动ffmpeg, 并在15s后关闭退出String[] commandList = new String[]{"ffmpeg", "-f", "gdigrab", "-i", "desktop", "-vcodec", "libx264", "-f", "flv", "rtmp://192.168.134.3:8002/flv/test"};ProcessBuilder processBuilder = new ProcessBuilder(commandList);try {Process process = processBuilder.start();// 需要命令的输出内容读取出来, 否则进程可能会因为缓冲区满而挂起StreamGobbler stdout = new StreamGobbler(process.getInputStream(), "stdout");StreamGobbler errout = new StreamGobbler(process.getErrorStream(), "errout");stdout.start();errout.start();/*new Thread(() -> {try {System.out.println("开始sleeping");TimeUnit.SECONDS.sleep(15);System.out.println("结束sleeping");System.out.println("开始关闭" + process.isAlive());process.getOutputStream().close();process.destroy();// process.destroyForcibly();System.out.println("关闭成功" + process.isAlive());} catch (InterruptedException | IOException e) {e.printStackTrace();}}).start();*/// 可以在此处等待process结束, 但是需要先开启上面这个线程来结束process, 就可以结束ffmpeg/*int exitCode = process.waitFor();System.out.println("退出码: "+ exitCode);*/System.out.println("开始sleeping");TimeUnit.SECONDS.sleep(15);System.out.println("结束sleeping");System.out.println("开始关闭" + process.isAlive());process.getOutputStream().close();process.destroy();// process.destroyForcibly();System.out.println("关闭成功" + process.isAlive());process = null;LockSupport.park();} catch (IOException | InterruptedException e) {e.printStackTrace();}}}

ShellUtils

public class ShellUtils {public static void main(String[] args) {//=====windows=====// 输出ip地址// ShellUtils.exec("ipconfig");// 弹出记事本, 关闭弹出的记事本, 这个命令才会结束// ShellUtils.exec("notepad");// 弹出记事本, 关闭弹出的记事本, 这个命令才会结束// ShellUtils.exec("cmd", "/c", "notepad");// Cannot run program "dir": CreateProcess error=2, 系统找不到指定的文件// ShellUtils.exec("dir");// 输出目录// ShellUtils.exec("cmd", "/c", "dir");// 输出ip地址// ShellUtils.exec("cmd", "/c", "ipconfig");// ShellUtils.exec("cmd", "/c", "ping www.baidu.com");// 运行ffmpeg// ShellUtils.exec("ffmpeg", "-f", "gdigrab", "-i", "desktop", "-vcodec", "libx264", "-f", "flv", "rtmp://192.168.134.3:8002/flv/test");// =====linux=====// 可以通过ProcessBuilder设置工作目录ShellUtils.exec("sh", "-c", "ls");}public static String exec(String... commandList) {ProcessBuilder processBuilder = new ProcessBuilder(commandList);try {System.out.println("准备执行命令: " + String.join(" ", commandList));// 创建进程Process process = processBuilder.start();// 读取进程的输出流和错误流StreamGobbler stdout = new StreamGobbler(process.getInputStream(), "stdout");StreamGobbler errout = new StreamGobbler(process.getErrorStream(), "errout");System.out.println("准备输出");stdout.start();errout.start();System.out.println("开始等待结果");// 等待进程结束int exitCode = process.waitFor();System.out.println("执行结果:" + exitCode);// 关闭输入流process.getOutputStream().close();stdout.join();errout.join();System.out.println("输出完毕");if (exitCode == 0) {System.out.println("执行成功");return stdout.output.toString();} else {System.out.println("执行失败");return errout.output.toString();}} catch (IOException | InterruptedException e) {e.printStackTrace();throw new RuntimeException("运行发生错误");}}}
public class StreamGobbler extends Thread {// 获取是否为windows系统private static boolean isWindows = System.getProperty("os.name").toLowerCase().contains("windows");private InputStream inputStream;private String type;StringBuilder output = new StringBuilder();public StreamGobbler(InputStream inputStream, String type) {this.inputStream = inputStream;this.type = type;}@Overridepublic void run() {try {System.out.println(Thread.currentThread().getName() + "-进入输出, type=" + type);String charset = isWindows ? "GBK" : "UTF-8";BufferedReader br =  new BufferedReader(new InputStreamReader(inputStream, charset));String line = null;while ((line = br.readLine()) != null) {System.out.println(Thread.currentThread().getName() + "-线程输出, type=" + type + ", line=>" + line);output.append(line);output.append(System.lineSeparator());TimeUnit.MILLISECONDS.sleep(100);}System.out.println(Thread.currentThread().getName() + "-线程输出结束, type=" + type);} catch (IOException | InterruptedException e) {e.printStackTrace();} finally {try {inputStream.close();} catch (IOException e) {System.out.println(Thread.currentThread().getName() + "-关闭流发生错误, type=" + type);e.printStackTrace();}}}
}

http://www.mrgr.cn/news/79126.html

相关文章:

  • 流媒体之linux下离线部署FFmpeg 和 SRS
  • MongoDB集群的介绍与搭建
  • 【测试工具JMeter篇】JMeter性能测试入门级教程(七):JMeter断言
  • pset2 substitution.c
  • Linux内核__setup 宏的作用及分析
  • [go-redis]客户端的创建与配置说明
  • ansible自动化运维(二)ad-hoc模式
  • 网络层总结
  • 基于TensorFlow框架的线性回归实现
  • AI处理器组合--华为OD机试2024年E卷
  • 两个畸变矩阵相乘后还是一个2*2的矩阵,有四个畸变元素。1、畸变矩阵吸收了法拉第矩阵。2、畸变矩阵也给法拉第旋转角带来模糊(求解有多种可能)
  • Scala:正则表达式
  • Transformers在计算机视觉领域中的应用【第3篇:Swin Transformer——多层次的Vision Transformer】
  • 快速上手 RabbitMQ:使用 Docker 轻松搭建消息队列系统
  • JS中的浅拷贝,深拷贝和引用
  • 【JuMP.jl】非线性规划
  • 项目开发之Jenkins
  • React第十二节组件之间通讯之发布订阅模式(使用pubsub-js插件)
  • FFmpeg:强大的音视频处理工具指南
  • 鸿蒙 Next 可兼容运行 Android App,还支持出海 GMS?