Java-执行sh文件脚本-cmd命令-查找并复制so库文件到jdk库文件夹-复制sh脚本文件到当前jar包路径-判断指定目录下是否有某个文件
注意:相对项目有新增,下次不可以直接全部复制
package cn.jiangjiesheng.fst.service.impl;
import cn.jiangjiesheng.fst.config.BizzConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
/**
* 1、命令行重启 libreoffice
* 2、复制jpeg,so到jdk库文件路径
*
* https://blog.51cto.com/stefanxfy/5083542
* https://blog.csdn.net/m0_37298500/article/details/125780155
*
* 执行cmd命令的示例:
* 1、killAndDeleteLibreOfficeTmp()
* 2、if(isLinuxOS()){
* Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", "chmod +x " + file.getAbsolutePath()}).waitFor();
* }
*
* 关键方法:
* 1、killAndDeleteLibreOfficeTmp 执行sh文件脚本
* 2、justRestartLibreOffice 执行cmd命令
* 3、writeJpegSoToLibAmd64Path 往jdk的库文件安装路径复制jpeg.so
* 4、writeCloseLibreOfficeShell 往jar包(idea环境是项目代码的目录)所在目录复制脚本
* 5、getCloseLibreOfficePath 往jar包(idea环境是项目代码的目录)所在目录路径
* 6、isLinuxOS 是否是linux系统
* 7、getJavaInstallLibAmd64Path 获取jdk的库文件安装路径
* 8、hasFile 判断指定目录下是否有某个文件(注意目录使用File.separatorChar处理过)
*
* 更多文件类操作见《Java-JFileUtil-文件类操作-创建多级目录-创建临时文件-查找临时文件夹路径-删除指定关键字的文件》
*/
@Service("fstStatusCheckService")
@Slf4j
@Order(value = 1)
public class FstStatusCheckService {
private static boolean hasWriteJpegSoToLibAmd64Path = false;
@Value(value = "${jodconverter.local.office-home}")
private String officeHome;
@Value("#{'${jodconverter.local.portNumbers:2002,2003}'.split(',')}")
private List<Integer> portNumbers;
@Autowired
private BizzConfig bizzConfig;
//这些批量再通过 justRestartLibreOffice 实现不知道行不行,以后可以尝试,目前是killAndDeleteLibreOfficeTmp这个方法执行的
private static List<String> RESTART_LIBRE_OFFICE_CMD_4_LINUX = new ArrayList<String>() {
{
add("kill -9 `ps -ef|grep libreoffice|grep -v grep|awk '{print $2}'`");
add("rm -rf /tmp/.jodconverter*");
add("kill -9 `ps -ef|grep libreoffice|grep -v grep|awk '{print $2}'`");
}
};
/**
* killAndDeleteLibreOfficeTmp 弃用
* 先关闭再重启[justRestartLibreOffice 启动进程后也不能使用]
*
* 最终使用以下方法控制关闭和启动
* OfficeConverter.closeLibreOffice();
*
* if(!officeManager.isRunning()){
* this.init();
* }
*
* 这里只关 进程,和rm tmp下的文件,justRestartLibreOffice 注释掉
* 每次定时任务完成后并在下次任务开始前执行,见 convertThreadEntry() # needRestartLibreOfficeAfterThisScheduleTask
* 定时任务执行过程过如果出现转码失败,也会立即执行
*
*/
public void killAndDeleteLibreOfficeTmp(boolean checkConfigSwitch) {
if(!bizzConfig.getEnableKillAndDeleteLibreOfficeTmp()){
log.info("FstStatusCheckService#不执行kill libreOffice进程脚本,enable.killAndDeleteLibreOfficeTmp={}",bizzConfig.getEnableKillAndDeleteLibreOfficeTmp());
return;
}
//记录下,fstStatusCheckService.killAndDeleteLibreOfficeTmp(true);执行时,这个判断条件不满足而放行时,转码服务稳定。
//也就是如果当前版本有问题,可以把enable.KillAndDeleteLibreOfficeTmpAfterThisScheduleTask改成true,每轮有文档的定时任务都会执行这个kill和rm的脚本,会有一些日志。
if(checkConfigSwitch && !bizzConfig.getEnableKillAndDeleteLibreOfficeTmpAfterThisScheduleTask()){
log.info("FstStatusCheckService#不执行kill libreOffice进程脚本,enable.killAndDeleteLibreOfficeTmpAfterThisScheduleTask={}",bizzConfig.getEnableKillAndDeleteLibreOfficeTmpAfterThisScheduleTask());
return;
}
log.info("FstStatusCheckService#即将执行kill libreOffice进程脚本");
if (isLinuxOS()) {
//https://blog.csdn.net/m0_37298500/article/details/125780155
try{
String targetFilePath = getCloseLibreOfficePath();
Process process = Runtime.getRuntime().exec("sh "+targetFilePath);
InputStreamReader ips = new InputStreamReader(process.getInputStream());
BufferedReader br = new BufferedReader(ips);
String line;
while ((line = br.readLine()) != null) {
// 这个返回值对命令执行,不知道是不是也很关键
log.info("FstStatusCheckService#执行kill libreOffice进程脚本文件:{},返回值:{}", targetFilePath, line);
}
} catch (Exception e) {
log.warn("FstStatusCheckService#即将执行kill libreOffice进程脚本出现异常:{}", e);
}
// justRestartLibreOffice();
} else {
log.info("FstStatusCheckService#当前非linux环境,不即将执行kill libreOffice进程脚本");
}
}
/**
* 重启libreOffice [命令可以生效,进程可以生成,但是进程仍然不工作]
* 关键词 端口 8100
*/
@Deprecated
public void justRestartLibreOffice(){
// 这个之前的8100的端口的,不行
// nohup /opt/libreoffice6.4/program/soffice --headless --accept="socket,host=127.0.0.1,port=22413;urp;" --nofirststartwizard &
// fst 自己启动的是这样的,
// nohup /opt/libreoffice6.4/program/soffice.bin --accept=socket,host=127.0.0.1,port=22412,tcpNoDelay=1;urp;StarOffice.ServiceManager --headless --invisible --nocrashreport --nodefault --nofirststartwizard --nolockcheck --nologo --norestore -env:UserInstallation=file:///tmp/.jodconverter_socket_host-127.0.0.1_port-22412_tcpNoDelay-1 &
//需要加""
// nohup /opt/libreoffice6.4/program/soffice --accept="socket,host=127.0.0.1,port=22412,tcpNoDelay=1;urp;StarOffice.ServiceManager" --headless --invisible --nocrashreport --nodefault --nofirststartwizard --nolockcheck --nologo --norestore -env:UserInstallation=file:///tmp/.jodconverter_socket_host-127.0.0.1_port-22412_tcpNoDelay-1 &
log.info("FstStatusCheckService#即将执行startlibreOffice进程脚本开始");
if(!officeHome.endsWith("/")){
officeHome = officeHome+"/";
}
for (Integer portNumber : portNumbers) {
// String cmd = "nohup "+ officeHome + "program/soffice --headless --accept=\"socket,host=127.0.0.1,port=" + portNumber + ";urp;\" --nofirststartwizard &";
String cmd = "nohup "+ officeHome + "program/soffice --headless --accept=\"socket,host=127.0.0.1,port=" + portNumber + ",tcpNoDelay=1;urp;StarOffice.ServiceManager\" --headless --invisible --nocrashreport --nodefault --nofirststartwizard --nolockcheck --nologo --norestore -env:UserInstallation=file:///tmp/.jodconverter_socket_host-127.0.0.1_port-"+portNumber+"_tcpNoDelay-1 &";
try {
int execValue = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", cmd}).waitFor();
log.info("FstStatusCheckService#执行startlibreOffice进程脚本完成: cmd:{},返回值execValue:{}", cmd, execValue);
} catch (Exception e) {
log.info("FstStatusCheckService#执行startlibreOffice进程脚本出现异常,cmd:{},异常:{}", cmd, e);
}
}
}
//执行复制
//往jdk的库文件安装路径复制jpeg.so (/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.332.b09-1.el7_9.x86_64/jre/lib/amd64)
public void writeJpegSoToLibAmd64Path(boolean mustRetry) {
try {
if(mustRetry){
hasWriteJpegSoToLibAmd64Path = false;
}
if (hasWriteJpegSoToLibAmd64Path) {
return;
}
//结尾带/
String libAmd64Path = getJavaInstallLibAmd64Path();
if (StringUtils.isBlank(libAmd64Path)) {
hasWriteJpegSoToLibAmd64Path = true;
log.info("FstStatusCheckService#writeJpegSoToLibAmd64Path:获取libAmd64Path为空,不执行写jpeg.so");
return;
}
//linux是libjpeg.so
//windows是jpeg.dll
boolean hasFile = hasFile(libAmd64Path, "libjpeg.so");
if (hasFile) {
hasWriteJpegSoToLibAmd64Path = true;
log.info("FstStatusCheckService#writeJpegSoToLibAmd64Path:路径下已有文件,不执行写jpeg.so");
return;
}
InputStream inputStream = this.getClass().getResourceAsStream("/libRes/libjpeg.so");
try {
File soFile = null;
if (libAmd64Path.endsWith("/")) {
soFile = new File(libAmd64Path + "libjpeg.so");
} else {
soFile = new File(libAmd64Path + "/libjpeg.so");
}
// 没有执行这个,也写入成功了
// file.createNewFile();
// file.setWritable(true);
FileUtils.copyInputStreamToFile(inputStream, soFile);
hasWriteJpegSoToLibAmd64Path = true;
hasFile = hasFile(libAmd64Path, "libjpeg.so");
if (hasFile) {
log.info("FstStatusCheckService#writeJpegSoToLibAmd64Path:执行写jpeg.so 成功");
String cmd = "chmod +x " + soFile.getAbsolutePath();
try {
//Runtime.getRuntime().exec("chmod +x " + soFile.getAbsolutePath());
Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", "chmod +x " + soFile.getAbsolutePath()}).waitFor();
log.info("FstStatusCheckService#writeJpegSoToLibAmd64Path:执行修复jpeg.so可执行权限 成功");
} catch (Exception e) {
log.warn("FstStatusCheckService#writeJpegSoToLibAmd64Path 写可执行权限出现异常,cmd:{},异常:{}", cmd, e);
}
} else {
log.info("FstStatusCheckService#writeJpegSoToLibAmd64Path:执行写jpeg.so失败,写入后没有找到,去确认下,可能已经写了");
}
} catch (IOException e) {
hasWriteJpegSoToLibAmd64Path = true;
log.warn("FstStatusCheckService#writeJpegSoToLibAmd64Path 写文件出现异常,异常:{}", e);
}
} catch (Exception e) {
log.warn("FstStatusCheckService#writeJpegSoToLibAmd64Path 写文件出现异常,异常:{}", e);
}
}
public void writeCloseLibreOfficeShell() {
try {
String targetFilePath = getCloseLibreOfficePath();
File file = new File(targetFilePath);
if (!file.exists()) {
file.createNewFile();
}
file.setWritable(true);
InputStream inputStream = this.getClass().getResourceAsStream("/libRes/closeLibreOffice.sh");
FileUtils.copyInputStreamToFile(inputStream, file);
log.info("FstStatusCheckService#closeLibreOffice.sh 已写入到jar包当前文件夹下");
// Runtime.getRuntime().exec("chmod +x " + file.getAbsolutePath());
if (isLinuxOS()) {
try {
Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", "chmod +x " + file.getAbsolutePath()}).waitFor();
} catch (InterruptedException e) {
log.error("FstStatusCheckService#closeLibreOffice.sh 写入到jar包当前文件夹出现异常 waitFor异常:{}", e);
}
}
} catch (IOException e) {
log.error("FstStatusCheckService#closeLibreOffice.sh 写入到jar包当前文件夹出现异常,异常:{}", e);
}
}
private String getCloseLibreOfficePath(){
String targetFile = "." + File.separatorChar + "closeLibreOffice.sh";
targetFile = "closeLibreOffice.sh";
return targetFile;
}
private boolean isLinuxOS() {
Properties properties = System.getProperties();
//判断是否是linux
String os = properties.getProperty("os.name");
log.info("isLinuxOS:{}",os);
return os != null && os.toLowerCase().contains("linux");
}
/**
* 期望获取 /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.332.b09-1.el7_9.x86_64/jre/lib/amd64
*
* @return
*/
private String getJavaInstallLibAmd64Path() {
String libAmd64Path = null;
if (isLinuxOS()) {
try {
Process exec = Runtime.getRuntime().exec("ls -lrt /etc/alternatives/java");
InputStream inputStream = exec.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, "gb2312"));
String line;
//一般只要读第一行,
while ((line = br.readLine()) != null) {
log.info("FstStatusCheckService#getJavaInstallLibAmd64Path#执行命令的结果:{}", line);
if (StringUtils.isNotBlank(line)) {
//lrwxrwxrwx. 1 root root 73 5月 31 2022 /etc/alternatives/java -> /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.332.b09-1.el7_9.x86_64/jre/bin/java
// /jre/lib/amd64
String[] str = line.split(" ");
log.info("FstStatusCheckService#getJavaInstallLibAmd64Path#执行结果分割:{}", (Object) str);
if (str.length > 1) {
String path = str[str.length - 1];
if (path != null && path.contains("jre/bin/java")) {
libAmd64Path = path.replace("jre/bin/java", "jre/lib/amd64");
log.info("FstStatusCheckService#getJavaInstallLibAmd64Path#获取到libAmd64Path:{}", libAmd64Path);
//libAmd64Path = "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.332.b09-1.el7_9.x86_64/jre/lib/amd64";
String[] split = libAmd64Path.split("/");
//TODO 关注:重新处理这个路径,非常关键,不然linux下的new File会有空指针
StringBuilder filePath = new StringBuilder(File.separator);
for (String folder : split) {
if(StringUtils.isNotBlank(folder)){
filePath.append(folder).append(File.separator);
}
}
return filePath.toString();
}
}
}
}
} catch (IOException e) {
log.warn("FstStatusCheckService#getJavaInstallLibAmd64Path出现异常:{}", e);
}
} else {
log.info("FstStatusCheckService#getJavaInstallLibAmd64Path#当前非linux环境,不获取libAmd64Path");
}
log.info("FstStatusCheckService#getJavaInstallLibAmd64Path#获取到libAmd64Path失败:{}", libAmd64Path);
return libAmd64Path;
}
// public static void main(String[] args) {
// String libAmd64Path = "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.332.b09-1.el7_9.x86_64/jre/lib/amd64";
// String[] split = libAmd64Path.split("/");
// StringBuilder filePath = new StringBuilder(File.separator);
// for (String folder : split) {
// if(StringUtils.isNotBlank(folder)){
// filePath.append(folder).append(File.separator);
// }
// }
// System.out.println(filePath.toString());
// }
/**
* 判断指定目录下是否有某个文件(注意目录使用File.separatorChar处理过)
* @param path
* @param fileName
* @return
*/
public boolean hasFile(String path, String fileName) {
log.info("FstStatusCheckService#hasFile入参:path:{},fileName:{}", path, fileName);
try {
if (isLinuxOS()) {
// String[] split = path.split("/");
// String filePath = File.separator;
// for (String folder : split) {
// filePath = folder + File.separator;
// }
String filePath = path + fileName;
File tmpdir = new File(filePath);
return tmpdir.exists();
} else {
//window ,其实还有mac
File tmpdir = new File(path);
//listFiles还有其他的方法,比如listFiles(FilenameFilter filter)根据名字模糊查询
File[] listFiles = tmpdir.listFiles((dir, name) -> name.equals(fileName));
return listFiles != null && listFiles.length > 0;
}
} catch (Exception e) {
log.warn("FstStatusCheckService#hasFile出现异常,默认为false,异常:{}", e);
return false;
}
// File tmpdir = new File(path);
// File[] listFiles = tmpdir.listFiles((dir, name) -> name.equals(keyword));
// return listFiles != null && listFiles.length > 0;
//这个true 是为了 业务需要不去重复执行
// FstStatusCheckService#hasFile入参:path:/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.332.b09-1.el7_9.x86_64/jre/lib/amd64,keyword:libjpeg.so
// 2023-02-07 15:06:35.376 [main] INFO cn.jiangjiesheng.fst.service.impl.FstStatusCheckService.hasFile:173 - FstStatusCheckService#FstStatusCheckService#hasFile 判断是否有执行的问题件
// java.lang.NullPointerException: null
// at java.io.File.<init>(File.java:279)
// at cn.jiangjiesheng.fst.service.impl.FstStatusCheckService.hasFile(FstStatusCheckService.java:169)
// at cn.jiangjiesheng.fst.service.impl.FstStatusCheckService.writeJpegSoToLibAmd64Path(FstStatusCheckService.java:79)
// at cn.jiangjiesheng.fst.FstApplication.main(FstApplication.java:31)
// at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
// at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
// at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
// at java.lang.reflect.Method.invoke(Method.java:498)
// at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
// at org.springframework.boot.loader.Launcher.launch(Launcher.java:108)
// at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
// at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)
}
}
正文到此结束