Change process name in Linux

前端 未结 5 2048
被撕碎了的回忆
被撕碎了的回忆 2021-01-03 21:50

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?

I want to

相关标签:
5条回答
  • 2021-01-03 22:08

    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], '\0', space); // wipe existing args
        strncpy(argv[0], title, space - 1); // -1: leave null termination, if title bigger than space
    } 
    
    0 讨论(0)
  • 2021-01-03 22:10

    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).

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

    1. glibc-specific: pthread_setname_np(...) where the np stands 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

    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]:

    ./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)

    See also

    See also these questions and answers:

    • https://unix.stackexchange.com/questions/167490/how-can-a-process-appear-to-have-different-name-in-ps-output
    • Using prctl PR_SET_NAME to set name for process or thread?
    0 讨论(0)
  • 2021-01-03 22:17

    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 ps to see the name changed. I have no clue, but it seems somewhat dangerous, since some things might depend on argv[0].

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

    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.

    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.

    0 讨论(0)
  • 2021-01-03 22:26

    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.

    To change the "long name" (/proc/self/cmdline which is actually used by htop and 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

    0 讨论(0)
  • 2021-01-03 22:28

    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

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

    Argv[0] --> Testing

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

    0 讨论(0)
提交回复
热议问题