2013-10-02 2 views
1

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

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

# generic code, somewhere in the program 
if success; then 
    log_f "Previous function returned success" 
else log_f "Previous function returned failure" 
fi 

Этот подход имеет дефект быть только в состоянии войти те сообщения, которые явно предназначены для передачи через log_f; то есть любые сообщения об ошибках, созданные внешними двоичными файлами или самим Bash, не будут сохранены в базе данных.

Простым решением может пройти по линии exec >log 2>&1, которая регистрирует все, что выходит из stdin и stderr в log. Однако мне нужно хранить сообщения журнала в базе данных, а не в файле.

Кроме того, exec представляется несовместимым с перераспределением труб, например exec | log_f. (log_f изменен для поддержки stdin). Единственное решение, которое я могу думать, что это некрасиво, это установить перенаправление всего скрипта (ов) в процессе их вызова, как:

# I am a starter of sub-scripts 
a_script_in_the_tree.sh 2>&1 | log_f 

Однако, было бы желательно, чтобы каждый сценарий управлять своей собственный метод ведения журнала, используя собственный набор функций, доступных в пределах своей области.

+1

Знаете ли вы о '{cmd1; ...; } | log_f'? Он обрабатывает перенаправление ввода-вывода для кода в рамках фигурных скобок, аналогичный, но не столь радикальный, как «exec» - и может использоваться с конвейерами (с оговорками о том, где переменные установлены и прочитаны). –

+0

Это потребует, чтобы каждая команда программы была направлена ​​к каждому регистратору отдельно, если я хочу собрать весь вывод из сценария. Немного сумасшедшее ИМХО. – davide

+0

Я просто понял, что весь скрипт можно поместить внутри '{}', за исключением определения 'log_f'. Однако у меня есть глобальные переменные, увы. – davide

ответ

1

Простое решение может идти по линии exec >log 2>&1

Именованная труба может занять место файла журнала, хотя для этого потребуется процесс ФИФО-к-SQL, чтобы потреблять выход и отправить это в базу данных. Это даст вам «уверенность в себе» для переадресации каждого сценария, одновременно добавляя нагрузку, которую каждый сценарий должен будет запускать идемпотентного потребителя. Означает ли это одно уродство для другого?

Вот простая пара сценариев, которые демонстрируют идею, сценарий, нуждающегося лесозаготовительных услуг:

$ cat nplog.sh 
#!/bin/bash 

logfifo=/tmp/log.fifo 
if [ ! -p $logfifo ]; then 
    # should maybe spawn npreader here 
    echo logging system is not running: $logfifo does not exist 1>&2 
    exit 1 
fi 

exec > $logfifo 2>&1 

while true; do 
    date 
    cat /does.not.exist 
    sleep 1 
done 

и cheezy читателя

$ cat npreader.sh 
#!/bin/bash 

# oversimplified for illustration. should remove the fifo upon exit so 
# that clients can't attach when reader is down 

logfifo=/tmp/log.fifo 
mkfifo $logfifo 
cat $logfifo 
0

Просто вышел из моей головы:

exec > >(log_f) 2>&1 
Смежные вопросы