返回顶部
首页 > 资讯 > 后端开发 > Python >Runtime.getRuntime().exec 路径包含空格的解决
  • 719
分享到

Runtime.getRuntime().exec 路径包含空格的解决

2024-04-02 19:04:59 719人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

目录Runtime.getRuntime().exec 路径包含空格1. 现象2. 原因解决办法Runtime.getRuntime().exec()产生阻塞的2个陷阱背景关于Run

Runtime.getRuntime().exec 路径包含空格

1. 现象

java代码通过Runtime.getRuntime().exec删除linux上的目录,如果路径信息不包含空格没有问题,但是有了空格,虽没有报错,但执行没有效果,文件夹删不掉。

2. 原因

Runtime.getRuntime().exec语法不支持空白符和管道符"|"

不支持空白符和管道符"|"的例子:


//包含空格
String cmd = "rm -fr test 1";
// 包含管道符
String cmd2 = "netstat -antup | grep ftp";
Process ps = Runtime.getRuntime().exec(cmd);
ps.waitFor();

解决办法

如果直接在命令行执行的话,可以通过给完整的字符带上单引号或双引号,java代码用法不适用。


[root@EMS3 ~]# rm -rf "/root/test 1"

使用重载函数即可:


public Process exec(String cmdarray[])

String cmd = "rm -fr test 1";
// 或
String cmd2 = "netstat -antup | grep ftp";
Process ps = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", cmd});
ps.waitFor();
...

其中-c表示cmd是一条命令

/bin/sh -c注意事项

由于增加了-c 参数,并指定shell类型,因此需要确认shell的类型。因此根据实际环境的shell类型。

/bin/sh是什么?

shell编程是以"#“为注释,但对”#!/bin/sh"却不是。"#!/bin/sh"是对shell的声明,说明你所用的是那种类型的shell及其路径所在(#! /bin/sh 是指此脚本使用/bin/sh来解释执行,#!是特殊的表示符,其后面跟的是解释此脚本的shell的路径)。如果没有声明,则脚本将在默认的shell中执行,默认shell是由用户所在的系统定义为执行shell脚本的shell。

如果脚本被编写为在Kornshell ksh中运行,而默认运行shell脚本的为C shell csh,则脚本在执行过程中很可能失败。所以建议大家就把"#!/bin/sh"当成C 语言的main函数一样,写shell必须有,以使shell程序更严密。

Runtime.getRuntime().exec()产生阻塞的2个陷阱

背景

相信做java服务端开发的童鞋,经常会遇到Java应用调用外部命令启动一些新进程来执行一些操作的场景,这时候就会使用到Runtime.getRuntime().exec(),然而这个方法如果不谨慎很容易掉进陷阱。

我们的一个pdf转码服务就踩到了这个坑掉进陷阱,这个转码服务主要是对pdf进行加密和转码成swf。这个服务上线后大部分时间都是稳定运行的,但是隔一段时间就会死掉,然后人肉手动重启一下服务就复活了。看了日志,有时候有一堆关于pdf转码过程的错误日志,有时候死掉的时候什么日志也没输出。这时候猜测可能是pdf转码异常导致应用挂掉的{因为这个转码服务一直是单线程在工作}。更深的原因大家也空没去找。反正运营反馈上传的pdf一直处在转码中很久了,一两天了还在转码中,于是开发就手动重启下服务。是的你没看过,就是一两天才发现,我们的业务监控没作上去,因为相对迭代任务,这都算不紧急的事情了。

后来运营反馈pdf问题次数增多了,于是写了个脚本,定时去检查日志最后的更新时间,发现日志超过一个小时没更新就重启应用,重启脚本没问题,问题是应用重启后,日志中出现了一堆的找不到要执行的命令。目前也不知道为什么通过脚本去重启动应用后,应用找不到要执行的命令。有知道的可以告知下。

终于某一天,应用又死掉了,看了下数据库堆积了将近2000个待转的文件。看了下应用日志打了exe()后就再也没内容了,于是下狠心花了半天时间来研究下Runtime.getRuntime().exe()找了下原因,最终解决了这个问题。

关于Runtime.getRuntime().exe()

根据jdk官方文档描述,每个Java应用都存在一个而Runtime的单例实例。这个类Runtime类封装了应用运行时的环境,通过这个类我们的java应用可以与其运行环境相连接。

1、java应用无法创建自己的Runtime实例,只能通过Runtime.getRuntime()来取得当前JVM的运行时环境,这也是在Java中唯一一个得到运行时环境的方法。一旦得到了一个当前的Runtime对象的引用,就可以调用Runtime对象的方法来控制Java虚拟机的状态和行为。

2、Runtime中的exit方法是退出当前JVM的方法,System类中的exit实际上也是通过调用Runtime.exit()来退出JVM的,这里说明一下Java对Runtime返回值的一般规则(后边也提到了),0代表正常退出,非0代表异常中止。

3、Runtime具有的详细方法请参考官方apiHttp://docs.oracle.com/javase/8/docs/api/

阻塞陷阱之Runtime.getRuntime().exe()的返回值Process

应用在调用Runtime.getRuntime().exec()这个方法会创建一个本机进程并返回Process子类的一个实例。该实例可用来控制该进程并获得其相关信息。Process类提供了执行从进程输入、执行输出到进程、等待进程完成、检查进程的退出状态以及销毁(杀掉)进程的方法。

官方文档解释了创建进程的方法可能无法针对某些本机平台上的特定进程很好地工作,比如,本机窗口进程,守护进程,Microsoft windows 上的 Win16/DOS 进程,或者 shell脚本。创建的子进程没有自己的终端或控制台。它的所有标准 io(即 stdin、stdout 和 stderr)操作都将通过三个管道重定向到父进程(也就是调用者java应用)。三个管道用于处理标准输入流,标准输出流,标准错误流。子进程在执行过程中,会不断的向JVM写入标准输出和标准错误输出。java应用可以通过Process 提供的getOutputStream()、getInputStream() 和 getErrorStream()来获得子进程输入输出信息。因为有些本机平台仅针对标准输入和输出流提供有限的缓冲区大小,当标准输出或者标准错误输出写满缓存池时,程序无法继续写入,子进程无法正常退出。读写子进程的输出流或输入流迅速出现失败,则可能导致子进程阻塞,甚至产生死

当调用Runtime.getRuntime().exe()后返回的Process对象除了可以多的三种输入输出流外,还有两个常用的方法:

1、非阻塞方法exitValue()获得子进程退出的状态值(0,正常退出,非0异常退出),需要注意的是调用这个方法程序会立即得到结果,如果子进程没有执行完,调用这个方法会抛出IllegalThreadStateException,表示此 Process 对象表示的子进程尚未终止。

2、阻塞方法 waitFor()导致当前线程等待,直到子进程结束并返回退出状态。如果已终止该子进程,此方法立即返回,如果没有终止该子进程,调用的线程将被阻塞,直到退出子进程。

先看看我们转码服务这里的历史代码:

8b6068fd-a41e-4e09-b951-d89eb6de11f4

这段代码,用同步的方法去读取标准错误输出流即相当于清空了错误输出流缓冲区,然而正常的标准输出流并没有清空,按照上面的原理解释,阻塞的原因可能就产生在这里。当阻塞产生的时候jstack了一下线程栈信息如下图所示。确实线程锁在了读取缓冲流上面了。

639048e4-46f9-4041-9b5d-a9b28d2f1f51?imageView&thumbnail=980x0

这种情况网上通用的解决方法就是异步开两个线程去读取正常的输出和错误输出流信息,清空缓冲区,参考了大家的解决方法,下图是修改后的方案,ProcessClearStream是一个异步线程,主要做的是将标准inputSream读取完毕。

6b31a150-06a0-4a5f-b7a5-ffd4b56e8348?imageView&thumbnail=980x0

阻塞陷阱之子进程阻塞

通过上面的代码优化后还是发现有转码阻塞的现象出现,而且发现每次阻塞都出现在固定的几个pdf上,测试发现重启应用后主要转到那几个特定的pdf时候,转码服务必挂无疑(通常一个pdf转码只需要几十秒,而这个阻塞持续几个小时,不人为干预它就可能无限阻塞下去)。所以重启应用也不管用了,只能跳过这几个pdf应用才行,于是在测试环境测试这几个pdf,每次阻塞的时候再jstack发现应用阻塞在proc.waitFor(),再也没其他错误信息了。查看了官方api,Process的waitFor方法本身会阻塞直到子进程正常或异常退出,到这里,应该可以推断是子进程无限阻塞下去了,导致waitFor一直阻塞中。为了验证这个推断,直接在终端kill掉这个子进程,然后再查看日志,发现转码服务又继续工作了。

有了上面的结论,一个简单的思路也就有了,我需要检测子进程状态,如果发现子进程有阻塞状态就kill掉(因为这个转码脚本比较老,要拿他的堆栈信息比较麻烦,所以kill掉是最简单直接暴力效率高的方法)。将这个想法和同事聊了下,万能的Java肯定可以干这事,大概思路就启动个线程去监控process的waitFor的阻塞时间,超过设置时间,就干掉了子进程,这不是Java线程池ExecutorService类配合Future接口来干的事情么。同事按照这个思路网上找了下现成的代码,于是照着这个这个方法抄袭了一下,下面贴下关键的代码:

9d08d3e6-2cb9-48c7-b9fa-2da654a68d62

当waitFor超时线程中断的的时候再调用process的destroy()销毁子进程。这个方案上线后,截至目前一周多时间转码服务稳定运行,没在出现以前的服务死掉的情况。

我们业务中当检测到超时退出后就重置任务状态为失败(算是降级吧),导致这种pdf转码子进程阻塞的一般是pdf本身不太标准,而这个转码工具不能很好的兼容处理这些pdf,后面把这些有问题的pdf重新转成标准pdf上传测试即可以正常转码。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

--结束END--

本文标题: Runtime.getRuntime().exec 路径包含空格的解决

本文链接: https://lsjlt.com/news/156291.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Runtime.getRuntime().exec 路径包含空格的解决
    目录Runtime.getRuntime().exec 路径包含空格1. 现象2. 原因解决办法Runtime.getRuntime().exec()产生阻塞的2个陷阱背景关于Run...
    99+
    2024-04-02
  • python调用程序路径中包空格,及包含特殊字符问题
      解决办法  import os  s = r'"C:\Program Files\Google\Chrome\Application\chrome.exe"'  print(s)  os.system...
    99+
    2023-06-02
  • win10系统注册包含无效路径怎么解决
    要解决Win10系统注册包含无效路径的问题,可以尝试以下方法:1. 运行系统文件检查工具:按下Win + X键,选择“命令提示符(管...
    99+
    2023-09-09
    win10
  • VBS中解决带空格路径的方法有哪些
    本篇内容介绍了“VBS中解决带空格路径的方法有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!方法一:Set wshell=Cr...
    99+
    2023-06-08
  • python管理包路径之pycharm自动解决包路径注册
    目录简介模块化模块导入包简介 Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。你可以将它理解成脚本语言,大多情况我也是将它作为写脚本工具的一个方式。py...
    99+
    2024-04-02
  • shell脚本传参中包含有空格的参数怎么解决
    本篇内容主要讲解“shell脚本传参中包含有空格的参数怎么解决”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“shell脚本传参中包含有空格的参数怎么解决”吧!问题描述调用并传参数给其他shell...
    99+
    2023-07-05
  • Laravel打包:如何处理包含ASP路径的文件?
    Laravel是一个流行的PHP框架,它提供了许多强大的功能和工具,使得开发人员可以更加轻松地开发和维护Web应用程序。其中一个强大的功能是打包,它可以将应用程序打包成单个文件,方便分发和部署。但是,在打包过程中,可能会遇到包含ASP路径的...
    99+
    2023-07-29
    path 打包 laravel
  • Shell如何遍历包含空格的文本详解
    shell遍历文件 有时候要对某个文件夹下面的所有文件做同样的处理,比如对每个文件统计行数,这时用遍历文件的方式就很简单了。 $ for i in `ls`;do wc -l $i;done 55552 f123.txt...
    99+
    2022-06-04
    shell遍历文本内容 shell遍历文本 shell遍历文本所有行
  • pyinstaller打包可执行文件,存放路径包含中文无法运行的解决方案
    一、实验环境 1.Windows7x64_SP1 2.anaconda2.5.0 + python2.7(anaconda集成,不需单独安装) 3.pyinstaller3.0 二、...
    99+
    2024-04-02
  • PHP中怎么获取包含路径信息的数组
    小编给大家分享一下PHP中怎么获取包含路径信息的数组,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!在PHP的使用过程中,文件的路径是比较常用的,那么如何将文件的路...
    99+
    2023-06-14
  • Shell中处理包含空格的文件名实例
    今天在处理文件时遇到个问题,当文件名包含空格时,for循环就出问题了。 例如,我在当前文件夹下建立3个文件名包含空格的文件: keakons-MacBook-Pro:test keakon$ touch "...
    99+
    2022-06-04
    空格 文件名 实例
  • shell脚本传参中包含有空格的参数
    目录问题描述原因分析解决方案拓展传递给函数的某个参数含有空格问题描述 调用并传参数给其他shell脚本,传的参数带有空格,被调用的shell脚本只取了这个参数的第一个单词。 代码如下...
    99+
    2023-03-22
    shell脚本传参有空格 shell传递带空格的参数
  • Shell中如何处理包含空格的文件名
    这篇文章主要介绍“Shell中如何处理包含空格的文件名”,在日常操作中,相信很多人在Shell中如何处理包含空格的文件名问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Shell中如何处理包含空格的文件名”的疑...
    99+
    2023-06-09
  • 如何在打包Laravel时正确处理包含ASP路径的文件?
    Laravel是一个流行的PHP框架,它提供了许多强大的功能,使得开发者能够更加轻松地构建现代Web应用程序。但是,在打包Laravel应用程序时,可能会遇到一些问题,特别是当应用程序中包含ASP路径的文件时。 在本文中,我们将探讨如何在打...
    99+
    2023-07-29
    path 打包 laravel
  • react打包图片路径错误如何解决
    今天小编给大家分享一下react打包图片路径错误如何解决的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。react打包图片路径...
    99+
    2023-07-05
  • 解决Java打包文件路径问题的小技巧!
    Java是一种广泛使用的编程语言,但是在使用Java时,我们经常会遇到一些打包文件路径问题,这些问题可能会给我们带来不便和困扰。为了解决这些问题,我们需要掌握一些小技巧,这篇文章将介绍一些解决Java打包文件路径问题的小技巧。 1.使用相对...
    99+
    2023-10-03
    打包 文件 path
  • 如何解决vue-cli项目打包出现空白页和路径错误的问题
    这篇文章主要介绍了如何解决vue-cli项目打包出现空白页和路径错误的问题,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。vue-cli项目打...
    99+
    2024-04-02
  • JavaScript网格中的最小路径讲解
    目录问题描述思路分析AC代码问题描述 给你一个下标从 0 开始的整数矩阵 grid ,矩阵大小为 m x n ,由从 0 到 m * n - 1 的不同整数组成。你可以在此...
    99+
    2024-04-02
  • linux下scp远程拷贝包含空格的目录或者文件的问题如何解决
    本篇内容介绍了“linux下scp远程拷贝包含空格的目录或者文件的问题如何解决”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!描述: 今天需要...
    99+
    2023-06-13
  • 打包FlaskAdmin程序时关于static路径问题的解决
    1、pyinstaller的使用 网上资料多,此处省略 2、打包时报错 1、可能有些包没有安装(跑跑程序不缺库就行) 2、有些包pyinstaller找不到? 打包时手动添加 --...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作