ps
определяется в пакете procps
в Linux.
Есть код, обрабатывающий флаги -c
и -l
и приоритет:
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");
}
Таким образом, если вы используете -c
, вы получите поле pri
.
Если вы используете -l, вы либо получитеpriority
(IRIX, как ), либо opri
(, это хорошо? флаг)
Другими словами, вы смотрите на разные данные и поэтому получаете разные результаты.
В файле display.c
мы видим этот комментарий:
// "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.
Таким образом, вы должны использовать -o opri
вместо -o pri
в своей командной строке.
Чтобы сравнить эти приоритеты, вы можете использовать параметр командной строки -o
с:
ps -e -o pri,opri,intpri,priority,ni,pcpu,pid,comm | less
На самом деле есть еще несколько приоритетов... Вот код, отображающий эти столбцы. Он всегда использует значение pp->priority
, он просто меняет знак или добавляет/вычитает к нему число. Единственный прямой — это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);
}
Итак, мы видим
Последние два ("pri" и "pri _api" )считаются "незаконными" в Unix.
Что касается того, откуда берутся эти данные, то они находятся в файле /proc/<id>/stat
. Файл читается, и одна строка текста анализируется следующим вызовом sscanf()
после пропуска идентификатора процесса и имени (, которые находятся в скобках.)
Мы видим, что один параметр равен &P->priority
.Итак, 18-й параметр (16-й после пропуска идентификатора и имени ), начиная с 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 */
);
Вот пример данных, которые libprocps
считывает:
$ 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
Таким образом, процесс 1 имеет приоритет Linux, равный 20. При преобразовании в pri
(, как с параметром командной строки -o pri
), он становится равным 39 -20 = 19.
При использовании параметра командной строки -l
вместо него используется opri
. Это означает, что 20 + 60 = 80.
Таким образом, сравнивать эти две командные строки совершенно неправильно, поскольку в одном случае приоритет ОБРАЩАЕТСЯ, а в другом нет. Не поймите меня неправильно... Я знаю, что в документации ps
почти ничего об этой информации нет. Думаю, вам решать, как работает ps
. К счастью, под Linux у нас есть исходный код!
Надеюсь, вам не нужно делать ваш скрипт совместимым с ядром, отличным от Linux...
Возможный подход:
# variable S0 - date string for hour ago
S0="time: $(date -d '1 hour ago' +%Y%m%d%H)"
# Variable S1 - date string for current hour
S1="time: $(date +%Y%m%d%H)"
# taking lines from between two just defined strings
# including first and excluding second date string
# from file /var/log/log.log
sed -n "/^${S0}/,/^${S1}/ {/^${S1}/"'!p};' /var/log/log.log
Теперь пытаемся сделать из этого компактный однолайнер:
sed -n "/^time: $(date -d '1 hour ago' +%Y%m%d%H)/,/^time: $(date +%Y%m%d%H)/ {/^time: $(date +%Y%m%d%H)/"'!p}' /var/log/log.log
Вы можете перенаправить вывод во временный файл и работать с ним.
Или вы можете просто добавить в конец одного лайнера трубу и grep:
|grep "mystring"
.
П.С. В зависимости от ОС формат командыдатаможет отличаться.
Linux, который мы использовали здесь:дата -d '1 час назад' +%Y%m%d%H
Linux мы могли бы использовать:date -d @$ (($ (date +%s )-3600 ))+%Y%m%d%H
MacOS X:дата -r $ (($ (дата +%s )-3600 ))+%Y%m%d%H
и т. д.
Обновлено.:Выяснено, что часть sed '$d' для удаления последней найденной строки не работает, поэтому обновила строку sed, чтобы она работала правильно.