Linux下列表所有进程、根据进程名得到pid和根据pid得到进程名

本文介绍了一种在Linux系统中获取当前所有运行进程信息的方法,通过遍历/proc目录下的子目录来收集每个进程的状态,包括PID、PPID和进程名。同时,提供了查找特定进程名对应的PID及根据PID获取进程名的C语言实现。

Linux下的当前正在运行的进程信息均存放在/proc目录下,有一系列以数字为名的子目录,每一个子目录对应一个进程,子目录名就是进程的pid。子目录下的status文件内容就是进程的基本信息,包括进程名、pid、ppid等。因此,若要扫描系统当前正在运行的所有进程,只需要遍历/proc目录下所有以数字为名的子目录下的status即可。据此,可得到获取当前系统所有进程快照、根据pid获得进程名和根据进程名获得pid的程序,如下所示:

#include <sys/types.h>
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define BUF_SIZE 1024
#define MAX_PROCESS_PATH 1024
#define PROC_NAME_FIELD ("name:")
#define PARENT_PID_FIELD ("ppid:")

#ifndef __cplusplus
typedef enum {false, true} bool;
#endif // __cplusplus

typedef struct __tagProcessEntry
{
   pid_t pid;
   pid_t ppid;
   char processName[MAX_PROCESS_PATH];
} ProcessEntry;

void string2lower(const char src[], char dest[])
{
   int length = strlen(src);
   int index;
   for(index = 0; index < length; index ++)
   {
      dest[index] = ((src[index] >= 'A') && (src[index] <= 'Z')) ? src[index] + 0x20 : src[index];
   }
   dest[length] = '\0';
}

int createProcessSnapshot(ProcessEntry pes[], int maxCount)
{
   int processCount = 0;
   DIR *dir;
   struct dirent *dirEntry;
   FILE *fp;
   char filePath[MAX_PROCESS_PATH];
   char fieldName[32];
   char fieldValue[MAX_PROCESS_PATH];
   char buf[BUF_SIZE];

   dir = opendir("/proc");
   if (NULL != dir)
   {
      while((dirEntry = readdir(dir)) != NULL) //循环读取路径下的每一个文件/文件夹
      {
         //如果读取到的是"."或者".."则跳过,读取到的不是文件夹名字也跳过
         if ((strcmp(dirEntry->d_name, ".") == 0) || (strcmp(dirEntry->d_name, "..") == 0) || (DT_DIR != dirEntry->d_type))
         {
            continue;
         }

         sprintf(filePath, "/proc/%s/status", dirEntry->d_name); //生成要读取的文件的路径
         fp = fopen(filePath, "r");
         if (NULL != fp)
         {
            do {
               if (fgets(buf, BUF_SIZE - 1, fp) == NULL)
               {
                  break;
               }
               sscanf(buf, "%s %s", fieldName, fieldValue);
               string2lower(fieldName, fieldName);
               if (strcmp(fieldName, PROC_NAME_FIELD) == 0)
               {
                  strcpy(pes[processCount].processName, fieldValue);
               }
               else if (strcmp(fieldName, PARENT_PID_FIELD) == 0)
               {
                  pes[processCount].ppid = atoi(fieldValue);
               }
            } while(!feof(fp));
            fclose(fp);

            pes[processCount].pid = atoi(dirEntry->d_name);
            processCount ++;
            if (processCount >= maxCount)
            {
               break;
            }
         }
      }
      closedir(dir);
   }
   return processCount;
}

int getPidByName(const char *procName, pid_t pids[], int maxCount)
{
   DIR *dir;
   struct dirent *dirEntry;
   FILE *fp;
   char filePath[MAX_PROCESS_PATH];
   char currProcName[MAX_PROCESS_PATH];
   char buf[BUF_SIZE];
   int pidCount = 0;

   dir = opendir("/proc");
   if (NULL != dir)
   {
      while((dirEntry = readdir(dir)) != NULL) //循环读取路径下的每一个文件/文件夹
      {
         //如果读取到的是"."或者".."则跳过,读取到的不是文件夹名字也跳过
         if ((strcmp(dirEntry->d_name, ".") == 0) || (strcmp(dirEntry->d_name, "..") == 0) || (DT_DIR != dirEntry->d_type))
         {
            continue;
         }

         sprintf(filePath, "/proc/%s/status", dirEntry->d_name); //生成要读取的文件的路径
         fp = fopen(filePath, "r"); //打开进程描述文件
         if (NULL != fp)
         {
            if (fgets(buf, BUF_SIZE - 1, fp) == NULL)
            {
               fclose(fp);
               continue;
            }
            sscanf(buf, "%*s %s", currProcName);

            if (strcmp(procName, currProcName) == 0)
            {
               pids[pidCount] = atoi(dirEntry->d_name);
               pidCount ++;
               if (pidCount >= maxCount)
               {
                  break;
               }
            }
            fclose(fp);
         }
      }
      closedir(dir);
   }
   return pidCount;
}

bool getNameByPid(pid_t pid, char procName[])
{
   char pidPath[BUF_SIZE];
   char buf[BUF_SIZE];
   bool success = false;

   sprintf(pidPath, "/proc/%d/status", pid);
   FILE *fp = fopen(pidPath, "r");
   if (NULL != fp)
   {
      if (fgets(buf, BUF_SIZE - 1, fp) != NULL)
      {
         sscanf(buf, "%*s %s", procName);
         success = true;
      }
      else
      {
         success = false;
      }
      fclose(fp);
   }

   return success;
}

int main(int argc, char **argv)
{
   char procName[MAX_PROCESS_PATH];
   pid_t pids[32];
   ProcessEntry pes[1024];

   pid_t currPid = getpid();
   printf("pid of this process:%d\n", currPid);
   getNameByPid(currPid, procName);
   printf("task name is %s\n", procName);
   strcpy(procName, "eclipse");
   int pidCount= getPidByName(procName, pids, sizeof pids / sizeof pids[0]);
   for(int index = 0; index < pidCount; index ++)
   {
      printf("pid of process %s: %d\n", procName, pids[index]);
   }

   int procCnt = createProcessSnapshot(pes, sizeof pes / sizeof pes[0]);
   printf("%d processes found.\n", procCnt);
   for(int index = 0; index < procCnt; index ++)
   {
      printf("proc: %-16s, pid: %6d, ppid: %6d.\n", pes[index].processName, pes[index].pid, pes[index].ppid);
   }

   return 0;
}

上述代码大部分源于网上材料,我在这里只是整理了一下,做为笔记。

<think>好的,用户想了解Linux下查询日志进程的基础命令。我需要分步骤来整理这些信息,确保结构清晰。首先,确定用户可能需要哪些常用命令,比如查看实时日志的tail、搜索日志的grep,还有进程相关的ps、top等。 接下来,要区分日志查询进程管理两部分。日志部分,常用的有tail、head、cat、grep、less、journalctl这些命令。需要给出每个命令的典型用法常见参数,比如tail -f跟踪日志,grep过滤特定关键字。同时,可能需要提醒用户权限问题,比如某些日志需要sudo。 然后是进程管理,主要命令包括ps、top、htop、pidof、kill、pkill、pgrep。这里需要解释每个命令的作用,例如ps aux查看所有进程,top实时监控,kill终止进程的不同信号。另外,像htop这种交互式工具可能用户更友好,但需要安装。 还要注意用户可能的实际应用场景,比如查找特定进程PID,或者如何终止进程。组合命令的例子可能会有帮助,比如管道符结合grep过滤结果。此外,journalctl是systemd系统的日志工具,需要说明其用法过滤选项。 需要检查是否有遗漏的基础命令,比如netstat或lsof虽然属于网络相关,但可能进程有关联,不过用户问题聚焦在日志进程,暂时可以不深入。确保每个命令的例子正确,比如ps aux的正确用法,kill -9的注意事项。 最后,整理结构,先分日志查询进程管理两大部分,每个部分下列出命令,每个命令有基本说明、常用参数示例。保持语言简洁,用中文,避免术语混淆。可能用户是刚入门的开发者或系统管理员,所以例子要具体实用,比如用grep找error信息,用kill终止进程。 另外,注意系统级指令中的格式要求,行内数学公式用$...$,但当前内容不涉及数学公式,所以可能不需要处理。但需要确认回答中的代码或命令格式是否正确,使用反引号或等宽字体,但根据用户的要求,可能只需正确使用代码块或命令行示例。不过用户没有特别要求代码格式,所以保持自然的中文描述,适当使用反引号突出命令。 总结下来,分两部分,每个命令简要说明、常用参数、示例,最后可能给出组合使用的例子,帮助用户解决实际问题。确保内容准确,比如journalctl的使用前提是系统使用systemd,这点需要提及。同时,检查命令参数是否正确,比如tail -nhead -n的正确用法。</think>### Linux 查询日志进程的基础命令 以下是查询日志管理进程的常用命令及操作指南,按场景分类: --- #### **一、日志查询命令** 日志文件通常位于 `/var/log/` 目录下(如 `/var/log/syslog`, `/var/log/nginx/access.log` 等)。 1. **`tail` - 查看日志尾部内容** - **基础用法**: ```bash tail -n 20 /var/log/syslog # 查看最后20行 tail -f /var/log/nginx/access.log # 实时跟踪日志更新(常用) ``` 2. **`grep` - 按关键字过滤日志** - **基础用法**: ```bash grep "error" /var/log/syslog # 搜索包含 "error" 的行 grep -i "timeout" /var/log/app.log # 忽略大小写搜索 grep -C 3 "crash" /var/log/syslog # 显示匹配行及其前后3行 ``` 3. **`less` - 分页查看日志** - **基础用法**: ```bash less /var/log/long.log # 进入分页模式 # 快捷键:空格(下一页),/关键词(搜索),q(退出) ``` 4. **`journalctl` - 查看系统日志(systemd 系统专用)** - **基础用法**: ```bash journalctl -u nginx.service # 查看 nginx 服务的日志 journalctl --since "2024-01-01" # 按时间过滤 journalctl -f # 实时跟踪日志 ``` --- #### **二、进程管理命令** 1. **`ps` - 查看当前进程** - **基础用法**: ```bash ps aux # 查看所有进程(常用) ps -ef | grep nginx # 结合管道过滤进程 ``` 2. **`top` / `htop` - 实时监控进程状态** - **基础用法**: ```bash top # 动态显示进程资源占用(CPU、内存等) htop # 增强版 top(需安装:sudo apt install htop) # 快捷键:q(退出),k(杀死进程),F(按字段排序) ``` 3. **`pidof` / `pgrep` - 获取进程 PID** - **基础用法**: ```bash pidof nginx # 直接获取进程 PID pgrep -f "python" # 按进程或参数搜索 PID ``` 4. **`kill` - 终止进程** - **基础用法**: ```bash kill 1234 # 向 PID 1234 发送终止信号(默认 SIGTERM) kill -9 1234 # 强制终止进程(SIGKILL) pkill nginx # 按进程终止 ``` --- #### **三、组合使用示例** 1. **查找并终止进程** ```bash ps aux | grep "python" # 找到 Python 进程PID kill -9 $(pidof python) # 强制终止所有 Python 进程 ``` 2. **实时跟踪特定服务的日志** ```bash tail -f /var/log/nginx/access.log | grep "404" ``` --- #### **注意事项** - **权限问题**:部分日志文件需 `sudo` 权限查看(如 `/var/log/auth.log`)。 - **日志轮转**:日志可能被压缩或归档(如 `*.gz`),需使用 `zcat` 或 `zless` 查看。 - **进程信号**:`kill -9` 是强制终止,优先尝试 `kill -15`(默认)允许进程清理资源。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值