1

For the first question I tried:

ps -le | tail -n+2 | awk '{if($7>80)print $7}' | wc --lines

and

ps -eo pri | tail -n+2 | awk '{if($1>80) print}' | wc --lines  

Surprisingly both gave different results and I don't know which one is correct and why.

For the second I don't have any ideas. Any help will be appreciated.

  • 3
    This is two questions. The second has an answer here [How to search for all SUID/SGID files?](https://unix.stackexchange.com/questions/254953/how-do-you-find-all-files-and-directories-without-sticky-bit) –  Dec 31 '17 at 00:14
  • 1
    I strongly suggest, as isaac mentioned, that you remove your second question from the title. And the last line in your post. Stackoverflow works that way, you ask one question per post. – Alexis Wilke Dec 31 '17 at 01:28

2 Answers2

2

ps is defined in the procps package in Linux.

There is the code handling the -c and -l flags and priority:

if(format_modifiers & FM_c){
  PUSH("pri"); PUSH("class");
}else if(format_flags & FF_Ul){
  PUSH("ni");
  if(personality & PER_IRIX_l) PUSH("priority");
  else /* is this good? */ PUSH("opri");
}

So, if you use -c, you get the pri field.

If you use -l, you either get the priority (IRIX like) or the opri (is this good? flag)

In other words, you're not looking at the same data and this is why you get different results.

In the display.c file we see this comment:

// "PRI" is created by "opri", or by "pri" when -c is used.
//
// Unix98 only specifies that a high "PRI" is low priority.
// Sun and SCO add the -c behavior. Sun defines "pri" and "opri".
// Linux may use "priority" for historical purposes.

So you should use -o opri instead of -o pri on your command line.

To compare these priorities, you can use the -o command line option with:

ps -e -o pri,opri,intpri,priority,ni,pcpu,pid,comm | less

There are actually a few more priorities... Here is the code that displays those columns. It's always using the pp->priority value, it just changes the sign or adds/subtract a number to it. The only direct one is priority ("Pure Linux priority").

// legal as UNIX "PRI"
// "priority"         (was -20..20, now -100..39)
static int pr_priority(char *restrict const outbuf, const proc_t *restrict const pp){    /* -20..20 */
    return snprintf(outbuf, COLWID, "%ld", pp->priority);
}

// legal as UNIX "PRI"
// "intpri" and "opri" (was 39..79, now  -40..99)
static int pr_opri(char *restrict const outbuf, const proc_t *restrict const pp){        /* 39..79 */
    return snprintf(outbuf, COLWID, "%ld", 60 + pp->priority);
}

// legal as UNIX "PRI"
// "pri_foo"   --  match up w/ nice values of sleeping processes (-120..19)
static int pr_pri_foo(char *restrict const outbuf, const proc_t *restrict const pp){
    return snprintf(outbuf, COLWID, "%ld", pp->priority - 20);
}

// legal as UNIX "PRI"
// "pri_bar"   --  makes RT pri show as negative       (-99..40)
static int pr_pri_bar(char *restrict const outbuf, const proc_t *restrict const pp){
    return snprintf(outbuf, COLWID, "%ld", pp->priority + 1);
}

// legal as UNIX "PRI"
// "pri_baz"   --  the kernel's ->prio value, as of Linux 2.6.8     (1..140)
static int pr_pri_baz(char *restrict const outbuf, const proc_t *restrict const pp){
    return snprintf(outbuf, COLWID, "%ld", pp->priority + 100);
}


// not legal as UNIX "PRI"
// "pri"               (was 20..60, now    0..139)
static int pr_pri(char *restrict const outbuf, const proc_t *restrict const pp){         /* 20..60 */
    return snprintf(outbuf, COLWID, "%ld", 39 - pp->priority);
}

// not legal as UNIX "PRI"
// "pri_api"   --  match up w/ RT API    (-40..99)
static int pr_pri_api(char *restrict const outbuf, const proc_t *restrict const pp){
    return snprintf(outbuf, COLWID, "%ld", -1 - pp->priority);
}

So we see

  • "priority" -- direct Linux priority (-100 to 39)
  • "intpri", "opri" -- Linux priority + 60 (-40 to 99)
  • "pri_foo" -- Linux priority - 20 (-120 to 19)
  • "pri_bar" -- Linux priority + 1 (-99 to 40)
  • "pri_baz" -- Linux priority + 100 (1 to 140)
  • "pri" -- 39 - Linux priority (0 to 139, REVERSED)
  • "pri_api" -- -1 - Linux priority (-40 to 99, REVERSED)

The last two ("pri" and "pri_api") are considered "illegal" under Unix.

As for where this data comes from, it is found in the /proc/<id>/stat file. The file is read and the one line of text is parsed by the following sscanf() call after skipping the process ID and name (which is between parenthesis.)

We see that one parameter is &P->priority. So the 18th parameter (16th after skipping the ID and name), starting at 1.

num = sscanf(S,
   "%c "
   "%d %d %d %d %d "
   "%lu %lu %lu %lu %lu "
   "%Lu %Lu %Lu %Lu "  /* utime stime cutime cstime */
   "%ld %ld "
   "%d "
   "%ld "
   "%Lu "  /* start_time */
   "%lu "
   "%ld "
   "%lu %"KLF"u %"KLF"u %"KLF"u %"KLF"u %"KLF"u "
   "%*s %*s %*s %*s " /* discard, no RT signals & Linux 2.1 used hex */
   "%"KLF"u %*u %*u "
   "%d %d "
   "%lu %lu",
   &P->state,
   &P->ppid, &P->pgrp, &P->session, &P->tty, &P->tpgid,
   &P->flags, &P->min_flt, &P->cmin_flt, &P->maj_flt, &P->cmaj_flt,
   &P->utime, &P->stime, &P->cutime, &P->cstime,
   &P->priority, &P->nice,
   &P->nlwp,
   &P->alarm,
   &P->start_time,
   &P->vsize,
   &P->rss,
   &P->rss_rlim, &P->start_code, &P->end_code, &P->start_stack, &P->kstk_esp, &P->kstk_eip,
/*     P->signal, P->blocked, P->sigignore, P->sigcatch,   */ /* can't use */
   &P->wchan, /* &P->nswap, &P->cnswap, */  /* nswap and cnswap dead for 2.4.xx and up */
/* -- Linux 2.0.35 ends here -- */
   &P->exit_signal, &P->processor,  /* 2.2.1 ends with "exit_signal" */
/* -- Linux 2.2.8 to 2.5.17 end here -- */
   &P->rtprio, &P->sched  /* both added to 2.5.18 */
);

There is an example of the data that the libprocps reads:

$ cat /proc/1/stat
1 (systemd) S 0 1 1 0 -1 4194560 188421 1692322137 105 191899 1093 466 35079020 6527486 20 0 1 0 2 341475328 1402 18446744073709551615 1 1 0 0 0 0 671173123 4096 1260 0 0 0 17 2 0 0 3606 0 0 0 0 0 0 0 0 0 0

So process 1 has a Linux priority of 20. When converted to a pri (as with your -o pri command line option), it becomes 39 - 20 = 19.

When using the -l command line option, it uses the opri instead. This means 20 + 60 = 80.

So comparing those two commands lines is completely wrong since in one case the priority is REVERSED and not the other. Now, don't get me wrong... I know there is pretty much nothing about that information in the documentation of ps. It's up to you to know how ps works, I guess. Luckily, under Linux we have the source code to the rescue!

I hope you don't need to make your script compatible with a kernel other than Linux...

Alexis Wilke
  • 2,697
  • 2
  • 19
  • 42
1
  1. As well as using the wrong output option for ps as mentioned by @Alexis Wilke, processes stop and start all the time so the count could be different on every run. This is less likely when searching for processes with a particular priority, but is very evident when counting all running processes. For example:
$ for i in {1..10} ; do ps hax | wc -l ; sleep 1; done
994
1032
1031
1023
1009
997
1037
1001
1038
1034

BTW, if you don't want headers from ps, then tell it not to print them. There's no need for ps ... | tail -n+2. Use ps h <other options> instead.

  1. find's -perm option can find files with specific permissions, including setuid bits. e.g.
$ find /usr/bin/ -perm /u+s | wc -l
34

If you want to see a detailed directory listing of matching files, get rid of the pipe to wc and add -ls to find's command line: find /usr/bin/ -perm /u+s -ls

From man find:

-perm /mode

Any of the permission bits mode are set for the file. Symbolic modes are accepted in this form. You must specify u, g or o if you use a symbolic mode. See the EXAMPLES section for some illustrative examples. If no permission bits in mode are set, this test matches any file (the idea here is to be consistent with the behaviour of -perm -000).

cas
  • 1
  • 7
  • 119
  • 185