这是blade问的一个问题,一个python脚本会fork出很多子进程一起工作,想能够一种方法同时kill掉这些脚本进程。
因为是python脚本,不能简单通过killall的方式来搞,因为可能还有其他python脚本运行。一种变通的方法就是grep出特定的python脚本执行进程,然后挨个的kill掉,很山寨啊。
能否有些优雅的方式来搞定这个事情呢,忽然想起似乎有api可以设置进程的名字,如果python脚本设置了进程层的名字的话,这样就可以与其他的python脚本进程区分开来了。
注意进程title和进程name是有区别的,通过strace查看ps和killall执行的系统调用,可以看出进程title是通过/proc/$pid/cmdline读取的,进程name通过/proc/$pid/stat读取的。
cmdline记录的是一个程序的启动参数,包括程序名&参数,就是argv[]的内容,如果要修改进程title,也就是要修改进程cmdline,修改进程的argv[],把argv[0]改为需要修改的title,argv[1]设置为NULL。【不考虑title超长的情况】
我们ps aux看到的是进程的title,killall使用的是进程的name,使用ps -e -o pid= -o comm=可以查看全部进程的pid和name。
参数argv和环境变量在连续的存储空间,如果贸然修改argv[0]可能会破坏这部分内存结构,因为title的长度不确定,如果太长了就修改了环境变量的内存区域。解决方案是重新给环境变量申请内存区域,然后将环境变量复制过去(environ是全局变量)。
【后记】ptcrl可以通过PR_SET_PDEATHSIG选项来设置父进程挂掉后向子进程发送XX信号。例如accord中
- /* flush on daemon's crash */
-
sa_new.sa_handler = (void*)log_sigsegv;
-
sigemptyset(&sa_new.sa_mask);
-
sa_new.sa_flags = 0;
-
sigaction(SIGSEGV, &sa_new, &sa_old );
-
-
prctl(PR_SET_PDEATHSIG, SIGSEGV);
示例代码
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <sys/prctl.h>
#ifndef PR_SET_NAME
#define PR_SET_NAME 15
#endif
#ifndef PR_GET_NAME
#define PR_GET_NAME 16
#endif
static char *arg_start;
static char *arg_end;
static char *env_start;
void init_proc_title(int argc, char **argv) {
int i;
arg_start = argv[0];
arg_end = argv[argc-1] + strlen(argv[argc-1])+1;
env_start = environ[0];
for(i=0; i<argc; i++)
argv[i] = strdup(argv[i]);
}
void set_proc_title(const char *title) {
int tlen = strlen(title)+1;
int i;
char *p;
if(arg_end-arg_start < tlen && env_start==arg_end) {
char *env_end = env_start;
for(i=0; environ[i]; i++) {
if(env_end == environ[i]) {
env_end = environ[i] + strlen(environ[i]) + 1;
environ[i] = strdup(environ[i]);
} else
break;
}
arg_end = env_end;
env_start = NULL;
}
i = arg_end - arg_start;
if(tlen==i) {
strcpy(arg_start, title);
} else if(tlen < i) {
strcpy(arg_start, title);
memset(arg_start+tlen, 0, i-tlen);
// 1、当要更改的进程名称串比原始进程名称串短时,填充argv[0]字段时,改为填充argv[0]区的后段,前段填充0
memset(arg_start,0,i);
strcpy(arg_start + (i - tlen),title);
} else {
*(char *)mempcpy(arg_start, title, i-1) = '\0';
}
if(env_start) {
p = strchr(arg_start, ' ');
if(p) *p = '\0';
}
}
void set_proc_name(const char *name) {
prctl(PR_SET_NAME, name);
}
void get_proc_name(char *name) {
prctl(PR_GET_NAME, name);
}
int main(int argc, char *argv[])
{
int ret = 0;
pid_t orig_pid = getpid();
for(int i=0; i<3; i++)
{
pid_t pid = fork();
if(pid==0)
{
prctl(PR_SET_PDEATHSIG, SIGHUP);
break;
}
}
if(getpid()==orig_pid)
{
const char *proc_title = "t_title";
const char *proc_name = "t_name";
init_proc_title(argc,argv);
set_proc_title(proc_title);
set_proc_name (proc_name);
}
while(1)
{
//printf("In pid: %d\n", getpid());
sleep(5);
}
return 0;
} |
阅读(11821) | 评论(0) | 转发(0) |