Перенаправление вывода ошибок CGI из STDERR в файл (python AND perl)

Я перемещаю веб-сайт на Hostmonster и спрашиваю, где находится журнал сервера, чтобы я мог автоматически сканировать его на наличие ошибок CGI. Мне сказали: "Мы сожалеем, но у нас нет ошибок cgi, перейдите к файлам, к которым у вас есть доступ".

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

У меня много сценариев (269), поэтому мне нужен простой способ, как в Python, так и в Perl, перенаправить STDERR в пользовательский файл журнала.

Что-то, что объясняет блокировку файла явно или неявно, было бы замечательно, так как общий файл журнала ошибок CGI теоретически мог быть записан более чем одним сценарием одновременно, если более одного сценария терпит неудачу одновременно.

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

Я знаю, что мне, возможно, придется изменить каждый файл (grrr), поэтому я ищу что-то элегантное, которое будет состоять всего из нескольких строк кода. Благодарю.

7 ответов

Решение

Решение, которое я наконец выбрал, было похоже на следующее, в верхней части всех моих сценариев:

Perl:

open(STDERR,">>","/path/to/my/cgi-error.log")
    or die "Could not redirect STDERR: $OS_ERROR";

Python:

sys.stderr = open("/path/to/my/cgi-error.log", "a")

Очевидно, в Perl вам не нужно закрывать ручку STDERR перед тем, как открывать ее снова.

Обычно я в любом случае закрываю его как лучший метод, но, как я уже сказал в этом вопросе, у меня есть 269 сценариев, и я пытаюсь минимизировать изменения. (Плюс, кажется, больше Perlish просто заново открывает дескриптор открытого файла, как бы ужасно это не звучало.)

В случае, если у кого-то появится что-то подобное в будущем, вот что я собираюсь сделать для обновления всех моих скриптов одновременно:

Perl:

find . -type f -name "*.pl" -exec perl -pi.bak -e 's%/usr/bin/perl%/usr/bin/perl\nopen(STDERR,">>","/path/to/my/cgi-error.log")\n    or die "Could not redirect STDERR: \$OS_ERROR";%' {} \;

Python:

find . -type f -name "*.py" -exec perl -pi.bak -e 's%^(import os, sys.*)%$1\nsys.stderr = open("/path/to/my/cgi-error.log", "a")%' {} \;

Причина, по которой я публикую эти команды, состоит в том, что мне потребовалось довольно много синтаксического массажа, чтобы заставить эти команды работать (например, изменение Couldnot на Could not, изменение #!/ Usr/bin/perl на just /usr/bin/perl, чтобы оболочка не интерпретировала! как символ истории, используя $OS_ERROR вместо $!, и т. д.)

Спасибо всем, кто прокомментировал. Поскольку никто не отвечал ни за Perl, ни за Python, я не мог "принять" ни один из приведенных ответов, но я отдавал голоса тем, которые привели меня в правильном направлении. Еще раз спасибо!

Для Perl просто закройте и снова откройте STDERR указать на файл по вашему выбору.

close STDERR;
open STDERR, '>>', '/path/to/your/log.txt' 
  or die "Couldn't redirect STDERR: $!";

warn "this will go to log.txt";

Кроме того, вы можете посмотреть в мультиплексор дескриптора файла, как File:: Tee.

В Perl попробуй CGI::Carp

BEGIN { 
use CGI::Carp qw(carpout); 
use diagnostics;
open(LOG, ">errors.txt"); 
carpout(LOG);
close(LOG);
}

use CGI::Carp qw(fatalsToBrowser);

Python: cgitb. В верхней части вашего скрипта, перед другим импортом:

import cgitb
cgitb.enable(False, '/home/me/www/myapp/logs/errors')

("ошибки" - это каталог, к которому у пользователя веб-сервера есть доступ для записи.)

Питон:

import sys

sys.stderr = open('file_path_with_write_permission/filename', 'a')

В моих программах Perl CGI я обычно

BEGIN {
  open(STDERR,'>>','stderr.log');
}

сразу после строки Шебанга и "используйте строгий; используйте предупреждения;". Если вы хотите, вы можете добавить $0 к имени файла. Но это не решит проблему нескольких программ, так как несколько копий одной программы могут быть запущены одновременно. Обычно у меня есть несколько выходных файлов для каждой группы программ.

У Python есть система. Модульstderr, который вы можете посмотреть.

>>>help(sys.__stderr__.read)
Help on built-in function read:

read(...)
    read([size]) -> read at most size bytes, returned as a string.

    If the size argument is negative or omitted, read until EOF is reached.
    Notice that when in non-blocking mode, less data than what was requested
    may be returned, even if no size parameter was given.

Вы можете сохранить вывод этого в строку и записать эту строку в файл.

Надеюсь это поможет

Другие вопросы по тегам