Grep — возвращать содержимое строки разного размера после совпадения

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

Итак, мы видим

  • "приоритет" --прямой приоритет Linux (-от 100 до 39)
  • "intpri", "opri" --Приоритет Linux + 60 (-от 40 до 99)
  • "pri _foo" --Приоритет Linux -20 (-От 120 до 19)
  • "pri _bar" --Приоритет Linux + 1 (-от 99 до 40)
  • "pri _baz" --Приоритет Linux + 100 (от 1 до 140)
  • "pri" --39 -Приоритет Linux (от 0 до 139, ОБРАТНЫЙ)
  • "pri _api"---1 -Приоритет Linux (-от 40 до 99, ОБРАТНЫЙ)

Последние два ("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...

0
15.01.2020, 16:15
1 ответ

Возможный подход:

# 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, чтобы она работала правильно.

1
28.01.2020, 02:38

Теги

Похожие вопросы