1) Quantos processos têm prioridade maior que 80? 2) Quantos arquivos executáveis que possuem setuid bit set estão em / usr / bin?

1

Para a primeira pergunta, tentei:

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

e

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

Surpreendentemente ambos deram resultados diferentes e eu não sei qual é o correto e por quê.

Para o segundo eu não tenho nenhuma ideia. Qualquer ajuda será apreciada.

    
por nmab0need5tl 31.12.2017 / 00:51

2 respostas

3

ps é definido no pacote procps no Linux.

Existe o código que processa os sinalizadores% e -c e -l e a prioridade:

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");
}

Então, se você usa -c , você obtém o campo pri .

Se você usar -l, você receberá o sinal priority (como IRIX) ou opri ( é bom? )

Em outras palavras, você não está olhando para os mesmos dados e é por isso que obtém resultados diferentes.

No arquivo display.c , vemos este comentário:

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

Portanto, você deve usar -o opri em vez de -o pri na sua linha de comando.

Para comparar essas prioridades, você pode usar a opção de linha de comando -o com:

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

Na verdade, existem mais algumas prioridades ... Aqui está o código que exibe essas colunas. Ele está sempre usando o valor pp->priority , apenas altera o sinal ou adiciona / subtrai um número a ele. O único direto é priority ("prioridade Pure Linux").

// 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);
}

Então vemos

  • "prioridade" - prioridade direta do Linux (-100 a 39)
  • "intpri", "opri" - prioridade do Linux + 60 (-40 a 99)
  • "pri_foo" - prioridade do Linux - 20 (-120 a 19)
  • "pri_bar" - prioridade do Linux + 1 (-99 a 40)
  • "pri_baz" - prioridade do Linux + 100 (1 a 140)
  • "pri" - 39 - Prioridade do Linux (0 a 139, REVERSED)
  • "pri_api" - -1 - Prioridade do Linux (-40 a 99, REVERSED)

Os dois últimos ("pri" e "pri_api") são considerados "ilegais" no Unix.

Quanto ao local de origem desses dados, ele é encontrado no arquivo /proc/<id>/stat . O arquivo é lido e a única linha de texto é analisada pela seguinte chamada sscanf() após ignorar o ID e o nome do processo (que está entre parênteses).

Vemos que um parâmetro é &P->priority . Então o 18º parâmetro (16º após pular o ID e o nome), começando em 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 */
);

Há um exemplo dos dados que o libprocps lê:

$ 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

Portanto, o processo 1 tem uma prioridade de 20. Quando convertido para pri (como na opção de linha de comando -o pri ), ele se torna 39 - 20 = 19.

Ao usar a opção de linha de comando -l , ela usa o opri . Isso significa 20 + 60 = 80.

Então, comparar essas duas linhas de comandos está completamente errado, já que em um caso a prioridade é REVERSA e não a outra. Agora, não me entenda mal ... Eu sei que não há praticamente nada sobre essa informação na documentação de ps . Cabe a você saber como ps funciona, eu acho. Felizmente, no Linux, temos o código fonte para o resgate!

Espero que você não precise tornar seu script compatível com um kernel diferente do Linux ...

    
por 31.12.2017 / 02:27
1
  1. Além de usar a opção de saída incorreta para ps , conforme mencionado por @Alexis Wilke, os processos param e iniciam o tempo todo, portanto, a contagem pode ser diferente em cada execução. Isso é menos provável ao procurar processos com uma prioridade específica, mas é muito evidente ao contar todos os processos em execução. Por exemplo:
$ for i in {1..10} ; do ps hax | wc -l ; sleep 1; done
994
1032
1031
1023
1009
997
1037
1001
1038
1034

BTW, se você não quiser cabeçalhos de ps , diga para não imprimi-los. Não há necessidade de ps ... | tail -n+2 . Use ps h <other options> em vez disso.

  1. A opção find do -perm pode encontrar arquivos com permissões específicas, incluindo bits setuid. por exemplo.
$ find /usr/bin/ -perm /u+s | wc -l
34

Se você deseja ver uma lista detalhada de diretórios de arquivos correspondentes, elimine o canal para wc e adicione a linha de comando -ls to find : find /usr/bin/ -perm /u+s -ls

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

    
por 31.12.2017 / 02:29