diff --git "a/1.1.5\347\211\210\346\234\254\344\271\213\345\211\215\347\232\204\345\206\205\345\255\230\351\227\256\351\242\230\350\247\243\345\206\263\346\226\271\346\241\210.md" "b/1.1.5\347\211\210\346\234\254\344\271\213\345\211\215\347\232\204\345\206\205\345\255\230\351\227\256\351\242\230\350\247\243\345\206\263\346\226\271\346\241\210.md" new file mode 100644 index 00000000..55f62e8b --- /dev/null +++ "b/1.1.5\347\211\210\346\234\254\344\271\213\345\211\215\347\232\204\345\206\205\345\255\230\351\227\256\351\242\230\350\247\243\345\206\263\346\226\271\346\241\210.md" @@ -0,0 +1,207 @@ +## step 1 导入jna包 +```xml + + net.java.dev.jna + jna + 5.13.0 + +``` +## step 2 创建内部接口 +```java +public interface Kernel32 extends StdCallLibrary { + Kernel32 INSTANCE = Native.load("kernel32", Kernel32.class); + long GetProcessId(Long hProcess); +} +``` + +## step 3 写获取进程id的方法 + +````java + /** + * 获取进程id + * @param process chrome进程 可以通过{@link com.ruiyun.jvppeteer.core.browser.Browser#process()} 获取} + * @return 进程id + */ +public static String getProcessId(Process process) { + long pid = -1; + Field field; + if (Platform.isWindows()) { + try { + field = process.getClass().getDeclaredField("handle"); + field.setAccessible(true); + pid = BrowserRunner.Kernel32.INSTANCE.GetProcessId((Long) field.get(process)); + } catch (Exception e) { + LOGGER.error("Failed to get processId on Windows platform.",e); + } + } else if (Platform.isLinux() || Platform.isAIX()) { + try { + String version = System.getProperty("java.version"); + double jdkversion = Double.parseDouble(version.substring(0, 3)); + Class clazz; + //如果生产环境是jdk8,就不用if判断了 + if (jdkversion <= 1.8) { + clazz = Class.forName("java.lang.UNIXProcess"); + } else { + clazz = Class.forName("java.lang.ProcessImpl"); + } + field = clazz.getDeclaredField("pid"); + field.setAccessible(true); + pid = (Integer) field.get(process); + } catch (Throwable e) { + LOGGER.error("Failed to get processId on Linux or Aix platform.",e); + } + } + return String.valueOf(pid); +} +```` +## step 4 通过kill 命令杀死进程 + +````java +/** + * kill 掉浏览器进程 + */ +public boolean kill() { + try { + String pid = pidMap.get(this.process); + if("-1".equals(pid)){ + LOGGER.warn("Chrome process pid is -1,will not use kill cmd"); + return false; + } + if(StringUtil.isEmpty(pid) ){ + LOGGER.warn("Chrome process pid is empty,will not use kill cmd"); + return false; + } + Process exec = null; + String command = ""; + if (Platform.isWindows()) { + command = "cmd.exe /c taskkill /PID " + pid + " /F /T "; + } else if (Platform.isLinux() || Platform.isAIX()) { + command = "kill -9 " + pid; + } + LOGGER.info("kill chrome process by pid,command: kill -9 {}", pid); + exec = Runtime.getRuntime().exec(new String[]{"/bin/sh","-c",command}); + return exec.waitFor(Constant.DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS); + } catch (Exception e) { + LOGGER.error("kill chrome process error ", e); + return false; + } +} +```` +## 完整代码示例 +````java + +package com.ruiyun.example; + +import com.ruiyun.jvppeteer.core.Constant; +import com.ruiyun.jvppeteer.core.Puppeteer; +import com.ruiyun.jvppeteer.core.browser.Browser; +import com.ruiyun.jvppeteer.core.browser.BrowserRunner; +import com.ruiyun.jvppeteer.core.page.Page; +import com.ruiyun.jvppeteer.options.LaunchOptions; +import com.ruiyun.jvppeteer.options.LaunchOptionsBuilder; +import com.ruiyun.jvppeteer.util.StringUtil; +import com.sun.jna.Native; +import com.sun.jna.Platform; +import com.sun.jna.win32.StdCallLibrary; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +public class KillExample { + + private static final Logger LOGGER = LoggerFactory.getLogger(BrowserRunner.class); + /** + * 多个browser的时候用pids储存pid + */ + private static Map pids = new HashMap<>(); + public static void main(String[] args) throws IOException, InterruptedException { + LaunchOptions launchOptions = new LaunchOptionsBuilder().withExecutablePath("C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe").withIgnoreDefaultArgs(Collections.singletonList("--enable-automation")).withHeadless(false).build(); + Browser browser = Puppeteer.launch(launchOptions); + Page page = browser.newPage(); + page.goTo("https://www.baidu.com/?tn=98012088_10_dg&ch=3"); + Process process = browser.process(); + String processId = getProcessId(process); + KillExample.LOGGER.info("process pid {}",processId); + // 做一些其他操作 + + + browser.close(); //可以关闭websocket连接 + kill(processId); + } + + public interface Kernel32 extends StdCallLibrary { + Kernel32 INSTANCE = Native.load("kernel32", Kernel32.class); + long GetProcessId(Long hProcess); + } + + public static String getProcessId(Process process) { + long pid = -1; + Field field; + if (Platform.isWindows()) { + try { + field = process.getClass().getDeclaredField("handle"); + field.setAccessible(true); + pid = KillExample.Kernel32.INSTANCE.GetProcessId((Long) field.get(process)); + } catch (Exception e) { + KillExample.LOGGER.error("Failed to get processId on Windows platform.",e); + } + } else if (Platform.isLinux() || Platform.isAIX()) { + try { + String version = System.getProperty("java.version"); + double jdkversion = Double.parseDouble(version.substring(0, 3)); + Class clazz; + //如果生产环境是jdk8,就不用if判断了 + if (jdkversion <= 1.8) { + clazz = Class.forName("java.lang.UNIXProcess"); + } else { + clazz = Class.forName("java.lang.ProcessImpl"); + } + field = clazz.getDeclaredField("pid"); + field.setAccessible(true); + pid = (Integer) field.get(process); + } catch (Throwable e) { + KillExample.LOGGER.error("Failed to get processId on Linux or Aix platform.",e); + } + } + return String.valueOf(pid); + } + + public static boolean kill(String pid) { + try { + if("-1".equals(pid)){ + LOGGER.warn("Chrome process pid is -1,will not use kill cmd"); + return false; + } + if(StringUtil.isEmpty(pid) ){ + LOGGER.warn("Chrome process pid is empty,will not use kill cmd"); + return false; + } + Process exec = null; + String command = ""; + if (Platform.isWindows()) { + command = "cmd.exe /c taskkill /PID " + pid + " /F /T "; + exec = Runtime.getRuntime().exec(command); + } else if (Platform.isLinux() || Platform.isAIX()) { + command = "kill -9 " + pid; + exec = Runtime.getRuntime().exec(new String[]{"/bin/sh","-c",command}); + } + if (exec != null) { + return exec.waitFor(Constant.DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS); + } + } catch (Exception e) { + LOGGER.error("kill chrome process error ", e); + return false; + } + return false; + } +} + +```` + + diff --git a/example/src/main/java/com/ruiyun/example/KillExample.java b/example/src/main/java/com/ruiyun/example/KillExample.java new file mode 100644 index 00000000..bcd307e7 --- /dev/null +++ b/example/src/main/java/com/ruiyun/example/KillExample.java @@ -0,0 +1,109 @@ +package com.ruiyun.example; + +import com.ruiyun.jvppeteer.core.Constant; +import com.ruiyun.jvppeteer.core.Puppeteer; +import com.ruiyun.jvppeteer.core.browser.Browser; +import com.ruiyun.jvppeteer.core.browser.BrowserRunner; +import com.ruiyun.jvppeteer.core.page.Page; +import com.ruiyun.jvppeteer.options.LaunchOptions; +import com.ruiyun.jvppeteer.options.LaunchOptionsBuilder; +import com.ruiyun.jvppeteer.util.StringUtil; +import com.sun.jna.Native; +import com.sun.jna.Platform; +import com.sun.jna.win32.StdCallLibrary; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +public class KillExample { + + private static final Logger LOGGER = LoggerFactory.getLogger(BrowserRunner.class); + /** + * 多个browser的时候用pids储存pid + */ + private static Map pids = new HashMap<>(); + public static void main(String[] args) throws IOException, InterruptedException { + LaunchOptions launchOptions = new LaunchOptionsBuilder().withExecutablePath("C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe").withIgnoreDefaultArgs(Collections.singletonList("--enable-automation")).withHeadless(false).build(); + Browser browser = Puppeteer.launch(launchOptions); + Page page = browser.newPage(); + page.goTo("https://www.baidu.com/?tn=98012088_10_dg&ch=3"); + Process process = browser.process(); + String processId = getProcessId(process); + KillExample.LOGGER.info("process pid {}",processId); + kill(processId); + // 做一些其他操作 + browser.close(); + } + + public interface Kernel32 extends StdCallLibrary { + Kernel32 INSTANCE = Native.load("kernel32", Kernel32.class); + long GetProcessId(Long hProcess); + } + + public static String getProcessId(Process process) { + long pid = -1; + Field field; + if (Platform.isWindows()) { + try { + field = process.getClass().getDeclaredField("handle"); + field.setAccessible(true); + pid = KillExample.Kernel32.INSTANCE.GetProcessId((Long) field.get(process)); + } catch (Exception e) { + KillExample.LOGGER.error("Failed to get processId on Windows platform.",e); + } + } else if (Platform.isLinux() || Platform.isAIX()) { + try { + String version = System.getProperty("java.version"); + double jdkversion = Double.parseDouble(version.substring(0, 3)); + Class clazz; + //如果生产环境是jdk8,就不用if判断了 + if (jdkversion <= 1.8) { + clazz = Class.forName("java.lang.UNIXProcess"); + } else { + clazz = Class.forName("java.lang.ProcessImpl"); + } + field = clazz.getDeclaredField("pid"); + field.setAccessible(true); + pid = (Integer) field.get(process); + } catch (Throwable e) { + KillExample.LOGGER.error("Failed to get processId on Linux or Aix platform.",e); + } + } + return String.valueOf(pid); + } + + public static boolean kill(String pid) { + try { + if("-1".equals(pid)){ + LOGGER.warn("Chrome process pid is -1,will not use kill cmd"); + return false; + } + if(StringUtil.isEmpty(pid) ){ + LOGGER.warn("Chrome process pid is empty,will not use kill cmd"); + return false; + } + Process exec = null; + String command = ""; + if (Platform.isWindows()) { + command = "cmd.exe /c taskkill /PID " + pid + " /F /T "; + exec = Runtime.getRuntime().exec(command); + } else if (Platform.isLinux() || Platform.isAIX()) { + command = "kill -9 " + pid; + exec = Runtime.getRuntime().exec(new String[]{"/bin/sh","-c",command}); + } + if (exec != null) { + return exec.waitFor(Constant.DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS); + } + } catch (Exception e) { + LOGGER.error("kill chrome process error ", e); + return false; + } + return false; + } +} diff --git a/src/main/java/com/ruiyun/jvppeteer/core/Puppeteer.java b/src/main/java/com/ruiyun/jvppeteer/core/Puppeteer.java index 52a2a679..60a6beee 100644 --- a/src/main/java/com/ruiyun/jvppeteer/core/Puppeteer.java +++ b/src/main/java/com/ruiyun/jvppeteer/core/Puppeteer.java @@ -5,16 +5,11 @@ import com.ruiyun.jvppeteer.launch.ChromeLauncher; import com.ruiyun.jvppeteer.launch.FirefoxLauncher; import com.ruiyun.jvppeteer.launch.Launcher; -import com.ruiyun.jvppeteer.options.BrowserOptions; -import com.ruiyun.jvppeteer.options.ChromeArgOptions; -import com.ruiyun.jvppeteer.options.FetcherOptions; -import com.ruiyun.jvppeteer.options.LaunchOptions; -import com.ruiyun.jvppeteer.options.LaunchOptionsBuilder; +import com.ruiyun.jvppeteer.options.*; import com.ruiyun.jvppeteer.transport.ConnectionTransport; import com.ruiyun.jvppeteer.util.StringUtil; import java.io.IOException; -import java.util.ArrayList; import java.util.List; import static com.ruiyun.jvppeteer.core.Constant.PRODUCT_ENV; diff --git a/src/main/java/com/ruiyun/jvppeteer/core/browser/BrowserRunner.java b/src/main/java/com/ruiyun/jvppeteer/core/browser/BrowserRunner.java index d9536895..cedbf2e6 100644 --- a/src/main/java/com/ruiyun/jvppeteer/core/browser/BrowserRunner.java +++ b/src/main/java/com/ruiyun/jvppeteer/core/browser/BrowserRunner.java @@ -217,6 +217,9 @@ public void onBrowserEvent(Object event) { * kill 掉浏览器进程 */ public boolean kill() { + if(this.closed){ + return true; + } try { String pid = pidMap.get(this.process); if("-1".equals(pid)){ @@ -231,13 +234,16 @@ public boolean kill() { String command = ""; if (Platform.isWindows()) { command = "cmd.exe /c taskkill /PID " + pid + " /F /T "; + exec = Runtime.getRuntime().exec(command); } else if (Platform.isLinux() || Platform.isAIX()) { command = "kill -9 " + pid; + exec = Runtime.getRuntime().exec(new String[]{"/bin/sh","-c",command}); } try { - LOGGER.info("kill chrome process by pid,command: kill -9 {}", pid); - exec = Runtime.getRuntime().exec(new String[]{"/bin/sh","-c",command}); - return exec.waitFor(Constant.DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS); + if (exec != null) { + LOGGER.info("kill chrome process by pid,command: {}", command); + return exec.waitFor(Constant.DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS); + } } finally { this.destroyCmdProcess(exec,command); if (StringUtil.isNotEmpty(this.tempDirectory)) { @@ -248,6 +254,7 @@ public boolean kill() { LOGGER.error("kill chrome process error ", e); return false; } + return false; } diff --git a/src/main/java/com/ruiyun/jvppeteer/util/Helper.java b/src/main/java/com/ruiyun/jvppeteer/util/Helper.java index 5fa72c14..2147c66e 100644 --- a/src/main/java/com/ruiyun/jvppeteer/util/Helper.java +++ b/src/main/java/com/ruiyun/jvppeteer/util/Helper.java @@ -534,7 +534,6 @@ public static String getProcessId(Process process) { try { String version = System.getProperty("java.version"); double jdkversion = Double.parseDouble(version.substring(0, 3)); - System.out.println("jdkversion = " +jdkversion); Class clazz; if (jdkversion <= 1.8) { clazz = Class.forName("java.lang.UNIXProcess");