在 Linux 中更改进程名称

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6082189/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 04:12:01  来源:igfitidea点击:

Change process name in Linux

clinuxprocess

提问by Frank Vilea

I'm on Linux and I am forking/execing a new process out of my C spawn application. Is it possible to also change the naming of these new child processes?

我在 Linux 上,我正在从我的 C spawn 应用程序中分叉/执行一个新进程。是否也可以更改这些新子进程的命名?

I want to be able to identify the process being started in case something goes wrong and I need to kill it manually. Currently they all have the same name.

我希望能够识别正在启动的进程,以防出现问题并且我需要手动终止它。目前,它们都具有相同的名称。

采纳答案by Amadan

I think this should work, to illustrate the principle...

我认为这应该有效,以说明原理......

#include <stdio.h>

int main(int argc, char *argv[]) {
  argv[0][0] = 65;
  sleep(10);
}

will change the name, and put an "A" instead of the first letter. CtrlZ to pause, then run psto see the name changed. I have no clue, but it seems somewhat dangerous, since some things might depend on argv[0].

将更改名称,并放置一个“A”而不是第一个字母。CtrlZ 暂停,然后运行ps以查看名称已更改。我不知道,但这似乎有点危险,因为有些事情可能取决于argv[0].

Also, I tried replacing the pointer itself to another string; no cigar. So this would only work with strcpyand strings shorter or equal than the original name.

另外,我尝试将指针本身替换为另一个字符串;没有雪茄。因此,这仅适用于strcpy比原始名称更短或相等的字符串。

There might or might not be a better way for this. I don't know.

可能有也可能没有更好的方法。我不知道。

EDIT: nonliteral solution: If you're forking, you know the child's PID (getpid()in the child, result of fork()in the parent). Just output it somewhere where you can read it, and kill the child by PID.

编辑:非文字解决方案:如果您要分叉,您就知道孩子的 PID(getpid()在孩子中,fork()在父母中的结果)。只需将其输出到您可以阅读的地方,然后通过 PID 杀死孩子。

another nonliteral solution: make softlinks to the executable with another name (ln -s a.out kill_this_a.out), then when you exec, exec the link. The name will be the link's name.

另一个非文字解决方案:使用另一个名称 ( ln -s a.out kill_this_a.out)制作指向可执行文件的软链接,然后在执行时执行链接。该名称将是链接的名称。

回答by Mukesh Chauhan

The below code sample would change the name of the process to "Testing".

下面的代码示例会将进程的名称更改为“测试”。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    int main (int argc, char *argv[]) {
    char* temp = (char*) malloc (20);
    strcpy(temp, "Testing");
    temp[7] = 0;
    printf("Argv[0] --> %s\n", argv[0]);
    argv[0] = temp;
    printf("Argv[0] --> %s\n", argv[0]);    
    return 0;
    }

The output of above program is:

上述程序的输出为:

./a.out

./a.out

Argv[0] --> ./a.out

Argv[0] --> ./a.out

Argv[0] --> Testing

Argv[0] --> 测试

The argv[0] contains the name of the process.

argv[0] 包含进程的名称。

回答by nitrogen

One of the comments mentions prctl, but this really deserves its own answer, because setting argv[0]will not work in all cases (it does nothing on my system).

评论之一提到了prctl,但这确实值得自己回答,因为设置argv[0]在所有情况下都不起作用(它在我的系统上没有任何作用)。

There are at least two library calls to set the name of a thread in Linux, both limited to 15 characters plus the terminating NULbyte:

在 Linux 中至少有两个库调用来设置线程的名称,都限制为 15 个字符加上终止NUL字节:

  1. glibc-specific: pthread_setname_np(...)where the npstands for "non-portable", but this might be present on some other OSes: https://linux.die.net/man/3/pthread_setname_np
  2. Linux-specific: prctl(PR_SET_NAME...)which is also non-portable: https://linux.die.net/man/2/prctl
  1. glibc 特定:pthread_setname_np(...)其中np代表“不可移植”,但这可能存在于其他一些操作系统上:https: //linux.die.net/man/3/pthread_setname_np
  2. 特定于 Linux:prctl(PR_SET_NAME...)这也是不可移植的:https: //linux.die.net/man/2/prctl


Example

例子

Here's a test of the different methods (with no error handling):

这是对不同方法的测试(没有错误处理):

// gcc pstest.c -o pstest -O2 -Wall -Wextra -Werror -Wno-unused -Wno-unused-result -std=gnu99 -pthread -D_GNU_SOURCE 
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/prctl.h>

int main(int argc, char *argv[])
{
    puts("Initial ps output:");
    system("ps | grep pstest");

    puts("\npthread_setname_np");
    pthread_setname_np(pthread_self(), "setname");
    system("ps | grep setname");

    puts("\nprctl");
    prctl(PR_SET_NAME, (unsigned long)"prctl", 0, 0, 0);
    system("ps | grep prctl");

    puts("\nargv[0]");
    argv[0] = "argv0";
    system("ps | grep argv0");

    return 0;
}

Notice the lack of output after argv[0]:

请注意以下之后缺少输出argv[0]

./pstest
Initial ps output:
17169 pts/0    00:00:00 pstest

pthread_setname_np
17169 pts/0    00:00:00 setname

prctl
17169 pts/0    00:00:00 prctl

argv[0]

In the wild

在野外

Here's an example in production code(as always, be sure to take note of the license when looking at code on GitHub)

这是生产代码中的示例(与往常一样,在 GitHub 上查看代码时一定要注意许可证)

See also

也可以看看

See also these questions and answers:

另请参阅这些问题和答案:

回答by hexchain

According to this comment, prctl(PR_SET_NAME)only affects the "short name" of a thread. It has the same effect as writing into /proc/self/comm.

根据此评论prctl(PR_SET_NAME)仅影响线程的“短名称”。它与写入/proc/self/comm.

To change the "long name" (/proc/self/cmdlinewhich is actually used by htopand ps u) you need some ugly hack (which is mentioned in that comment but the link is dead). An example of this kind of hack can be found in Chromium source code: https://cs.chromium.org/chromium/src/services/service_manager/embedder/set_process_title_linux.cc?sq=package:chromium&g=0

要更改“长名称”(/proc/self/cmdline实际上由htop和 使用ps u),您需要一些丑陋的技巧(该评论中提到了这一点,但链接已失效)。可以在 Chromium 源代码中找到此类 hack 的示例:https: //cs.chromium.org/chromium/src/services/service_manager/embedder/set_process_title_linux.cc?sq=package:chromium &g=0

回答by fadedbee

This is a non-portable hack:

这是一个非便携式黑客:

/*
 * Sets process title, truncating if there is not enough space, 
 * rather than causing memory corruption.
 */
void set_title_np(int argc, char **argv, const char *title) {
    // calculate available size
    size_t space = 0;
    for (int i = 0; i < argc; i++) {
        size_t length = strlen(argv[i]);
        space += length + 1; // because of terminating zero 
    }
    memset(argv[0], '##代码##', space); // wipe existing args
    strncpy(argv[0], title, space - 1); // -1: leave null termination, if title bigger than space
}