Как ранние журналы регистрируются в rsyslog, когда rsyslog еще не запущен?

Если у вас установлена ​​GNU awkверсии 4 или более поздней, она имеет возможность загружать внешние модули, обеспечивающие функциональность, отсутствующую в стандартном awk или даже в расширенном GNU -awk. Он поставляется с набором модулей, в том числе с именем filefuncs. Модуль filefuncsвключает awkоболочку для системной statфункции, которую можно использовать для получения информации о файлах (, в том числе о том, существуют они или нет ).

Следующий скрипт awkзагружает модуль filefuncs, считывает каждую входную строку, проверяет 5-й столбец, чтобы решить, какой путь следует предварительно -ожидать для каждого входного имени файла, и проверяет, существует ли файл. Если это так, он печатает полный путь и имя файла на стандартный вывод. Если это не так, он печатает предупреждающее сообщение в stderr.

Ассоциативный массив paths(, также известный как «хэш» или «хешированный массив» )и путь по умолчанию, предварительно -ожидающий, — мои лучшие предположения о том, что вы намереваетесь. Отрегулируйте по мере необходимости. Это соответствует данным в предоставленных вами образцах (, даже очевидная ошибка с Media -> /Volumes/Logic ), а не то, что вы сказали в одном из ваших комментариев. Если ваш комментарий точен, то код можно упростить.

#!/usr/bin/awk -f

# this will only work with GNU awk >= version 4.0
@load "filefuncs"

BEGIN {
  FS=OFS="|";
  paths["default"] = "/Users/spazek/Pictures/Fotos Library.photoslibrary/Masters/";
  paths["Logic"] = "/Volumes/Logic/";
  paths["Media"] = "/Volumes/Logic/";
  paths["macOS"] = "/";
}

{ if ($5 in paths) {
    filename = paths[$5] $1;
  } else { # $5 not known in paths array, use a default
    filename = paths["default"] $1;
  }

  # try to stat the file. get the return code in variable 'rc' and error
  # string (if any) in 'error'.
  rc=stat(filename,fstat);
  error=ERRNO;   # oddly, ERRNO is a string, not a number.

  if (rc == -1) {  # return code of -1 is "No such file or directory"
    # print warning to stdout and skip to next input line
    print filename ": " error > "/dev/stderr"
    next;
  };

  # filename exists, do something with filename.
  print filename, $2, $3, $4, $5;
}

Сохранить как, например. ./exists.awk, сделайте его исполняемым с помощьюchmod +x(так же, как с помощью сценария оболочки ), и запустите его следующим образом:

./exists.awk /Users/spazek/Desktop/filelist1.txt

или направьте sqlite3 прямо в него:

sqlite3  -separator $'|' /Users/spazek/Desktop/xsystx/systphotos.db \
'select RKMaster.imagePath, RKMaster.name, RKMaster.uuid, RKMaster.fileIsReference, ( select RKVolume.name from RKVolume where RKVolume.modelId  = RKMaster.volumeId) from RKMaster' \
  |./exists.awk

Я не знаю, какая версия awkв настоящее время поставляется с Mac OS.Я подозреваю, что это, вероятно, либо BSD awk, либо какая-то древняя версия GNU awk, существовавшая до того, как Free Software Foundation перешла на использование лицензии GPLv3 (, поэтому Mac застряли на древней bashv3, а чем текущая bashверсия 4 -, это не потому, что Apple не может обновить bash, а потому, что они не будут . Используйте brew , если вам нужна более поздняя версия GNU bashили awk).

В любом случае, если у вас не установлен GNU awk >= v4.0, вы можете сделать то же самое с любой версией perl.

Следующий скрипт perlне использует никаких нестандартных -модулей или функций Perl, и даже не требует использования perlвстроенной -в stat()функции, поскольку в Perl есть операторы. аналогичны тем, что в shдля проверки существования файла. Здесь мы будем использовать оператор -e, который проверяет существование файла, как и в sh:

.

#!/usr/bin/perl

use strict;

# declare %paths hash
my %paths = (
  "default" => "/Users/spazek/Pictures/Fotos Library.photoslibrary/Masters/",
  "Media"   => "/Volumes/Logic/",
  "Logic"   => "/Volumes/Logic/",
  "macOS"   => "/",
);

# main loop, read in each line of input and process it.
while(<>) {
  chomp; # strip trailing linefeed from end-of-line
  my $filename='';  # declare $filename to belong to this scope

  # split input on "|" characters
  my ($path,$name,$id,$reference,$diskname) = split /\|/;

  if (defined($paths{$diskname})) {
    $filename = $paths{$diskname}. $path;
  } else {  # diskname not known in %paths hash, use a default
    $filename = paths{"default"}. $path;
  }

  if (! -e $filename) {
    # print warning to stderr and skip to next input line
    warn "$filename: No such file or directory\n";
    next;
  };

  # filename exists, do something with filename.
  print join('|', $filename, $id, $reference, $diskname), "\n";
}

Опять же, сохраните его как exists.plи сделайте исполняемым с помощью chmod +x. Выполнить как:

./exists.pl /Users/spazek/Desktop/filelist1.txt

Любой из этих двух сценариев будет в сотни или тысячи раз быстрее, чем сценарий оболочки, использующий while readили аналогичный цикл.

3
30.08.2020, 08:47
2 ответа

Процесс syslogобычно получает сообщения из трех источников.:

  1. Заявки через/dev/log
  2. Сеть через порт 514
  3. Ядро через/proc/kmsg

Теперь первое... традиционно любое приложение, которое отправляет в /dev/logдо запуска процесса syslogd, теряет свои сообщения. systemdнемного сбивает с толку, потому что он вместо этого может прослушивать этот сокет. И тогда syslogdможет читать из systemd. Но это, похоже, не твоя забота.

Второе явно не относится к вашему вопросу.

Итак, мы сосредоточимся на третьем. Это строки, которые начинаются с [...], где число является отметкой времени после загрузки. Это сообщения, созданные ядром, а не приложениями пользовательского пространства.

Сообщения ядра помещаются в "кольцевой буфер", и когда rsyslogзапускается, оно будет считывать этот буфер, чтобы поместить данные... туда, куда конфигурационные файлы говорят поместить их.

При нормальных обстоятельствах это хорошо. Вам нужен журнал всех сообщений загрузки ядра на случай, если что-то не запустится должным образом.

Но если они вас не волнуют, вы можете использовать команду dmesg --clear. Это очищает «кольцевой буфер». Поэтому, если вы поместите это в последовательность загрузки перед запуском rsyslog, тогда демон не будет читать никаких сообщений ядра; буфер был очищен.

Теперь то, как вы это сделаете, очень зависит от используемого вами дистрибутива. При использовании традиционного sysvinitвы можете захотеть создать RC-файл, который запускается непосредственно перед сценарием запуска системного журнала. С помощью systemd вы можете создать модуль с предварительным требованием для процесса системного журнала.

4
18.03.2021, 23:09

Удаление сообщений из dmesg/kmsg — плохая идея, и в долгосрочной перспективе это может вас укусить. Вы можете не захотеть видеть эти сообщения в xconsole, но они могут быть важны для отладки при сохранении в других журналах.

Вероятно, лучшим решением здесь является очистка xconsole в начале процесса загрузки, через некоторое время сразу после запуска системного журнала, но до того, как будут собраны другие «загрузочные сообщения поздней стадии».

Если некоторые из ваших «загрузочных сообщений поздней стадии» съедаются этим процессом, вы можете добавить парсер к очистке, чтобы он останавливался либо после последней строки ядра, которую вы хотите съесть, либо после первой поздней стадии. строку, которую вы не хотите очищать.

Вы можете внедрить эту «очистку xconsole», установив ее приоритет сразу после rsyslogd или добавив ее в сценарий инициализации rsyslogd, если вам это удобно, хотя изменения могут быть изменены обновлениями.

-2
22.08.2021, 13:57

Теги

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