3

scala/java 通过bash创建新的进程,杀死相应进程

 2 years ago
source link: https://cfonheart.github.io/2019/02/25/scala-java-%E9%80%9A%E8%BF%87bash%E5%88%9B%E5%BB%BA%E6%96%B0%E7%9A%84%E8%BF%9B%E7%A8%8B-%E6%9D%80%E6%AD%BB%E7%9B%B8%E5%BA%94%E8%BF%9B%E7%A8%8B/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

scala/java 通过bash创建新的进程,杀死相应进程

2019-02-25

我们经常可能需要从代码中启动一个脚本,或者一个程序来辅助自己完成需要的功能。比如bash脚本启动一个程序服务,可以通过进程之间的通信(比如socket)获取本程序想要的信息。

##进程的创建

Java提供了两种方法用来启动进程或其它程序:
(1)使用Runtime的exec()方法
(2)使用ProcessBuilder的start()方法

实际上Runtime.exec() 代码中最终也调用了ProcessBuilder的start()方法 。

这里主要展示一个简单的执行查看网卡信息的代码和从java代码中启动一个bash进程执行java命令的代码

// bash查看网络配置信息
String cmd = "ifconfig";
String [] execCmd = {"sh", "-c", cmd};
Process process = Runtime.getRuntime().exec(execCmd);
process.waitFor();
Scanner scanner = new Scanner(process.getInputStream());
while(scanner.hasNextLine()){
System.out.println(scanner.nextLine());
}catch (Exception ex){
ex.printStackTrace();
// bash执行java的main函数
String classpath = System.getProperty("java.class.path");
// -cp -> -classpath, 这里是前提是代码已经编译成class文件,且在infrastructure包下有一个包含main函数的TranswarpServer类,且这个main函数可以接受三个String的参数12346 server1 NORMAL
String cmd = "java -cp " + classpath + " infrastructure.TranswarpServer 12346 server1 NORMAL";
// String cmd = "nohup java -cp " + classpath + " infrastructure.TranswarpServer 12346 server1 NORMAL &"; //如果不想因为等待这个进程完成而堵塞,可以直接选择在bash里挂起进程
String [] env = {"PATH=%s:%s/bin".format(System.getenv("PATH"),System.getenv("JAVA_HOME"))};
String [] execCmd = {"sh", "-c", cmd};
Process process = Runtime.getRuntime().exec(execCmd, env);
process.waitFor();
Scanner scanner = new Scanner(process.getInputStream());
// Scanner scanner = new Scanner(process.getErrorStream()); //可以查看java不能正常执行的报错信息
while(scanner.hasNextLine()){
System.out.println(scanner.nextLine());
// Thread.sleep(1000);
}catch (Exception ex){
ex.printStackTrace();

代码中启动的新进程可能是一个服务或者类似ping baidu.com这种的不停执行的命令,不会因为当前进程的退出而退出。而且进程process对象中也无法获取到进程的id,给我们用于kill。

杀掉创建的进程

  1. 代码中通过启动一个新的进程找到和之前启动的进程相关的程序,比如之前启动的进程包含了执行infrastructure.TranswarpServer的java程序,那么可以通过ps aux | grep ‘infrastructure.TranswarpServer’找到相关的进程信息

  2. 我们简单测试就可知,从代码中执行ps aux | grep ‘infrastructure.TranswarpServer’指令,得到的不止我们需要的信息,还包括grep本身的进程,以及我们bash -c启动的进程信息,如下所示的这前两个就是无用的,最后一个才是我们真正需要的,而且这个bash执行完,前两个进程实际就消失了。

    但是我们不用在意这些,将所有的pid都收集起来形成一个list,均kill -9 掉,如果已经不存在,kill -9 也不会有什么作用,对真正我们要kill的pid,也能正常kill。

    ganjun 11178 0.0 0.0 2432804 1324 ?? R 6:47PM 0:00.00 grep infrastructure.TranswarpServer
    ganjun 11176 0.0 0.0 2435440 2124 ?? S 6:47PM 0:00.00 bash -c ps aux | grep 'infrastructure.TranswarpServer'
    ganjun 10014 0.0 0.2 8207960 29408 ?? S 6:15PM 0:02.33 /usr/bin/java -cp ... infrastructure.TranswarpServer
def getProcessIds(key: String): util.ArrayList[Int] ={
import java.io.{BufferedReader, InputStreamReader}
var pids = new util.ArrayList[Int]()
val re = false
val command = s"ps aux | grep '${key}'"
val process = Runtime.getRuntime.exec( Array("bash", "-c", command) )
val br = new BufferedReader(new InputStreamReader(process.getInputStream))
var line: String = br.readLine()
while (line != null){
println(line)
val tInputStringStream = new ByteArrayInputStream(line.getBytes)
// let string as input stream read the process id
val scanner = new Scanner(tInputStringStream)
val user = scanner.next()
val pid = scanner.nextInt()
scanner.close()
pids.add(pid)
line = br.readLine()
br.close()
} catch {
case e: Exception =>
System.out.println(e.toString)
// 统计实际删除的进程个数
def killProcesses(key: String): Int={
var killNumbers = 0
val pids: List[Int] = getProcessIds(key)
println( pids )
pids.foreach(pid => {
val process = Runtime.getRuntime().exec(Array("bash", "-c", s"kill -9 ${pid}"))
if( process.waitFor() == 0) // 因为有些得到的进程id是前面本身grep产生的无意义的
killNumbers += 1
killNumbers
killProcesses("infrastructure.TranswarpServer")

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK