В прекрасном и идеально мире каждый должен заниматься своим делом.
В частности я убежден что когда логи пишет логи самостоятельно — это неправильно. Более того совсем неправильно если приложение не умеет отправлять логи в syslog (через сокет или сеть). Сейчас пришел systemd и логи вообще можно писать в STDIN и не париться.
Например apache ну умеет писать логи в syslog. Но он умеет писать их в пайп. Пишем в конфиге
ErrorLog "| /usr/bin/logger --tag example.org_apache-error -n 192.168.5.254"
CustomLog "| /usr/bin/logger --tag example.org_apache -n 192.168.5.254" combined
и логи полетели на syslog-сервер 192.168.5.254. Или не указывает «-n» и логи уходят в локальный syslog.
Но сегодня наткнулся на debian7 (да древность, да нужно выкидывать уже, но тем не менее на данный момент оно еще поддерживается).
Запускаю «echo 123 | /usr/bin/logger -n 192.168.5.254» и на сервер ничего не доходит.
Проверил связанность, настройки фаерволов с обоих сторон, позапускал tcpdump, поперебирал разные варианты настроек и ничего. Взял strace:
[root@d314 /var/log]# date | strace -f /usr/bin/logger -n 192.168.5.254
execve("/usr/bin/logger", ["/usr/bin/logger", "-n", "192.168.5.254"], [/* 22 vars */]) = 0
brk(0) = 0xe26000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff32ee1f000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=26469, ...}) = 0
mmap(NULL, 26469, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7ff32ee18000
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\300\357\1\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1607696, ...}) = 0
mmap(NULL, 3721272, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7ff32e875000
mprotect(0x7ff32e9f9000, 2093056, PROT_NONE) = 0
mmap(0x7ff32ebf8000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x183000) = 0x7ff32ebf8000
mmap(0x7ff32ebfd000, 18488, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ff32ebfd000
close(3) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff32ee17000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff32ee16000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff32ee15000
arch_prctl(ARCH_SET_FS, 0x7ff32ee16700) = 0
mprotect(0x7ff32ebf8000, 16384, PROT_READ) = 0
mprotect(0x603000, 4096, PROT_READ) = 0
mprotect(0x7ff32ee21000, 4096, PROT_READ) = 0
munmap(0x7ff32ee18000, 26469) = 0
brk(0) = 0xe26000
brk(0xe47000) = 0xe47000
open("/usr/lib/locale/locale-archive", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=2709120, ...}) = 0
mmap(NULL, 2709120, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7ff32e5df000
close(3) = 0
getpid() = 2530
open("/etc/resolv.conf", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=19, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff32ee1e000
read(3, "nameserver 8.8.8.8\n", 4096) = 19
read(3, "", 4096) = 0
close(3) = 0
munmap(0x7ff32ee1e000, 4096) = 0
uname({sys="Linux", node="d314", ...}) = 0
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(514), sin_addr=inet_addr("192.168.5.254")}, 16) = 0
close(1) = 0
fstat(0, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff32ee1e000
read(0, "\320\241\321\200\320\264 \320\244\320\265\320\262 21 10:18:33 MSK 20"..., 4096) = 35
time([1519197513]) = 1519197513
open("/etc/localtime", O_RDONLY) = 1
fstat(1, {st_mode=S_IFREG|0644, st_size=1470, ...}) = 0
fstat(1, {st_mode=S_IFREG|0644, st_size=1470, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff32ee1d000
read(1, "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\r\0\0\0\r\0\0\0\0"..., 4096) = 1470
lseek(1, -903, SEEK_CUR) = 567
read(1, "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\16\0\0\0\16\0\0\0\0"..., 4096) = 903
close(1) = 0
munmap(0x7ff32ee1d000, 4096) = 0
socket(PF_FILE, SOCK_DGRAM|SOCK_CLOEXEC, 0) = 1
connect(1, {sa_family=AF_FILE, path="/dev/log"}, 110) = 0
sendto(1, "<13>Feb 21 10:18:33 logger: \320\241\321\200"..., 62, MSG_NOSIGNAL, NULL, 0) = 62
read(0, "", 4096) = 0
close(1) = 0
exit_group(0) = ?
[root@d314 /var/log]#
Сокет до 192.168.5.254 открывается (строки 43-44), но почему-то UDP, в хелпе (и мане сказанно):
[root@d314 /var/log]# logger -h
Usage:
logger [options] [message]
Options:
-d, --udp use UDP (TCP is default)
-i, --id log the process ID too
-f, --file <file> log the contents of this file
-h, --help display this help text and exit
-n, --server <name> write to this remote syslog server
-P, --port <number> use this UDP port
-p, --priority <prio> mark given message with this priority
-s, --stderr output message to standard error as well
-t, --tag <tag> mark every line with this tag
-u, --socket <socket> write to this Unix socket
-V, --version output version information and exit
[root@d314 /var/log]#
То есть должен быть tcp по умолчанию (опции «переключи на tcp» нет, только обратная ей «переключи на udp»), но у нас UDP (SOCK_DGRAM).
Но что самое интересное — в сокет даже не пытается ничего отправляться. Тупо открыли сокет до указанного сервера, потом открываем до локального syslog-а и отправляем в локальный.
Ладно, хер с ним. Беру и пишу свою реализацию logger’а (писать багрепорты на ОС, которую через месяц выкинул с поддержки смысла не вижу):
#!/usr/bin/env perl
use warnings;
use strict;
use Net::Syslog;
my $syslog=new Net::Syslog(Facility => 'local4',SyslogHost => '192.168.5.254', Name => 'tag' );
while(42){
open(FIFO, "< /var/log/fifo") || die("Err opening a fifo: $!");
while (42) {
my $line = <FIFO>;
if ( ! defined($line) ) {
sleep 1;
next;
}
$syslog->send( $line , Priority => 'info');
}
}
Код конечто не идеальный, но хочется использовать именновой пайп (что бы не дергать лишний раз диск). Если из пайпа перестать выбирать данные, то тот, кто их туда пишет просто залипнет в состоянии D. Поэтому 2 бесконечных цикла в коде, а третий во врапере на баше был. Проверил, перероверирил и вот это все, убедился что само запуститься если там oom прибъет или еще почему-либо упадет. Захожу в мускуль говорю «вкдючай slow-лог и пиши вон в тот пайп, хуй там был.
2018-02-21 06:25:03 10912 [ERROR] Could not open /var/log/mysql/mysql-slow.log for logging (error 11). Turning logging off for the whole duration of the MySQL server process. To turn it on again: fix the cause, shutdown the MySQL server and restart it.
И только гугл нам подсказывает что ни я первый и единственный вариант — в новых версиях мускуля есть штатный механизм записи в syslog.
Пиздец в общем. Такую простую задачу вот так эпично сьфейлить.