ffmpeg 集成的时候封装了一个java调用shell的工具类
依赖
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-exec</artifactId>
<version>1.3</version>
</dependency>
代码
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.exec.*;
import org.apache.commons.lang3.exception.ExceptionUtils;
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@Slf4j
public class CommandUtils {
private static final String DEFAULT_CHARSET = "UTF-8";
private static final Long TIMEOUT = 1000L * 60;
static {
log.info("[------当前shell路径[{}]------]", exeCommand("pwd"));
}
public synchronized static String exeCommand(String command) throws RuntimeException {
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
int exitCode = exeCommand(command, out);
if (exitCode == 0) {
log.info("[{}]-命令运行成功,耗时[{}]", command, System.currentTimeMillis());
} else {
log.info("[{}]-命令运行失败,耗时[{}]", command, System.currentTimeMillis());
}
return out.toString(DEFAULT_CHARSET);
} catch (Exception e) {
log.info(ExceptionUtils.getStackTrace(e));
throw new RuntimeException(ExceptionUtils.getStackTrace(e));
}
}
public synchronized static int exeCommand(String command, OutputStream out) throws IOException {
log.info("[shell]-[{}]", command);
String[] shellDesc = command.split(" ");
CommandLine commandLine = CommandLine.parse(command);
if (shellDesc.length > 1) {
commandLine = new CommandLine(shellDesc[0]);
for (int i = 1; i < shellDesc.length; i++) {
commandLine.addArgument(shellDesc[i]);
}
}
PumpStreamHandler pumpStreamHandler = null;
if (null == out) {
pumpStreamHandler = new PumpStreamHandler();
} else {
pumpStreamHandler = new PumpStreamHandler(out);
}
// ExecuteWatchdog.INFINITE_TIMEOUT
ExecuteWatchdog watchdog = new ExecuteWatchdog(TIMEOUT);
DefaultExecutor executor = new DefaultExecutor();
executor.setStreamHandler(pumpStreamHandler);
executor.setWatchdog(watchdog);
return executor.execute(commandLine);
}
public static List<String> getShellResultLines(String result) {
if (result != null) {
log.info("[getShellResultLines]-[{}]", result);
result = result.replaceAll("\\r\\n", "\\n ");
log.info("[getShellResultLines]-[{}]", result);
String[] resultLines = result.split("\\n");
return Arrays.asList(resultLines);
}
return Collections.emptyList();
}}
常见问题
commons-exec,在执行的时候会返回一些自定义错误码,比如143。但是在shell中所有非0的错误码,都是没有意义的。
所以可以根据日志手动执行一遍shell命令,来判断错误原因。
博主列出经常碰到的不同错误码原因
- shell命令参数中带有复杂的参数,例如url,请参考使用 commandLine.addArgument(shellDesc[i]) 的方式添加参数。
- 执行shell命令,是否是在 bin/ 下
- 在shell命令中,是否存在需要权限的指令,比如 mkdir
- 执行命令中是否超时,上面的代码设置的是60超时,不确定时间的情况可以尝试 ExecuteWatchdog.INFINITE_TIMEOUT 无穷大设置。