日々良く使っていそうなパイプによる連結。「パイプはモナド!!」とか言いたい方は是非こちらへ。
行数を数えたい
単純に行数を数えたい場合は wc -l
で十分です。wc
は word count で、-l
は line number を教えろという意味です。
$ netstat -tn | wc -l
34
でも何だか味気ないです。exact match でその行がどれくらいあるの? みたいなのが知りたい場合には sort
と uniq
を併せて使います。
$ netstat -tn | awk '{print $6}' | sort | uniq | wc -l
5
uniq
は連続した重複行を 1 行にまとめてくれるので、sort
を前にかまします。uniq
に -c
を付けるとその重複行が何行あったか教えてくれて便利です。
$ netstat -tn | awk '{print $6}' | sort | uniq -c
1
1 CLOSE_WAIT
32 ESTABLISHED
1 TIME_WAIT
1 状態
sort
は -n
で文字列ではなく数字として sort、-r
で逆順で sort してくれるので、最後にくっつけるとものによっては見やすくなります。
$ netstat -tn | awk '{print $6}' | sort | uniq -c | sort -nr
31 ESTABLISHED
1 状態
1 TIME_WAIT
1 CLOSE_WAIT
1
欲しい行だけ抜き出す
grep
とか egrep
とか使えばいいですね。圧縮展開が面倒だ、というときには zgrep
とか zegrep
とかもあります。あんまり option 覚えていませんが、良く(?)使うのは
option | 説明 |
---|---|
-i |
大文字小文字区別しない |
-v |
マッチする行以外を表示 |
-a |
ascii として grep (制御文字入っちゃってるときとか) |
-h |
複数ファイル指定したとき行頭にファイル名を入れない |
少ないな、覚えてるの。表組する程でもないかもしれない。
行のうち欲しい部分だけ抜き出す
上にも出てるけど手軽なのは awk
で $6
とかしてスペースとか区切りの文字を抜き出してしまう方法。若しくは cut
で -c
で抜き出す column を指定しても良い。
$ sudo cut -c -9 /var/log/messages* | uniq -c | sort -n | tail
9 Mar 29 20
9 Mar 30 02
10 Mar 9 08
10 Mar 18 01
10 Mar 20 01
17 Mar 30 00
27 Mar 12 01
225 Mar 29 19
351 Mar 13 07
9118 Mar 18 23
ちなみに、3/18 の 23:43 は OOM killer が走っていました。
気軽に Perl に手を出す
awk
力が高かったり grep
力が高かったりすると色々できそうですが、私の場合貧弱なので直ぐに Perl に手を出します。
perl
は -n
で引数で指定されたファイルや標準入力の各行を $_
という変数に入れて各行を処理してくれます。処理内容は -e
でしてあげれば ok です。
$ netstat -tn | perl -ne '@F=split(" "); print $F[5]."\n";' | sort | uniq -c
1
2 CLOSE_WAIT
28 ESTABLISHED
1 TIME_WAIT
1 状態
これは awk
と同じことをやってるんですが、-a
を付けると awk
っぽく振る舞ってくれるようになり @F
の定義すら必要なくなります。
$ netstat -tn | perl -a -ne 'print $F[5]."\n";' | sort | uniq -c
1
2 CLOSE_WAIT
28 ESTABLISHED
1 TIME_WAIT
1 状態
また、-F
で区切り文字も色々変えれます。-F,
とかすればお手軽な CSV であれば読めます。で、これでもぉ立派な Perl なので、"Foreign Address" が 443 port のものの "State" だけ出力、というのも簡単にできます。
$ netstat -tn | perl -ane 'print $F[5]."\n" if $F[4] =~ /:443/;' | sort | uniq -c
6 ESTABLISHED
1 TIME_WAIT
正規表現さえ使えてしまうと、例えば URL っぽいものを全部引っこ抜くというのも簡単です。
$ curl -s http://www.google.com/ | perl -ne 'while (s/href="(http[^"]+)"//) { print $1."\n" }' | less
http://www.google.com/imghp?hl=en&tab=wi
http://maps.google.com/maps?hl=en&tab=wl
https://play.google.com/?hl=en&tab=w8
http://www.youtube.com/?tab=w1
http://news.google.com/nwshp?hl=en&tab=wn
https://mail.google.com/mail/?tab=wm
https://drive.google.com/?tab=wo
http://www.google.com/intl/en/options/
http://www.google.com/history/optout?hl=en
https://accounts.google.com/ServiceLogin?hl=en&continue=http://www.google.com/
https://plus.google.com/116899029375914044550
足し算したい
awk
を使った場合は END
を使うとファイル読み込みの最後の処理を指示できます。ps aux
の結果から RSS の合計を得るには
$ ps aux | awk '{s+=$6} END {print s}'
6787580
s
が自動的に 0 に初期化されて後は足されていきます。
繰り返す
zsh
を全く使いこなしていないので未だに for
文を書いています。bash
すら使いこなしていません。
for i in `seq -w 2 3 20`; do echo $i; done
02
05
08
11
14
17
20
これは 2 から 20 まで 3 ずつ増やして 0 詰の等幅で表示しています。echo を wget
にしたりすると連番ゲットだぜ的なものになります。
$ for i in `seq -w 2 3 20`; do wget http://www.example.com/$i.png; done
これは Perl で URL っぽいものを引っこ抜き続けるのも同じです。`` で囲まれてる部分がだんだん長くなってくると、残念な気分が増してきます。mysql
とか入れないようにしましょう。
再帰的に directory を掘る
未だに ack
や ag
を使っていない老害です。find
と xargs
を使っています。zsh
があればここにあることは不要なはずです。あんまり参考にせず zsh
とか使いこなしましょう。
近頃の find
は何も引数つけないと -print
と同じでファイルなどの名前を表示してくれます。GNU と FreeBSD とかの違いかもしれません。
find /usr/lib/python2.7 | head -n 5
/usr/lib/python2.7
/usr/lib/python2.7/nntplib.pyc
/usr/lib/python2.7/dbhash.py
/usr/lib/python2.7/inspect.pyc
/usr/lib/python2.7/textwrap.pyc
'-name' すると名前を絞ってくれます。例えば *py
にマッチするものだけなら、
find /usr/lib/python2.7 -name '*py'| head -n 5
/usr/lib/python2.7/dbhash.py
/usr/lib/python2.7/_weakrefset.py
/usr/lib/python2.7/commands.py
/usr/lib/python2.7/mailbox.py
/usr/lib/python2.7/os.py
で、xargs
で出てきた出力結果ファイルに一斉にコマンドを実行します
$ find /usr/lib/python2.6/site-packages/botocore -name '*py' | xargs egrep 'request\.' | less
/usr/lib/python2.6/site-packages/botocore/operation.py: in a request.
/usr/lib/python2.6/site-packages/botocore/awsrequest.py: """Represents a prepared request.
/usr/lib/python2.6/site-packages/botocore/response.py: # the request.
/usr/lib/python2.6/site-packages/botocore/response.py: if not http_response.request.method == 'HEAD':
/usr/lib/python2.6/site-packages/botocore/retryhandler.py: to send the request.
(snip)
これは、指定したフォルダ以下の py
で終わるファイルで request
という変数の attribute を参照している部分を探していますね。何したかったんだろう。。。
find
と xargs
の組み合わせは、ファイル名に space が入ってたりすると悲惨なことになるので find
の -print0
と xargs
の -0
を組み合わせる必要がありますが、まぁ、ぐぐってみて下さい。
find
は -type
でファイルタイプが指定できますが大抵 -type f
で regular file に限定する程度でしょう。-mtime -3
とかで過去 3 日以内に変更されたファイル、なども選べるので、/var/log
で作業するときには少し便利かもしれません。
証明書をゲットしたい
www.google.com
のサーバ証明書だけ欲しい場合には以下で google.pem
に保存できます。
$ openssl s_client -connect www.google.com:443 < /dev/null | openssl x509 > google.pem
中身にしか興味が無い場合には、さっさと parse しちゃいます。
$ openssl s_client -connect www.google.com:443 < /dev/null | openssl x509 -noout -text | less
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 8151063296760904526 (0x711e64e1d9287b4e)
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=US, O=Google Inc, CN=Google Internet Authority G2
Validity
(snip)
負荷分散されてる場合とか、一遍に調べたい場合には for
で回しちゃいましょう。openssl
の -servername
は、対応してたら使えるといいですね!!
$ for i in `dig +short www.google.com`; do openssl s_client -servername www.google.com -connect $i:443 < /dev/null > $i.pem;done
$ ls
173.194.33.48.pem 173.194.33.49.pem 173.194.33.50.pem 173.194.33.51.pem 173.194.33.52.pem
JSON が返ってくるんですけど
perl
でよければ URL っぽいもの引っこ抜く奴で正規表現で頑張れます。あと、json_pp
ってコマンドもあって、これ使うと pretty print してくれるので grep
とかできますね。
python
使うと json
モジュールを呼び出して parse できます。
$ python -m json.tools < cfn.template
まぁ、素直に jq 使え、という話な気がしてきます。