好的,我有这行将数据输出到文本文件。唯一的问题是我需要线条是唯一的。那么,如果它要添加一条已存在的行,我该怎么办呢?这是我的剧本:
tcpdump -lvi any "udp port 53" 2>/dev/null|grep -E 'A\?'|awk '{print $(NF-1)}' >> /tmp/domains
我管道输入awk并以某种方式删除重复项吗?我是否有另一个脚本每分钟运行一次,以删除重复项?
以下是加载Amazon.com的输出:
amazon.com.
amazon.com.
www.amazon.com.
www.amazon.com.
amazon.com.
www.amazon.com.
a0e90b2a1701074fb52d450dc80084cb1.labs.cloudfront.net.
a0e90b2a1701074fb52d450dc80084cb1.labs.cloudfront.net.
ad.doubleclick.net.
ad.doubleclick.net.
ecx.images-amazon.com.
...more
在查看我的输出时,看起来我需要弄清楚为什么会有一个尾随点。
答案 0 :(得分:2)
你永远不需要grep和awk,因为如果你使用awk,awk可以做grep可以做的任何事情,只需使用awk:
tcpdump -lvi any "udp port 53" 2>/dev/null|
awk '/A\?/{ key=$(NF-1); if (!seen[key]++) print key }' > /tmp/domains
如果您需要停止此脚本并重新启动它,但只将新域附加到输出文件,则只需先读取输出文件以填充“看到”的数组,例如:
tcpdump -lvi any "udp port 53" 2>/dev/null|
awk -v outfile="/tmp/domains" '
BEGIN{
while ( (getline key < outfile) > 0 )
seen[key]++
close(outfile)
}
/A\?/{ key=$(NF-1); if (!seen[key]++) print key >> outfile }
'
答案 1 :(得分:1)
这将只打印出看不见的输入行,而不是像其他一些重复的删除awk脚本一样打印出来。
awk '{host=$(NF-1)} !(host in list) {print host; list[host]++}'
如果你只是想定期运行整个事情并更新列表,那么可能更容易做类似的事情
tcpdump and extract hostnames | sort -u /tmp/domains - > /tmp/domains.new
mv /tmp/domains.new /tmp/domains
答案 2 :(得分:0)
更改此
tcpdump -lvi any "udp port 53" 2>/dev/null|grep -E 'A\?'|awk '{print $(NF-1)}'
要:
tcpdump -lvi any "udp port 53" 2>/dev/null|grep -E 'A\?'|awk '{a[$(NF-1)]++}END{for(i in a)print i}'
答案 3 :(得分:0)
嗯,你需要一个域列表(唯一)吗?或者你需要整条线?
您可以尝试将整行用作awk数组中的键,但时间戳将不同,并且数据包等等。
gawk 'BEGIN{count=0} {arr[$0]=$(NF-1); if (length(arr) > count) { count++; print $0 )}'domain
虽然对你来说可能更有用的是每个域的行......
gawk '{ domain = $(NF-1); arr[ domain ] = $0 ;}
END { for (entry in arr) print "domain:",entry, arr[entry]} '
某些输出对于查看非常有用。 好的,我现在看到了输出,
域必须以点结尾祝你好运!!
PS。使用这个
cmd | gawk 'BEGIN{ count = 0 } {
arr[ $0 ] = $(NF-1);
if (length(arr) > count) {
count++;
print $0
}
}'
因为它不断向输出添加新域。最好不要查找域名并改用ips ...
replace $(NF-1) with |& host -t A domain or so
请参阅gawk信息页面'info gawk'
中的高级功能::双向管道为了使它有用,您需要将新域插入到排序列表中。虽然我不建议为此使用ncurses,但是将输出汇总到一个java程序,该程序在单个排序表中显示数据也不会太难......
答案 4 :(得分:0)
除非您计划长时间运行或拥有非常繁忙的站点,否则您可以通过将先前的查找保存到awk哈希来确保唯一性。这可以在这里工作:
tcpdump -lvi any "udp port 53" 2> /dev/null | grep -E 'A\?' | awk '!h[$(NF-1)]++ { print $(NF-1) }' > /tmp/domains
否则,您需要将tcpdump/grep
输出的块保存到临时文件并将其与/tmp/domains
合并。我知道的最好的方法是保持输出单独排序,然后与sort -mu
进行唯一的合并排序。这可以在这里工作:
lim=10000
tmpfile=$(mktemp /tmp/unique.domain.XXXXXX)
unique_domains=/tmp/domains
tcpdump -lvi any "udp port 53" 2> /dev/null | grep -E 'A\?' | while read line; do
awk -v lim=$lim '!h[$(NF-1)]++ { print $(NF-1); ndomain++ }; ndomain > lim { exit }' | sort > $tmpfile
sort -mu $tmpfile $unique_domains 2> /dev/null > $unique_domains.tmp
mv $unique_domains.tmp $unique_domains
done
如果您想在{} 1}运行时访问/tmp/domain
,则需要添加一些文件锁定功能,例如使用lockfile
:
lim=10000
lock=/tmp/domains.lock
tmpfile=$(mktemp /tmp/unique.domain.XXXXXX)
unique_domains=/tmp/domains
tcpdump -lvi any "udp port 53" 2> /dev/null | grep -E 'A\?' | while read line; do
awk -v lim=$lim '!h[$(NF-1)]++ { print $(NF-1); ndomain++ }; ndomain > lim { exit }' | sort > $tmpfile
lockfile $lock
sort -mu $tmpfile $unique_domains 2> /dev/null > $unique_domains.tmp
mv $unique_domains.tmp $unique_domains
rm $lock
done
现在要获得/tmp/domains
的快照,你会做这样的事情:
lockfile /tmp/domains.lock
cp /tmp/domains unique_domains
sync
rm -f /tmp/domains.lock
答案 5 :(得分:0)
以下是使用管道进行bash功能的解决方案
checkDuplicates() {
touch -- "$1" # Where $1 is a file that holds the data. It could be the same file that you write to or any other one.
while read -r nextCheck; do
grep -q -m 1 "$nextCheck" "$1" || printf "%s\n" "$nextCheck"
done
}
myFile='/tmp/domains'
YOURANYCOMMAND | checkDuplicates "$myFile" > "$myFile"
当您想要查看两个文件之间的差异时,这可能很有用。例如:
fileA:
what
is
this
fileB:
what
I
is
dont
this
even
然后这段代码
cat 'fileB' | checkDuplicates 'fileA'
将要输出
I
Dont
Even