PgSQL的内核日志文件,根据配置文件postgresql.conf的默认配置,放在log文件夹下。
但是它不会自动清理,会无限增长直到把硬盘撑爆。
现有两种方案用于自动清理内核日志文件:
1、配置方案
来源:“PgSQL中文社区”翻译的《PgSQL14 中文手册》
1.1、调整配置文件
log_destination = 'csvlog' #输出日志格式,常见有stderr, csvlog, jsonlog, syslog等,默认值为stderr
logging_collector = on #开启日志,默认值为on
# 下面几个配置,根据需要使用一个,其他地方是我自己做的记录,仅此处扣题
# 其中的参数详见 https://pubs.opengroup.org/onlinepubs/009695399/functions/strftime.html
#log_filename = 'pgsql-%I.log' #最多保存12小时的日志,每小时一个文件
#log_filename = 'pgsql-%H.log' #最多保存24小时的日志,每小时一个文件
#log_filename = 'pgsql-%w.log' #最多保存一周的日志,每天一个文件
#log_filename = 'pgsql-%d.log' #最多保存一个月的日志,每天一个文件
#log_filename = 'pgsql-%j.log' #最多保存一年的日志,每天一个文件
log_filename = 'pgsql-%m%d.log' # %m两位月份数字,%d两位日期数字
log_rotation_age = 1d #单个日志文件的最大时间量,之后将创立一个新的日志文件。默认单位分钟。默认值为1d(此处因log_destination配置优先,故此处无效)
log_rotation_size = 0 #个体日志文件的最大尺寸,默认值为10MB(此处因log_destination配置优先,故此处无效)
log_truncate_on_rotation = on #是否截断日志文件(覆盖而不是追加),默认值为off。详见中文手册
log_line_prefix = '%m [%p]' #每一行日志的前缀,因log_destination配置优先,故此处无效
#log_line_prefix = '[%m][%h][%d][%u][%p][%x]' #每一行日志的前缀,详见中文手册,默认值为 %m [%p],看习惯也可以不改
log_statement = 'mod' #详见中文手册,默认值为none
1.2、将需要仔细检查的日志导入数据表中检查分析
1.2.1、建表(表名也可以自己定,比如专门建个临时用的表)
-- 注意,此处建的表,Postgresql 13与14表结构相同,但是PgSQL 15增加了字段,详见中文手册
-- 表结构不同,是无法正确将csv日志导进来的,会报错
CREATE TABLE postgres15_log -- 表名也可自己定一个专门临时使用的如[pgsql15_log_debug]什么的
(
log_time timestamp(3) with time zone,
user_name text,
database_name text,
process_id integer,
connection_from text,
session_id text,
session_line_num bigint,
command_tag text,
session_start_time timestamp with time zone,
virtual_transaction_id text,
transaction_id bigint,
error_severity text,
sql_state_code text,
message text,
detail text,
hint text,
internal_query text,
internal_query_pos integer,
context text,
query text,
query_pos integer,
location text,
application_name text,
backend_type text,
leader_pid integer,
query_id bigint,
PRIMARY KEY (session_id, session_line_num)
);
CREATE TABLE postgres14_log -- 表名也可自己定一个专门临时使用的如[pgsql14_log_debug]什么的
(
log_time timestamp(3) with time zone,
user_name text,
database_name text,
process_id integer,
connection_from text,
session_id text,
session_line_num bigint,
command_tag text,
session_start_time timestamp with time zone,
virtual_transaction_id text,
transaction_id bigint,
error_severity text,
sql_state_code text,
message text,
detail text,
hint text,
internal_query text,
internal_query_pos integer,
context text,
query text,
query_pos integer,
location text,
application_name text,
PRIMARY KEY (session_id, session_line_num)
);
1.2.2、Copy导入csv日志文件,然后就可以从表里做查询、分析了
-- 以管理员执行SQL语句,导入csv格式的日志文件,具体的表名、路径、日志文件名请自行调整
postgres=# copy schema-hwg.pgsql_log_debug from '/var/lib/postgresql/data/pg_log/viid-2022-03-14_000000.csv' with csv;
COPY 26031
postgres=# copy schema-hwg.pgsql_log_debug from '/var/lib/postgresql/data/pg_log/viid-2022-03-15_000000.csv' with csv;
COPY 1297
2、脚本方案(未验证)
来源:Linux 使用shell脚本清理postgresql内核日志 - 南大仙 - 博客园
postgresql内核日志格式为postgresql-2022-06-07_081953.log
log_filename = 'PostgreSQL-%Y-%m-%d.log'
PostgreSQL-%Y-%m-%d.log中的%Y%m%d格式如下解释
Linux日期格式
date +%Y%m%d
20220609
$ date +%F
2022-06-09
$ date +%y%m%d
220609
$ date -d yesterday +%Y%m%d
20220608
$ date
Thu Jun 9 10:09:23 CST 2022
$
$ date -d -1day +%Y%m%d
20220608
$ date -d yesterday +%F
2022-06-08
$ date -d -1day +%y%m%d
220608
$ date -d -1day +%Y%m%d
20220608
$ echo $(date +%y%m%d)
220609
$
上述时间格式为:
% H 小时(00…23)
% I 小时(01…12)
% k 小时(0…23)
% l 小时(1…12)
% M 分(00…59)
% p 显示出AM或PM
% r 时间(hh:mm:ss AM或PM),12小时
% s 从1970年1月1日00:00:00到目前经历的秒数
% S 秒(00…59)
% T 时间(24小时制)(hh:mm:ss)
% X 显示时间的格式(%H:%M:%S)
% Z 时区 日期域
% a 星期几的简称( Sun…Sat)
% A 星期几的全称( Sunday…Saturday)
% b 月的简称(Jan…Dec)
% B 月的全称(January…December)
% c 日期和时间( Mon Nov 8 14:12:46 CST 1999)
% d 一个月的第几天(01…31)
% D 日期(mm/dd/yy)
% h 和%b选项相同
% j 一年的第几天(001…366)
% m 月(01…12)
% w 一个星期的第几天(0代表星期天)
% W 一年的第几个星期(00…53,星期一为第一天)
% x 显示日期的格式(mm/dd/yy)
% y 年的最后两个数字( 1999则是99)
% Y 年(例如:1970,1996等)
以下清理是以日志名字中带有日期的删除方式
cat clean.sh
path=/data/.../log 设置日志路径变量
del_date=date +'%F %H%M%S' -d "5 days ago" 将5天前的日期付给del_date作为保留天数
//将日志路径下的所有日志打印,将打印结果放在处理管道中,一个一个进入循环处理,当ls出来的日志满足如下结果进入循环
//ls $path/postgresql*.log | awk -F / '{print $5}'| cut -b 12-28将日志ls出来使用awk进行分割,分隔符为/,并输出第五项,然后使用cut-b截取第12-28个字符
for n in ls $path/postgresql*.log | awk -F / '{print $5}'| cut -b 12-28;do
if [[ $n < $del_date || $n = $del_date ]];then //ruguo ls出来的日志截取后的日期小于等于del_date,将日志删除,说明日志时间比较早
echo file $path/postgresql-$n.log will be deleted. //打印某个日志即将被删除
rm -rf $path/$firstname$n$lastname
rm -rf $path/postgresql-$n.log//删除该日志,后面也可以加上删除是否成功的判断,此处不做处理
fi
done
head -n1 postgresql-2022-06-07_081953.log |awk -F - {print,$1,$2,$3} //打印日志第一行,并进行截取,也可以使用这个日期作为判断
//file_date=ls postgresql*.log -1 | cut -b 12-21 | sed 's/-//g' //提取文件中的日期并将日期中的-换为空,即将2022-06-01改为20220601