awk处理SFTP日志:用用户名替换会话ID生成CSV求助
SFTP日志解析:替换会话ID为用户名并生成目标CSV
我需要分析SFTP日志,生成汇总CSV后邮件发送,但日志解析环节卡壳了。
完整日志示例
Oct 24 10:39:02 T-FTP-01 internal-sftp[1110]: session closed for local user ftpuser Oct 24 10:39:06 T-FTP-01 internal-sftp[1165]: session opened for local user ftpuser Oct 24 10:39:06 T-FTP-01 internal-sftp[1165]: opendir "/ftp/user/ftpuser" Oct 24 10:39:07 T-FTP-01 internal-sftp[1165]: closedir "/ftp/user/ftpuser" Oct 24 10:40:42 T-FTP-01 internal-sftp[1165]: session closed for local user ftpuser Oct 24 10:47:01 T-FTP-01 internal-sftp[572]: session opened for local user ftpuser Oct 24 10:47:01 T-FTP-01 internal-sftp[572]: received client version 6 Oct 24 10:47:01 T-FTP-01 internal-sftp[572]: realpath "/ftp/user/ftpuser" Oct 24 10:47:01 T-FTP-01 internal-sftp[572]: lstat name "/ftp/user/ftpuser" Oct 24 10:47:02 T-FTP-01 internal-sftp[572]: opendir "/ftp/user/ftpuser" Oct 24 10:47:03 T-FTP-01 internal-sftp[572]: closedir "/ftp/user/ftpuser" Oct 24 10:47:32 T-FTP-01 internal-sftp[572]: opendir "/ftp/user/ftpuser" Oct 24 10:47:33 T-FTP-01 internal-sftp[572]: closedir "/ftp/user/ftpuser" Oct 24 10:47:40 T-FTP-01 internal-sftp[572]: open "/ftp/user/ftpuser/test.txt" flags READ mode 0666 Oct 24 10:47:41 T-FTP-01 internal-sftp[572]: close "/ftp/user/ftpuser/test.txt" bytes read 4 written 0 Oct 24 10:49:35 T-FTP-01 internal-sftp[572]: session closed for local user ftpuser Oct 24 12:53:15 T-FTP-01 internal-sftp[487]: session opened for local user root
当前使用的awk脚本(存在问题)
BEGIN {print "month;day;time;session;output"} {gsub(/\"/,'',$0)}; {gsub(/\[/,'',$0)}; {print $1 ";" $2 ";" $3 ";" $5 ";" $6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20 }
需求说明
- 日志仅在用户登录(
session opened)时显示用户名,其他操作日志仅能看到会话ID(如internal-sftp[1165]) - 需要将所有日志中的会话ID字段替换为对应用户名,最终CSV的
session列(原$5字段)显示用户名而非会话ID - 会话ID与用户名一一对应,可通过
awk '$7 ~ /opened/ { print $5 " " $11 }' /root/log/sftp.log提取对应关系
预期输出(格式化后日志,对应CSV内容逻辑)
Oct 24 10:39:02 ftpuser session closed for local user ftpuser Oct 24 10:39:06 ftpuser session opened for local user ftpuser Oct 24 10:39:06 ftpuser opendir "/ftp/user/ftpuser" Oct 24 10:39:07 ftpuser closedir "/ftp/user/ftpuser" Oct 24 10:40:42 ftpuser session closed for local user ftpuser Oct 24 10:47:01 ftpuser session opened for local user ftpuser Oct 24 10:47:01 ftpuser received client version 6 Oct 24 10:47:01 ftpuser realpath "/ftp/user/ftpuser" Oct 24 10:47:01 ftpuser lstat name "/ftp/user/ftpuser" Oct 24 10:47:02 ftpuser opendir "/ftp/user/ftpuser" Oct 24 10:47:03 ftpuser closedir "/ftp/user/ftpuser" Oct 24 10:47:32 ftpuser opendir "/ftp/user/ftpuser" Oct 24 10:47:33 ftpuser closedir "/ftp/user/ftpuser" Oct 24 10:47:40 ftpuser open "/ftp/user/ftpuser/test.txt" flags READ mode 0666 Oct 24 10:47:41 ftpuser close "/ftp/user/ftpuser/test.txt" bytes read 4 written 0 Oct 24 10:49:35 ftpuser session closed for local user ftpuser Oct 24 12:53:15 root session opened for local user root
解决方案:修改后的awk脚本
核心思路:先扫描日志建立会话ID与用户名的映射关系,再逐行处理日志替换会话ID为用户名,同时生成目标CSV。
BEGIN { print "month;day;time;session;output" # 第一次扫描日志,构建会话ID到用户名的映射数组 while ((getline line < "/root/log/sftp.log") > 0) { split(line, arr) if (arr[7] == "opened") { session_key = arr[5] session_map[session_key] = arr[11] } } close("/root/log/sftp.log") } # 逐行处理日志生成CSV { gsub(/"/, "", $0) current_session = $5 # 优先使用映射的用户名,无映射则保留原会话ID username = session_map[current_session] ? session_map[current_session] : current_session # 拼接output字段内容 output = "" for (i=6; i<=NF; i++) { output = output (output == "" ? "" : " ") $i } # 输出CSV格式行 print $1 ";" $2 ";" $3 ";" username ";" output }
脚本说明
- 初始化阶段:提前读取日志文件,提取所有
session opened记录的会话ID和用户名,存入session_map关联数组 - 逐行处理:
- 移除日志中的引号,避免CSV格式混乱
- 根据当前行的会话ID,从映射数组中取出对应用户名
- 拼接第6个字段到行尾的所有内容作为
output列 - 按指定CSV格式输出,
session列替换为用户名
- 容错处理:若某条日志的会话ID无对应映射,保留原会话ID,避免数据丢失
内容的提问来源于stack exchange,提问作者NXYBWzyK
相关产品推荐
相关产品推荐

