У меня есть файл журнала, который производится сценарием, файл журнала ежедневно поворачивается. Это будет содержать строки
Transfer started at timestamp
и
Transfer completed successfully at timestamp
неоднократно, поскольку упомянутая передача будет каждый час происходить. Метки времени будут ранее созданы с date
.
Я предполагаю, что должен буду использовать sed
или awk
но действительно неопытно с ними. Я хочу использовать команду в сценарии удара и понять то, что делает каждая часть, таким образом, некоторое объяснение было бы очень полезно.
Блок в качестве примера файла журнала:
ERROR - Second tech sync failed with rsync error code 255 at Fri May 27 13:50:4$
--------------------------------------------------------------------
After_sync script completed successfully with no errors.
Main script finished at Fri May 27 13:50:43 BST 2016 with PID of 18808.
--------------------------------------------------------------------
Transfer started at Fri May 27 13:50:45 BST 2016
Logs transferred successfully.
Images transferred successfully.
Hashes transferred successfully.
37 approvals pending.
Transfer completed successfully at Fri May 27 14:05:16 BST 2016
--------------------------------------------------------------------
Local repository verification started at Fri May 27 14:35:02 BST 2016
...
Желаемый вывод:
Transfer started at Fri May 27 13:50:45 BST 2016
Logs transferred successfully.
Images transferred successfully.
Hashes transferred successfully.
37 approvals pending.
Transfer completed successfully at Fri May 27 14:05:16 BST 2016
Однако, если файл журнала был похож на это:
ERROR - Second tech sync failed with rsync error code 255 at Fri May 27 13:50:4$
--------------------------------------------------------------------
After_sync script completed successfully with no errors.
Main script finished at Fri May 27 13:50:43 BST 2016 with PID of 18808.
--------------------------------------------------------------------
Transfer started at Fri May 27 13:50:45 BST 2016
Logs transferred successfully.
Images transferred successfully.
Hashes transferred successfully.
Я хотел бы произвести:
Transfer started at Fri May 27 13:50:45 BST 2016
Logs transferred successfully.
Images transferred successfully.
Hashes transferred successfully.
ERROR: transfer not complete by end of log file
Когда я слышу, что "Хочу сделать X с последним что-то в файле", я думаю:
В коде:
tac logfile | awk '
BEGIN {text = "ERROR: transfer not complete by end of log file"}
/^Transfer completed successfully/ {text = ""}
{text = text ORS $0}
/^Transfer started at / {print text; exit}
' | tac
Так как мы читаем файл журнала с самого начала, я запускаю с предположения, что передача не завершается. Если я вижу, что "передача завершила" сообщение, мы можем вывести то, что мы получили до сих пор. Мы сохраняем каждую строку. Когда мы видим, что "передача запустила" строку, мы знаем, что видели всю последнюю передачу в файле: распечатайте (обратный) полученный текст и выйдите из awk.
Python все вещи, но позволяют регулярным выражениям сделать работу для Вас!
Вставьте сценарий ниже в любой файл, например. logfilter.py
и сделайте это исполняемым файлом с помощью команды chmod +x logfilter.py
.
Затем можно выполнить его как это, предположив, что это расположено в текущем каталоге:
./logfilter.py logfile.txt
Это заставит его обработать файл logfile.txt
.
Однако, если Вы не передадите его никакие параметры командной строки, то это будет ожидать данных по стандартному входу. Это означает, что можно также передать данные по каналу в него. Следующий пример обрабатывает данные от буфера обмена (потребности xsel
установленный для доступа к буферу обмена):
xsel -ob | ./logfilter.py
Сценарий:
#! /usr/bin/env python3
p_start = r'^Transfer started at .*?$'
p_end = r'^Transfer completed successfully at .*?$'
error_no_match = 'ERROR: no match found'
error_no_end = 'ERROR: transfer not complete by end of log file'
pattern = r'{p0}(?!.*{p0})(?:.*?{p1}|.*)'.format(p0=p_start, p1=p_end)
import sys, re
if len(sys.argv) > 1:
with open(sys.argv[1]) as f:
text = f.read()
else:
text = sys.stdin.read()
matches = re.findall(pattern, text, re.DOTALL | re.MULTILINE)
if matches:
last_match = matches[-1]
print(last_match)
if not re.search(p_end, last_match, re.DOTALL | re.MULTILINE):
print(error_no_end)
else:
print(error_no_match)
Вы могли использовать массив awk с переключателем, чтобы буферизовать последний блок и распечатать текст ошибки, если переключатель все еще установлен в конце (это - по существу awk реализация ответа Python @anatoly_techtonik, я думаю):
awk '
BEGIN{PROCINFO["sorted_in"]="@ind_num_asc"}
/Transfer started/ {inblock=1; delete a;}
/Transfer completed/ {a[FNR]=$0; inblock=0;}
inblock == 1 {a[FNR]=$0}
END {
for (i in a) print a[i];
if (inblock)
print "ERROR: transfer not complete by end of log file"
}
' logfile
Просто используйте Python. У меня действительно нет времени, но я запустил бы с этого:
#!/usr/bin/env python
start = "Transfer started at"
end = "Transfer completed successfully"
buffer = ""
log = False
for line in open('logfile.log'):
if line.startswith(start):
buffer = line
log = True
elif line.startswith(end):
buffer += line
log = False
elif log:
buffer += line
open('output.log', 'w').write(buffer)
if log == True:
print("End string was not found")