模仿nginx修改进程名

本文介绍了如何通过修改C程序中的argv[0]来改变进程名,但需注意新名称过长可能覆盖环境变量environ。推荐使用setproctitle库,避免此类问题,并给出了相关源码示例。
摘要由CSDN通过智能技术生成

个人博客原文: https://rebootcat.com/2020/10/25/setproctitle/

nginx 进程名

使用 nginx 的过程中,我们经常看到 nginx 的进程名是不同的,如下:

$ ps -ef |grep nginx 
smaug    1183  1115  0 05:46 pts/2    00:00:00 grep --color=auto nginx
root     14201     1  0  2019 ?        00:00:00 nginx: master process ./sbin/nginx
nobody   28887 14201  0 Oct14 ?        00:00:00 nginx: worker process
nobody   28888 14201  0 Oct14 ?        00:00:00 nginx: worker process

可以看到 nginx 的进程名是不同的,那么它是怎么做到的呢?

argv[0]

首先来看一下 C 语言中的 main 函数的定义:

int main(int argc, char *argv[]);

这个应该大家都是比较熟悉的,argc 表示命令行参数个数, argv 保存了各个命令行参数的内容。其中 argv[0] 表示的是进程的名字,这就是修改进程名的关键点所在。

只需要修改 argv[0] 的值即可完成修改进程名

hello world

下面以程序员经典入门代码为例说明:

// filename: hello_world_setproctitle.cc
// build: g++ hello_world_setproctitle.cc -o hello_world_setproctitle

#include <cstdio>
#include <cstring>

int main(int argc, char *argv[]) {
    printf("hello world\n");
    while (true) {
        // block here
        char c = getchar();
    }
    return 0;
}

编译运行:

g++ hello_world_setproctitle.cc -o hello_world_setproctitle
./hello_world_setproctitle

查看一下进程名:

# ps -ef |grep hello_world
root     26356 12289  0 14:17 pts/3    00:00:00 ./hello_world_setproctitle
root     26366 20422  0 14:18 pts/1    00:00:00 grep --color=auto hello_world

可以看到进程名是 hello_world_setproctitle,接下来我们修改一下 argv[0] 的值,代码如下:

// filename: hello_world_setproctitle.cc
// build: g++ hello_world_setproctitle.cc -o hello_world_setproctitle

#include <cstdio>
#include <cstring>

int main(int argc, char *argv[]) {
    // new process name
    const char* new_name = "new_new_hello_world_setproctitle";
    strcpy(argv[0], new_name);
    printf("hello world\n");
    while (true) {
        // block here
        char c = getchar();
    }
    return 0;
}

编译运行之后,查看进程名:

# ps -ef |grep hello_world
root     26750 12289  0 14:23 pts/3    00:00:00 new_new_hello_world_setproctitle
root     26754 20422  0 14:23 pts/1    00:00:00 grep --color=auto hello_world

可以看到进程名已经修改为 new_new_hello_world_setproctitle 了。

是不是很简单?

不过上面的代码是有一定的风险的,如果新的进程名超过了原来 argv[0] 的长度,就可能会影响到后面的 environ 的内容

环境变量 environ

C 语言中 main 函数的定义还有一个:

int main(int argc, char *argv[], char *envp[]);

这个版本提供了第三个参数,大多数 Unix 系统支持,但是 POSIX.1 不建议这么做,如果要访问环境变量建议使用 getenvputenv 接口。这里就不展开讲了。

envp 这个参数表示环境变量,每一个进程都有与之相关的环境变量,其中每个字符串都以(name=value)形式定义,并且 envp 的地址紧跟在 argv 之后

hello world environ

接下来我们打印一下 envp 这个参数的值,基于上面的代码,简单修改一下:

// filename: hello_world_setproctitle.cc
// build: g++ hello_world_setproctitle.cc -o hello_world_setproctitle

#include <cstdio>
#include <cstring>

int main(int argc, char *argv[], char *envp[]) {
    int i;
    for (i = 0; i < argc; ++i) {
        printf("mem:%p len:%d argv[%d]: %s\n", argv[i], strlen(argv[i]), i, argv[i]);
    }
    printf("\n");
    for (i = 0; envp[i] != NULL; ++i) {
        printf("mem:%p len:%d envp[%d]: %s\n", envp[i], strlen(envp[i]), i, envp[i]);
    }

    const char* new_name = "new_new_hello_world_setproctitle";
    strcpy(argv[0], new_name);
    printf("hello world\n");
    while (true) {
        // block here
        char c = getchar();
    }
    return 0;
}

上面的代码同时也打印了每个参数的地址以及长度,编译并执行:

# ./hello_world_setproctitle 1 22
mem:0x7ffc84cf7544 len:26 argv[0]: ./hello_world_setproctitle
mem:0x7ffc84cf755f len:1 argv[1]: 1
mem:0x7ffc84cf7561 len:2 argv[2]: 22

mem:0x7ffc84cf7564 len:19 envp[0]: XDG_SESSION_ID=2554
mem:0x7ffc84cf7578 len:13 envp[1]: HOSTNAME=Jiao
mem:0x7ffc84cf7586 len:23 envp[2]: SELINUX_ROLE_REQUESTED=
mem:0x7ffc84cf759e len:19 envp[3]: TERM=xterm-256color
mem:0x7ffc84cf75b2 len:15 envp[4]: SHELL=/bin/bash
mem:0x7ffc84cf75c2 len:13 envp[5]: HISTSIZE=1000
mem:0x7ffc84cf75d0 len:31 envp[6]: SSH_CLIENT=192.168.1.3 61311 22
mem:0x7ffc84cf75f0 len:26 envp[7]: SELINUX_USE_CURRENT_RANGE=
mem:0x7ffc84cf760b len:75 envp[8]: ANDROID_NDK_TOOLCHAIN_ROOT=/root/smaug/software/android-ndk-r16b/toolchains
mem:0x7ffc84cf7657 len:12 envp[9]: OLDPWD=/root
mem:0x7ffc84cf7664
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值