美文网首页
比调用Shell更高效的判断进程是否存在的方式

比调用Shell更高效的判断进程是否存在的方式

作者: ShootHzj | 来源:发表于2021-08-12 17:24 被阅读0次

    有很多场景需要我们的代码检测一个进程是否存在,常用的一种方式是通过调用脚本通过ps -ef的方式查看,然而其实这种做法并不怎么高效,会fork一个进程出来,还会影响go协程的调度

    一种更好的方式是可以通过解析/proc文件夹来得到想要的信息,其实可以通过strace命令查看,ps -ef也是读取了这个路径下的信息

    image-20210812141644151

    下面分别是java和go的轮子示例

    使用正则表达式[0-9]+的原因是/proc路径下还有一些其他文件,其中pid都是数字。

    java

    private static final Pattern numberPattern = Pattern.compile("[0-9]+");
    
        public static boolean processExists(String processName) throws Exception {
            final File procFile = new File("/proc");
            if (!procFile.isDirectory()) {
                throw new Exception("why proc dir is not directory");
            }
            final File[] listFiles = procFile.listFiles();
            if (listFiles == null) {
                return false;
            }
            final List<File> procDir = Arrays.stream(listFiles).filter(f -> numberPattern.matcher(f.getName()).matches()).collect(Collectors.toList());
            // find the proc cmdline
            for (File file : procDir) {
                try {
                    final byte[] byteArray = FileUtils.readFileToByteArray(new File(file.getCanonicalPath() + File.separator + "cmdline"));
                    final byte[] bytes = new byte[byteArray.length];
                    for (int i = 0; i < byteArray.length; i++) {
                        if (byteArray[i] != 0x00) {
                            bytes[i] = byteArray[i];
                        } else {
                            bytes[i] = (byte) 0x20;
                        }
                    }
                    final String cmdLine = new String(bytes, StandardCharsets.UTF_8);
                    if (cmdLine.contains(processName)) {
                        return true;
                    }
                } catch (IOException e) {
                    // the proc may end during the loop, ignore it
                    log.error("read file exception ", e);
                }
            }
            return false;
        }
    

    go

    func ProcessExists(processName string) (bool, error) {
        result := false
        fileInfos, err := ioutil.ReadDir("/proc")
        if err != nil {
            return false, err
        }
        for _, info := range fileInfos {
            name := info.Name()
            matched, err := regexp.MatchString("[0-9]+", name)
            if err != nil {
                return false, err
            }
            if !matched {
                continue
            }
            cmdLine, err := parseCmdLine("/proc/" + info.Name() + "/cmdline")
            if err != nil {
                glog.Error("read cmd line failed ", err)
                // the proc may end during the loop, ignore it
                continue
            }
            if strings.Contains(cmdLine, processName) {
                result = true
            }
        }
        return result, err
    }
    
    func parseCmdLine(path string) (string, error) {
        cmdData, err := ioutil.ReadFile(path)
        if err != nil {
            return "", err
        }
        if len(cmdData) < 1 {
            return "", nil
        }
    
        split := strings.Split(string(bytes.TrimRight(cmdData, string("\x00"))), string(byte(0)))
        return strings.Join(split, " "), nil
    }
    

    相关文章

      网友评论

          本文标题:比调用Shell更高效的判断进程是否存在的方式

          本文链接:https://www.haomeiwen.com/subject/drwlbltx.html