药学专业网站,北京软件公司名称大全,南宁建设网站制作,怎么用云服务器做网站文章目录 前言一、linux命令执行二、使用步骤三、踩坑 前言
java 执行linux 命令#xff1b; 本文模拟复制linux文件到指定文件夹后打zip包后返回zip名称#xff0c;提供给下载接口下载zip#xff1b;
一、linux命令执行
linux命令执行Process process Runtime.getRunti… 文章目录 前言一、linux命令执行二、使用步骤三、踩坑 前言
java 执行linux 命令 本文模拟复制linux文件到指定文件夹后打zip包后返回zip名称提供给下载接口下载zip
一、linux命令执行
linux命令执行Process process Runtime.getRuntime().exec或Process process new ProcessBuilder(commands).start(); /*** 执行Linux命令*/public static void execCommand(String commands) throws IOException {Process process null;BufferedReader reader null;try {//创建进程实例执行Linux命令process Runtime.getRuntime().exec(new String[]{/bin/sh, -c, commands});// 获取标准输入流reader new BufferedReader(new InputStreamReader(process.getInputStream()));String line;while ((line reader.readLine()) ! null) {//log.info(linux---- line);}// 等待进程结束int exitCode process.waitFor();if (exitCode ! 0) {log.error(执行Linux命令异常,exitCode{},linux command{}, exitCode, commands);throw new BusinessCheckException(执行Linux命令异常);}} catch (IOException | InterruptedException e) {log.error(执行Linux命令异常, e);throw new BusinessCheckException(执行Linux命令异常);} finally {if (reader ! null) {reader.close();}if (process ! null) {process.destroy();}}}二、使用步骤
通过linux命令打包目标数据到zip
public String downToZip(CorpQrCodeReq req, HttpServletResponse response) {StopWatch sw new StopWatch();// 参数校验if (CollectionUtils.isEmpty(req.getCorpIds()) || CollectionUtils.isEmpty(req.getCorpNames())) {return 0;}// 生成保存目录文件夹String uuid UUID.randomUUID().toString().replace(-, );String baseUploadPath /tmp/zip/uuid/;FileUtil.mkdir(baseUploadPath);try {//生成二维码到临时目录ListString enterpriseIds req.getCorpIds();ListString enterpriseNames req.getCorpNames();ListString command new ArrayList(enterpriseIds.size());// 拼接被复制的文件地址for (int i 0; i enterpriseIds.size(); i) {String path this.qrCode(CorpQrCodeReq.builder().corpIds(Lists.newArrayList(enterpriseIds.get(i))).corpNames(Lists.newArrayList(enterpriseNames.get(i))).build());command.add(path );}sw.stop();log.info(sw.getLastTaskName() sw.getTotalTimeSeconds() s);sw.start(执行cp命令);String property System.getProperty(line.separator);//拼接shell脚本String sb for i in String.join( , command) property do property cp -n \$i\ baseUploadPath property done;//执行cp命令execCommand(sb);sw.stop();log.info(sw.getLastTaskName() sw.getTotalTimeSeconds() s);sw.start(执行压缩命令);//执行压缩命令 统一压缩比一个一个压缩进去效率高 //-j忽略源文件路径直接打包目标文件String zipCommand /bin/zip -1 -j baseUploadPath.concat(.zip) baseUploadPath /*;execCommand(zipCommand);sw.stop();log.info(sw.getLastTaskName() sw.getTotalTimeSeconds() s);log.info(sw.prettyPrint());return uuid;} catch (Exception e) {log.error(压缩包下载失败 , e);throw new BusinessCheckException(压缩包下载失败);}}根据uuid下载zip文件2个接口一个是根据条件生成zip另一个根据zip名称下载此处下载应用了nginx的X-Accel-Redirect具体使用方法参考springboot X-Accel-Redirect 大文件下载实现 public void downZip(String path, HttpServletResponse response) {try {String baseUploadPath /tmp/zip/;response.addHeader(Content-Disposition, attachment;filename URLEncoder.encode(企业二维码, StandardCharsets.UTF_8.toString()) .zip);//设置URI给nginx进行内部的跳转response.setHeader(X-Accel-Redirect, /upload baseUploadPath.concat(path).concat(.zip));} catch (Exception e) {log.error( 二维码压缩包下载失败 , e);throw new BusinessCheckException(二维码压缩包下载失败);}}三、踩坑
linux 和 java 2个进程异步问题
linux命令执行后和java服务是2个进程。 当linux命令执行过程期间java下面的业务服务已触发时比如文件数量较大而下载接口触发较快时会造成数据不完整zip包打包不全一般一个文件没有。 此时我们需要利用 读取执行流 process.waitFor()等待linux进程结束后再做业务处理。
关于Process初始化 Process process null;// 如果commands拼接的命令中包含空格 会自动识别为2段命令process new ProcessBuilder(commands).start();// 不支持空格和|process Runtime.getRuntime().exec(commands);// -c 表示cmd是一条命令不会被截断process Runtime.getRuntime().exec(new String[]{/bin/sh, -c, commands});linux for cp 空格识别问题 执行脚本如下
for i in /data/mnt/www/corp-qr/769847/九台区九台中由 生活服务部.jpg
docp -n $i /data/zip/5e0e67f59c524a4e9851abd3a3dfe0ac
done此时执行命令报错cp: 无法获取/data/mnt/www/corp-qr/769847/九台区九台中由 的文件状态(stat): 没有那个文件或目录 cp: 无法获取生活服务部.jpg 的文件状态(stat): 没有那个文件或目录linux 会将目标文件解析成2个文件。
解决方案
/data/mnt/www/corp-qr/769847/九台区九台中由 生活服务部.jpg 修改为 /data/mnt/www/corp-qr/769847/* 或
cp -n $i /data/zip/5e0e67f59c524a4e9851abd3a3dfe0ac 修改为 cp -n $i /data/zip/5e0e67f59c524a4e9851abd3a3dfe0ac执行效率优化 一千个文件测试结果 a. 文件循环时直接打包到zip/bin/zip -rj baseUploadPath.concat(.zip) baseUploadPath /*;效率不如cp 到文件夹下压缩文件夹 b. 调整压缩率 zip -1 c. 文件循环时直接cp由于execCommand执行linux命令要等返回结果再执行所以效率也不高 cp 文件覆盖问题 同名文件cp linux会提示是否覆盖如果通过java执行cp无法给予是否覆盖的回应报错没有那个文件或目录如果忽略覆盖提示 覆盖提示原因 我们执行cp时 实际linux执行的是cp -i -i 表示覆盖前提示
-- 命令前加反斜线忽略alias
\cp /var/tmp/test.txt /tmp
-- 使用命令全路径
/bin/cp /var/tmp/test.txt /tmp
-- 先取消别名再复制不推荐
unalias cp
-- 不覆盖
cp -n /var/tmp/test.txt /tmp