📊

SadServers解説 Easy No.2 「IPアドレスを数えてください」

に公開

https://ja.wikipedia.org/wiki/サスカトゥーン

問題概要

問題URL

https://sadservers.com/scenario/saskatoon

シナリオ

IPアドレスを数えてください

問題詳細

/home/admin/access.log は Web サーバのアクセスログです。
このファイルは 1 行が 1 回の HTTP リクエストで、各行の先頭列にはリクエスト元の IP アドレスが入っています。

このログの中で、最も多く登場する IP アドレスを見つけて、/home/admin/highestip.txt に書き込みます。例えば回答が "1.2.3.4" の場合は、echo "1.2.3.4" > /home/admin/highestip.txt を実行します。

同率はなく、最多の IP アドレスは 1 つだけです。正解の IP アドレスは access.log に 482 回出現します。

解決判定

答えを/home/admin/highestip.txtに記載してください。例えば回答が"1.2.3.4"の場合は、以下のコマンドを実行してください。

echo "1.2.3.4" > /home/admin/highestip.txt

sha1sum /home/admin/highestip.txt の結果は 6ef426c40652babc0d081d438b9f353709008e93 になります。

問題解決の方針

【表示する】

この問題は、アクセスログの先頭列に並んでいる IP アドレスを集計して、最も多く現れる値を見つける問題です。

具体的な解決の段取りを表示する
  1. まずログの形式を見て、先頭列が本当に IP アドレスか確認する。
  2. 先頭列だけを取り出して、集計対象を IP アドレスの一覧に絞る。
  3. 同じ IP アドレスを数えられる形に整えて、出現回数を集計する。
  4. 件数が最大の IP アドレスを特定する。

ヒント

オリジナルヒント

ヒント1

最初に、ログの先頭に IP アドレスがあることを確認します。

実行コマンド

ログの先頭部分を見て、各行の最初に IP アドレスがあるか確認します。

~$ head /home/admin/access.log
83.149.9.216 - - [17/May/2015:10:05:03 +0000] "GET /presentations/logstash-monitorama-2013/images/kibana-search.png HTTP/1.1" 200 203023 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
83.149.9.216 - - [17/May/2015:10:05:43 +0000] "GET /presentations/logstash-monitorama-2013/images/kibana-dashboard3.png HTTP/1.1" 200 171717 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
83.149.9.216 - - [17/May/2015:10:05:47 +0000] "GET /presentations/logstash-monitorama-2013/plugin/highlight/highlight.js HTTP/1.1" 200 26185 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
...
ヒント2

先頭列が IP アドレスだと分かったら、次はその列だけを抜き出します。
この問題では空白区切りの 1 列目を取りたいので、cut を素直に使えます。

実行コマンド

1 列目だけを表示して、IP アドレスだけの一覧になるか確認します。

$ cut -d' ' -f1 /home/admin/access.log | head
83.149.9.216
83.149.9.216
83.149.9.216
83.149.9.216
83.149.9.216
83.149.9.216
83.149.9.216
83.149.9.216
83.149.9.216
83.149.9.216
ヒント3

IP アドレスの一覧ができたら、同じ値を数えます。
ただし uniq -c は、同じ行が連続していないと正しく数えられません。
そのため、先に並べ替えてから件数を数えます。

実行コマンド

IP アドレスだけを取り出し、並べ替えてから件数を集計します。

$ cut -d' ' -f1 /home/admin/access.log | sort | uniq -c | head
      6 1.22.35.226
      6 100.2.4.116
     84 100.43.83.137
     33 101.119.18.35
      3 101.199.108.50
      1 101.226.168.196
      1 101.226.168.198
      2 101.226.33.222
      4 103.245.44.13
      1 103.247.192.5
ヒント4

件数一覧ができたら、最後に「件数が最大の行」を取り出します。

実行コマンド

件数の多い順に並べて最上位を確認します。
件数の大小で並べ替えるために、再度 sort を使います。-n で数値として比較し、-r で大きい順に並べます。

$ cut -d' ' -f1 /home/admin/access.log | sort | uniq -c | sort -nr | head
    482 66.249.73.135
    364 46.105.14.53
    357 130.237.218.86
    273 75.97.9.59
    113 50.16.19.13
    102 209.85.238.199
     99 68.180.224.225
     84 100.43.83.137
     83 208.115.111.72
     82 198.46.149.143

この出力から、最も多く登場する IP アドレスは 66.249.73.135 だと読み取れます。答えをファイルに書き込み、sha1sum で確認します。

$ echo "66.249.73.135" > /home/admin/highestip.txt
$ sha1sum /home/admin/highestip.txt
6ef426c40652babc0d081d438b9f353709008e93  /home/admin/highestip.txt

SadServers公式ヒント(翻訳)

ヒント1

ファイルの 1 列目、つまり IP アドレスを取り出します。
awk '{print $1}' access.log や、空白を区切り文字にした cut を使えます。
フィルタが正しく動いているか確認するために、途中で headtail を付けるとよいでしょう。

ヒント2

前の手順で取り出した IP アドレスを並べ替えて、同じ IP アドレスがまとまるようにします。

ヒント3

次に uniq -c で件数を数えます。
ここまでで、awk '{print $1}' access.log | sort | uniq -c になります。

ヒント4

最後に、その結果を sort で並べ替えます。
昇順なら最後の行を tail -1 で取り出し、逆順なら sort -r で先頭を取れます。
たとえば awk '{print $1}' access.log | sort | uniq -c | sort -r | head -1 のようにできます。

参考

今回は cut を使う方針で進めました。一方で、公式ヒントは awk を中心に説明しています。awkcut より記述が複雑ですが、その分できることも多く、列の加工や条件付き集計など柔軟に対応できます。cut で解決できたら、次は awk で同じことができるか試してみてもよいかもしれません。
 
「いきなり問題を解き始めても調べるばかりになってしまう…」 「やりたいことが分かっても、コマンドが分からない…」 という方は、下記の記事でLinuxのコマンドを復習してから、SadServersの問題に取り掛かってみてはいかがでしょうか。
https://zenn.dev/comf_nakamura/articles/linux_command

 

問題一覧はこちら

https://zenn.dev/comf_nakamura/articles/sadservers_sitemap

Discussion