!include once #1034919 // Include OSHI library 6.1.5 import oshi.util.*; import oshi.software.os.*; import oshi.software.os.OSProcess; import oshi.software.os.linux.*; import oshi.software.os.linux.LinuxOperatingSystem.ProcPidStat; import oshi.util.platform.linux.ProcUtil; import oshi.software.os.OperatingSystem.ProcessSort; static OSProcess[] oshi_listProcesses_withoutOpenFiles(int limit, ProcessSort sort) { new L procs; File[] pids = ProcUtil.getPidFiles(); // now for each file (with digit name) get process info for (File pid : pids) { OSProcess proc = oshi_getProcess_withoutOpenFiles(ParseUtil.parseIntOrDefault(pid.getName(), 0)); if (proc != null) procs.add(proc); } List sorted = processSort(procs, limit, sort); return sorted.toArray(new OSProcess[sorted.size()]); } static OSProcess oshi_getProcess_withoutOpenFiles(int pid) { String path = ""; Pointer buf = new Memory(1024); int size = Libc.INSTANCE.readlink(String.format("/proc/%d/exe", pid), buf, 1023); if (size > 0) { path = buf.getString(0).substring(0, size); } Map io = FileUtil.getKeyValueMapFromFile(String.format("/proc/%d/io", pid), ":"); // See man proc for how to parse /proc/[pid]/stat long now = System.currentTimeMillis(); String stat = FileUtil.getStringFromFile(String.format("/proc/%d/stat", pid)); // A race condition may leave us with an empty string if (stat.isEmpty()) null; new OSProcess proc; // We can get name and status more easily from /proc/pid/status which we // call later, so just get the numeric bits here proc.setProcessID(pid); int[] PROC_PID_STAT_ORDERS = cast get(oshi_operatingSystem(), 'PROC_PID_STAT_ORDERS); long[] statArray = ParseUtil.parseStringToLongArray(stat, PROC_PID_STAT_ORDERS, procPidStatLength, ' '); proc.setParentProcessID((int) statArray[ProcPidStat.PPID.ordinal()]); proc.setThreadCount((int) statArray[ProcPidStat.THREAD_COUNT.ordinal()]); proc.setPriority((int) statArray[ProcPidStat.PRIORITY.ordinal()]); proc.setVirtualSize(statArray[ProcPidStat.VSZ.ordinal()]); proc.setResidentSetSize(statArray[ProcPidStat.RSS.ordinal()] * this.memoryPageSize); proc.setKernelTime(statArray[ProcPidStat.KERNEL_TIME.ordinal()] * 1000L / USER_HZ); proc.setUserTime(statArray[ProcPidStat.USER_TIME.ordinal()] * 1000L / USER_HZ); long BOOT_TIME = cast getOpt(oshi_operatingSystem(), 'BOOT_TIME); proc.setStartTime(BOOT_TIME + statArray[ProcPidStat.START_TIME.ordinal()] * 1000L / USER_HZ); // BOOT_TIME could be up to 5ms off. In rare cases when a process has // started within 5ms of boot it is possible to get negative uptime. if (proc.getStartTime() >= now) { proc.setStartTime(now - 1); } proc.setUpTime(now - proc.getStartTime()); // See man proc for how to parse /proc/[pid]/io proc.setBytesRead(ParseUtil.parseLongOrDefault(MapUtil.getOrDefault(io, "read_bytes", ""), 0L)); proc.setBytesWritten(ParseUtil.parseLongOrDefault(MapUtil.getOrDefault(io, "write_bytes", ""), 0L)); // gets the open files count List openFilesList = ExecutingCommand.runNative(String.format("ls -f /proc/%d/fd", pid)); proc.setOpenFiles(openFilesList.size() - 1L); Map status = FileUtil.getKeyValueMapFromFile(String.format("/proc/%d/status", pid), ":"); proc.setName(MapUtil.getOrDefault(status, "Name", "")); proc.setPath(path); switch (MapUtil.getOrDefault(status, "State", "U").charAt(0)) { case 'R': proc.setState(OSProcess.State.RUNNING); break; case 'S': proc.setState(OSProcess.State.SLEEPING); break; case 'D': proc.setState(OSProcess.State.WAITING); break; case 'Z': proc.setState(OSProcess.State.ZOMBIE); break; case 'T': proc.setState(OSProcess.State.STOPPED); break; default: proc.setState(OSProcess.State.OTHER); break; } proc.setUserID(ParseUtil.whitespaces.split(MapUtil.getOrDefault(status, "Uid", ""))[0]); proc.setGroupID(ParseUtil.whitespaces.split(MapUtil.getOrDefault(status, "Gid", ""))[0]); LinuxUserGroupInfo userGroupInfo = cast get(oshi_operatingSystem(), 'userGroupInfo); OSUser user = userGroupInfo.getUser(proc.getUserID()); if (user != null) proc.setUser(user.getUserName()); proc.setGroup(userGroupInfo.getGroupName(proc.getGroupID())); // THe /proc/pid/cmdline value is null-delimited proc.setCommandLine(FileUtil.getStringFromFile(String.format("/proc/%d/cmdline", pid))); pcall { String cwdLink = String.format("/proc/%d/cwd", pid); String cwd = new File(cwdLink).getCanonicalPath(); if (!cwd.equals(cwdLink)) { proc.setCurrentWorkingDirectory(cwd); } } ret proc; }