将防火墙日志字段加载到Hive表

时间:2017-10-13 04:11:09

标签: hadoop logging hive apache-pig

我有来自防火墙的日志文件,但有些日志没有所有列,或者它们以不同的顺序显示。

日志示例:

time=2013-08-07 15:00:38|log_component=Firewall Rule|status=Allow|application=Skype Services|src_ip=172.16.16.79|dst_ip=192.168.2.4
time=2013-08-07 15:00:39|log_component=Firewall Rule|status=Allow|src_ip=172.16.16.80
time=2013-08-07 15:00:40|status=Allow|src_ip=172.16.16.81|dst_ip=192.168.2.6
time=2013-08-07 15:00:41|log_component=Firewall Rule|status=Allow|application=Gmail Services|src_ip=172.16.16.82|dst_ip=192.168.2.7

我已使用此脚本将日志字段加载到Hive表:

DROP TABLE IF EXISTS firewall_logs;
CREATE TABLE firewall_logs(
time STRING,
log_component STRING,
status STRING,
application STRING,
src_ip STRING,
dst_ip STRING
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
WITH SERDEPROPERTIES (
"input.regex" = "time=(.*?)\\|log_component=(.*?)\\|status=(.*?)\\|application=(.*?)\\|src_ip=(.*?)\\|dst_ip=(.*?)",
"output.format.string" = "%1$s %2$s %3$s %4$s %5$s %6$s"
)
STORED AS TEXTFILE;
LOAD DATA LOCAL INPATH "/home/hadoop/firewall.log" INTO TABLE firewall_logs;
SELECT * FROM firewall_logs;

这是查询的结果:

+---------------------+---------------+-------+----------------+--------------+-------------+
| 2013-08-07 15:00:38 | Firewall Rule | Allow | Skype Services | 172.16.16.79 | 192.168.2.4 |
| NULL                | NULL          | NULL  | NULL           | NULL         | NULL        |
| NULL                | NULL          | NULL  | NULL           | NULL         | NULL        |
| 2013-08-07 15:00:41 | Firewall Rule | Allow | Gmail Services | 172.16.16.82 | 192.168.2.7 |
+---------------------+---------------+-------+----------------+--------------+-------------+

但是,我需要使用以下格式将日志字段加载到Hive表:

+---------------------+---------------+-------+----------------+--------------+-------------+
| 2013-08-07 15:00:38 | Firewall Rule | Allow | Skype Services | 172.16.16.79 | 192.168.2.4 |
| 2013-08-07 15:00:39 | Firewall Rule | Allow | *NULL*         | 172.16.16.80 | *NULL*      |
| 2013-08-07 15:00:40 | *NULL*        | Allow | *NULL*         | 172.16.16.81 | 192.168.2.6 |
| 2013-08-07 15:00:41 | Firewall Rule | Allow | Gmail Services | 172.16.16.82 | 192.168.2.7 |
+---------------------+---------------+-------+----------------+--------------+-------------+

但是,Hive SerDe(ReGex)有此限制(根据here中的文档):

“RegexSerDe使用正则表达式(regex)来反序列化数据。它不支持数据序列化。 它可以使用正则表达式对数据进行反序列化,并将组提取为列。 在反序列化阶段,如果行与正则表达式不匹配,则该行中的所有列都将为NULL。如果一行与正则表达式匹配但具有少于预期的组,则缺少的组将为NULL。如果一行与正则表达式匹配但具有多于预期的组,则会忽略其他组。“

如何将日志中不可用的字段加载到表中,其值等于 NULL

是否有任何其他Hadoop生态系统工具允许我在将日志加载到Hive表之前格式化(或根据表字段映射日志字段)?

2 个答案:

答案 0 :(得分:0)

ROW FORMAT DELIMITED FIELDS TERMINATED BY '|' LINES TERMINATED BY '\n' STORED AS TEXTFILE; 正在消耗文本的其余部分,因此第一行之后的所有内容都为NULL

是否有任何其他Hadoop生态系统工具允许我在将日志加载到Hive表之前格式化(或根据表字段映射日志字段)?

Hive会起作用,但你的SerDe需要更好地测试。如果你坚持使用正则表达式,猪和火花将有同样的问题。

但是,您不需要正则表达式。使用管道作为分隔符

||

在使用之前,您需要清理数据以使其始终分隔。例如,您需要(?:application=(.*?)\\|)? 来分隔空字段。

您可以使用正则表达式捕获缺失的字段,例如

$random_values = array("1","2","3","4","5");
	
	for ($i = 0; $i < 20; $i++) {
		$key = array_rand($random_values); 
		echo $random_values[$key] . "\n";
	}	

但是你的人总是期望这些列的顺序是严格的

就个人而言,Spark至少可以在管道中拆分每一行,然后有条件地将每一列解析为一个类对象,从中定义数据集并将其写入Hive

答案 1 :(得分:0)

  1. create table temp(line string);
  2. 将数据加载到表temp中
  3. 作为select spilled插入main_table(regexp_extract(行,&#34;((time =?)[0-9] ( - ) [0-9] ( - ) [0-9]的(\ S) [0-9]的(:) [0-9]的(:) [0-9]的( - ) [0-9]的( - ) | $)&#34;),&#39; \ =&#39;) [1]作为临时页面
  4. 我有一个列的wriiten正则表达式..你已经为所有列写了正则表达式

    选择regex()为col1,regex()为col2,....来自temp。

    我希望这会有所帮助。