技術者になりたい何か

技術者になりたい何かの覚書的な何かです

てきすとすとりーむ2

テキスト処理系2回目。
テキストデータを加工するための色々。
組み合わせて使うとなんだか色々できる。

■uniq

重複している行をまとめて出力する。
入力するテキストストリームは予めソートしておく必要がある。
ので、多くの場合sortと併用される。

ログの集計とかに便利。nginxとかapacheアクセスログから簡易アクセス解析とかもできます。

というわけでsshdのFailedを集計してみます。先日やったけども。

こういうログから存在しているユーザ名でのログイン失敗ログからIPを抜き出して集計。
(対象ログ→/var/log/auth.log)

Dec 3 00:01:10 tminserver sshd[29952]: Failed password for root from 58.242.83.26 port 41788 ssh2
Dec 3 00:01:13 tminserver sshd[29952]: Failed password for root from 58.242.83.26 port 41788 ssh2
Dec 3 00:01:15 tminserver sshd[29952]: Failed password for root from 58.242.83.26 port 41788 ssh2
Dec 3 00:01:17 tminserver sshd[29952]: Failed password for root from 58.242.83.26 port 41788 ssh2
Dec 3 00:12:15 tminserver sshd[30090]: Failed password for invalid user admin from 103.207.37.155 port 507
05 ssh2
Dec 3 00:12:23 tminserver sshd[30092]: Failed password for invalid user support from 103.207.37.155 port 6
3144 ssh2
Dec 3 00:12:32 tminserver sshd[30099]: Failed password for invalid user admin from 103.207.37.155 port 620
87 ssh2

パターン①rootでログイン失敗しているアクセス元IPの集計

集計期間は12/3-6 →grep 'Dec [3-6]'
失敗してるのを抜き出す →grep 'Failed'
存在しないユーザ名での失敗ははじく→grep -v 'invalid'
IPのカラム(フィールド)を抜き出す→ cut -d ' ' -f 12
抜き出したIPをソート → sort
ソートしたIPの重複分削除するけどそれぞれの件数(行数?)はカウントする → uniq -c
カウントした結果が1カラム目に出るので、多い方から順にソート → sort -nr

$ sudo grep 'Dec [3-6]' /var/log/auth.log | grep 'Failed' | grep -v 'invalid' | cut -d ' ' -f 12 | sort | uniq -c | sort -nr
54381 58.242.83.26
15564 42.7.26.91
156 193.201.224.218
21 103.207.37.155
14 103.99.1.187
14 103.207.37.154
12 92.247.83.86
12 42.62.51.53
12 103.99.0.199
10 181.214.87.4
6 91.126.205.238
6 90.226.61.158
6 87.123.137.84
6 84.135.151.34
6 83.233.45.72
6 69.165.46.170
6 69.131.92.126
6 61.153.20.84
6 60.179.11.32
6 60.173.82.156
6 60.165.208.28
6 59.15.210.188
6 59.120.249.139
6 46.72.18.89
6 41.82.138.10
6 39.71.158.158
6 38.108.61.214


~~~以下略~~~~

 

パターン②存在しないユーザで入力されているユーザ名を集計。

集計期間は12/3-6 →grep 'Dec [3-6]'
失敗してるのを抜き出す →grep 'Failed'
存在しないユーザ名での失敗を抜き出す →grep 'invalid user'
入力されたユーザ名のカラム(フィールド)を抜き出す→ cut -d ' ' -f 12
抜き出したユーザ名をソート → sort
ソートしたユーザ名の重複分削除するけどそれぞれの件数(行数?)はカウントする → uniq -c
カウントした結果が1カラム目に出るので、多い方から順にソート → sort -nr

$ sudo grep 'Dec [3-6]' /var/log/auth.log | grep 'Failed' | grep 'invalid user' | cut -d ' ' -f 12 | sort | uniq -c | sort -nr
446 admin
52 user
36 ubnt
33 test
32 pi
31 support
27
25 ftp
22 guest
22 ftpuser
21 service
20 1234
20 0
14 user1
14 adm
14 111111
13 super
13 operator
13 default
10 manager
10 22
9 sysadmin
9 nagios
9 a
8 webmaster
8 tomcat
8 scan
8 postgres
8 monitor
8 git
8 fax
8 apache
8 123321
7 www
7 usuario
7 report
7 mother
7 matsumoto
7 auction
7 administrator
7 123
~~~以下省略~~~~

 
つかpiって誰だよ

■wc

ファイルの行数、単語数、文字数を表示。
数えるのがめんどい時に便利。

オプション
-c 文字数(バイト数)を表示
-l 行数を表示
-w 単語数を表示

単純に大きいファイルの時に行数見たりとか、
grepの検索結果をwc -l に渡して件数カウントしたりする時とかに使える。

上記sshアタックのログの場合で、rootでログインしようとして失敗しているログの件数(12/3~12/6)


$ sudo grep 'Dec [3-6]' /var/log/auth.log.1 | grep 'Failed' | grep 'root' |wc -l
70539

■pr

印刷前の整形によく使うらしい。
コマンドラインから印刷・・・?

-l でヘッダ・フッタを含むページの行数を指定。+1:2で1ページ目から2ページ目まで。

$ pr -l 25 +1:2 dpkg.log


2017-12-13 18:16 dpkg.log 1 ページ


2017-12-02 08:56:42 startup archives unpack
2017-12-02 08:57:16 upgrade curl:amd64 7.38.0-4+deb8u7 7.38.0-4+deb8u8
2017-12-02 08:57:16 status half-configured curl:amd64 7.38.0-4+deb8u7
2017-12-02 08:57:17 status unpacked curl:amd64 7.38.0-4+deb8u7
2017-12-02 08:57:17 status half-installed curl:amd64 7.38.0-4+deb8u7
2017-12-02 08:57:17 status triggers-pending man-db:amd64 2.7.0.2-5
2017-12-02 08:57:17 status half-installed curl:amd64 7.38.0-4+deb8u7
2017-12-02 08:57:17 status unpacked curl:amd64 7.38.0-4+deb8u8
2017-12-02 08:57:17 status unpacked curl:amd64 7.38.0-4+deb8u8
2017-12-02 08:57:18 upgrade libcurl3:amd64 7.38.0-4+deb8u7 7.38.0-4+deb8u8
2017-12-02 08:57:18 status half-configured libcurl3:amd64 7.38.0-4+deb8u7
2017-12-02 08:57:18 status unpacked libcurl3:amd64 7.38.0-4+deb8u7
2017-12-02 08:57:18 status half-installed libcurl3:amd64 7.38.0-4+deb8u7
2017-12-02 08:57:18 status half-installed libcurl3:amd64 7.38.0-4+deb8u7
2017-12-02 08:57:18 status unpacked libcurl3:amd64 7.38.0-4+deb8u8

 

 

 

2017-12-13 18:16 dpkg.log 2 ページ


2017-12-02 08:57:18 status unpacked libcurl3:amd64 7.38.0-4+deb8u8
2017-12-02 08:57:19 upgrade libcurl3-gnutls:amd64 7.38.0-4+deb8u7 7.38.0-4+deb8u8
2017-12-02 08:57:19 status half-configured libcurl3-gnutls:amd64 7.38.0-4+deb8u7
2017-12-02 08:57:19 status unpacked libcurl3-gnutls:amd64 7.38.0-4+deb8u7
2017-12-02 08:57:19 status half-installed libcurl3-gnutls:amd64 7.38.0-4+deb8u7
2017-12-02 08:57:19 status half-installed libcurl3-gnutls:amd64 7.38.0-4+deb8u7
2017-12-02 08:57:20 status unpacked libcurl3-gnutls:amd64 7.38.0-4+deb8u8
2017-12-02 08:57:20 status unpacked libcurl3-gnutls:amd64 7.38.0-4+deb8u8
2017-12-02 08:57:20 upgrade bzr:all 2.6.0+bzr6595-6 2.6.0+bzr6595-6+deb8u1
2017-12-02 08:57:20 status half-configured bzr:all 2.6.0+bzr6595-6
2017-12-02 08:57:20 status unpacked bzr:all 2.6.0+bzr6595-6
2017-12-02 08:57:20 status half-installed bzr:all 2.6.0+bzr6595-6
2017-12-02 08:57:20 status half-installed bzr:all 2.6.0+bzr6595-6
2017-12-02 08:57:20 status unpacked bzr:all 2.6.0+bzr6595-6+deb8u1
2017-12-02 08:57:21 status unpacked bzr:all 2.6.0+bzr6595-6+deb8u1

 

これリダイレクトかなんかで新しいファイルに出力すると印刷時にきれいになるという事かな?
ぶっちゃけ使う場面がいまいち・・・

■fmt

テキストを決められた桁に整形する。

オプション
-w 一行の幅を設定

$ head -5 /var/log/dpkg.log
2017-12-02 08:56:42 startup archives unpack
2017-12-02 08:57:16 upgrade curl:amd64 7.38.0-4+deb8u7 7.38.0-4+deb8u8
2017-12-02 08:57:16 status half-configured curl:amd64 7.38.0-4+deb8u7
2017-12-02 08:57:17 status unpacked curl:amd64 7.38.0-4+deb8u7
2017-12-02 08:57:17 status half-installed curl:amd64 7.38.0-4+deb8u7


↑のようなのを最大幅40で整形すると・・・

$ head -5 /var/log/dpkg.log | fmt -w 40
2017-12-02 08:56:42 startup archives
unpack 2017-12-02 08:57:16 upgrade
curl:amd64 7.38.0-4+deb8u7
7.38.0-4+deb8u8 2017-12-02
08:57:16 status half-configured
curl:amd64 7.38.0-4+deb8u7 2017-12-02
08:57:17 status unpacked curl:amd64
7.38.0-4+deb8u7 2017-12-02 08:57:17
status half-installed curl:amd64
7.38.0-4+deb8u7

とはいえなかなかうまいとこで切れてくれないです。行が変に結合して余計読みにくい。
こういう時は-sオプション付けて行結合しないように指定してやると・・・

$ head -5 /var/log/dpkg.log | fmt -s -w 40
2017-12-02 08:56:42 startup archives
unpack
2017-12-02 08:57:16 upgrade curl:amd64
7.38.0-4+deb8u7 7.38.0-4+deb8u8
2017-12-02 08:57:16 status
half-configured curl:amd64
7.38.0-4+deb8u7
2017-12-02 08:57:17 status unpacked
curl:amd64 7.38.0-4+deb8u7
2017-12-02 08:57:17 status
half-installed curl:amd64
7.38.0-4+deb8u7

さっきよりましになりましたね。

■expand

テキストファイル内のタブをスペースに変換

オプション 
-i 行頭のタブのみ変換
-t タブ幅 タブ幅を設定する

■unexpand

行頭にある連続した空白をタブに変換

オプション
-a 行頭以外の空白も変換
-t タブ幅 タブ幅指定(デフォルトでは8ケタ)

インデント付けるときの変換とかには便利かもしれない
あと空白→タブに一括返還しといてエクセル貼り付けとか?

■xargs

これはテキストストリームに入れていいのかよくわからないけども。
標準入力から受け取った文字列を引数に指定して、与えられたコマンドを実行。
引数の数が多すぎた場合でも良きに計らってくれる気が利くやつ。
大量のログ調査とかでうまい事やってくれてるのがこいつの仕業である。

$ find -type f -name "*log*"

logがファイル名に含まれるファイルをカレントディレクトリから検索。

これをxargs でcatにつなぐと、cat の引数として上記ファイルが全てうまい事引き渡される。
ので、順次catで展開されていく。後ろに| grep 'hoge' をつければその結果からhogeが含まれる行を抽出してくれる。

$ find -type f -name "*log*" | xargs cat | grep "hoge"

引き渡すコマンド次第では引数となるファイルが多すぎるとエラーを吐いたりすることがある。
その辺上手くやってくれるのがxargs。
xargs [コマンド] のコマンド部分の引数として前の結果を渡すので、コマンド次第ではうまくいかないときもなきにしもあらず。


$ sudo find /var/log -type f -name 'mail.log.?.gz'
/var/log/mail.log.2.gz
/var/log/mail.log.4.gz
/var/log/mail.log.3.gz

この出力されたmail.log[2-4].gz をxargsでzcatに渡してgrepをかけると

$ sudo find /var/log -type f -name 'mail.log.?.gz' | xargs sudo zcat | grep 'status=sent'
Jul 7 17:33:15 tminserver postfix/local[6448]: 0E4B540D99: to=<tmin@tminserver.localdomain>, orig_to=<root>, relay=local, delay=0.56, delays=0.33/0.09/0/0.15, dsn=2.0.0, status=sent (delivered to mailbox)

3つのファイルが順次に後ろのzcatに渡される→grep status=sentで。
ちなみに下記のコマンドと一緒になる。(最初のカラムにファイルフルパスが出るかどうか)

$ sudo zgrep 'status=sent' /var/log/mail.log.?.gz
/var/log/mail.log.3.gz:Jul 7 17:33:15 tminserver postfix/local[6448]: 0E4B540D99: to=<tmin@tminserver.localdomain>, orig_to=<root>, relay=local, delay=0.56, delays=0.33/0.09/0/0.15, dsn=2.0.0, status=sent (delivered to mailbox) 


上手く使えば○○日以上たったファイルを前部圧縮とか全部退避、とかもできる。