Search code examples
clinuxdebiannice

Change niceness of all processes by niceness


I am using Debian, is there a way to change the niceness of all running process based on their current niceness? For instance change all currently running processes that have a niceness of -20 or -19 to -10. Renice can change a process, and processes for certain users. But as far as I can tell it can't do it based on current niceness.

I am trying to run a program with -20 niceness to try and get around some timing spikes that seem to occur semi-regularly. These might be caused by certain processes with the same priority taking resources. I was hoping to check this with some niceness fiddling.


Solution

  • Something to start with in C:

    #include <stdio.h>
    #include <sys/types.h>
    #include <dirent.h>
    #include <stdlib.h>
    #include <string.h>
    
    static char *prstatname(char *buf, char **endptr)
    {
        /* parse process name */
        char *ptr = buf;
        while (*ptr && *ptr != '(') ++ptr;
        ++ptr;
        if (!ptr) return 0;
    
        char *name = ptr;
        while (*ptr)
        {
            if (*ptr == ')' && *(ptr+1) && *(ptr+2) && *(ptr+3)
                    && *(ptr+1) == ' ' && *(ptr+3) == ' ')
            {
                *ptr = 0;
                *endptr = ptr + 1;
                return name;
            }
            ++ptr;
        }
        return 0;
    }
    
    int main(void)
    {
        DIR *proc = opendir("/proc");
        if (!proc) return 1;
    
        struct dirent *ent;
    
        while ((ent = readdir(proc)))
        {
            /* check whether filename is all numeric, then it's a process id */
            char *endptr;
            int pid = strtol(ent->d_name, &endptr, 10);
            if (*endptr) continue;
    
            /* combine to '/proc/{pid}/stat' to get information about process */
            char statname[64] = {0,};       
            strcat(statname, "/proc/");
            strncat(statname, ent->d_name, 52);
            strcat(statname, "/stat");
    
            FILE *pstat = fopen(statname, "r");
            if (!pstat) continue;
    
            /* try to read process info */
            char buf[1024];
            if (!fgets(buf, 1024, pstat))
            {
                fclose(pstat);
                continue;
            }
            fclose(pstat);
    
            char *name = prstatname(buf, &endptr);
            if (!name) continue;
    
            /* nice value is in the 17th field after process name */
            int i;
            char *tok = strtok(endptr, " ");
            for (i = 0; tok && i < 16; ++i) tok = strtok(0, " ");
            if (!tok || i < 16) continue;
    
            int nice = strtol(tok, &endptr, 10);
            if (*endptr) continue;
    
            printf("[%d] %s -- nice: %d\n", pid, name, nice);
        }
    }
    

    If you understand this program, you can easily modify it to do what you wanted.