Change process name in Linux
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:
- glibc-specific:
pthread_setname_np(...)
where thenp
stands for "non-portable", but this might be present on some other OSes: https://linux.die.net/man/3/pthread_setname_np - 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?
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.
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
}
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://source.chromium.org/chromium/chromium/src/+/master:content/common/set_process_title_linux.cc