全力で怠けたい

怠けるために全力を尽くしたいブログ。

Firehose で GZIP 圧縮して S3 に流したデータをダウンロードすると GZIP 圧縮されてない?と勘違いしたときのメモ。

AWS Kinesis Data Firehose で GZIP 圧縮して S3 に流したデータをブラウザーでダウンロードすると GZIP 圧縮されてない? と勘違いしたときのメモ。

Firehose で GZIP 圧縮して S3 に流したデータをダウンロードすると GZIP 圧縮されてない?

サーバーのログは Firehose で S3 に流してて Firehose のデータ配信ストリームは S3 のデータ使用量を抑えるためにサーバーのログを GZIP 圧縮してから S3 に保存するように設定してるんだけど、ブラウザーで S3 に保存してるサーバーのログをダウンロードしてファイルタイプを確認したら GZIP じゃなくて JSON だった。 サーバーのログは JSON 形式で出力しているんだけど Firehose がサーバーのログを GZIP 圧縮してなさそうに思ったので「Firehose の配信ストリームの設定を間違えてるのかな?」と少し調べたときのメモ。

結論としては Firehose の配信ストリームの設定は間違ってなくて Firehose のデータ配信ストリームから S3 に流すときにちゃんと GZIP 圧縮してる。

事象

サーバーのログは JSON 形式で出力してて Firehose の配信ストリーム経由で S3 に保存している。

Firehose のデータ配信ストリームは S3 のデータ使用量を抑えるためにサーバーのログを GZIP 圧縮してから S3 に保存するように設定してるんだけど、ブラウザーAWS コンソールを表示して保存してるサーバーのログをダウンロードしてファイルタイプを確認したら GZIP じゃなくて JSON だった。 テキストエディターでログ (data.gz) を表示してみると普通に表示できてやっぱり JSON になってる。

$ file data.gz
data.gz: JSON data

一応、AWS CLI で同じログを S3 からダウンロードすると今度はファイルタイプが GZIP になってる。 やっぱり Firehose の配信ストリームの設定は合ってるっぽい。

$ aws s3 cp s3://hoge-bucket/data.gz data-2.gz
download: s3://hoge-bucket/data.gz to ./data-2.gz

$ file data-2.gz
data-2.gz: gzip compressed data, from FAT filesystem (MS-DOS, OS/2, NT), original size modulo 2^32 3115

原因

S3 に保存してるサーバーのログを AWS コンソールでいろいろ見たりググったりしたら、どうも原因は Firehose がデータを S3 に保存するときに Content-Encoding: gzip メタデータをサーバーのログに付与してからっぽい。

AWS コンソールでサーバーのログのメタデータを表示すると Content-Encoding: gzip が付いてる。

f:id:ebc_2in2crc:20200801152631p:plain:w500

Content-Encoding: gzip がサーバーのログに付いてるのでブラウザーでアクセスすると Content-Encoding: gzip ヘッダーがレスポンスヘッダーに付く。 ブラウザーはレスポンスに Content-Encoding: gzip ヘッダーが付いてると body を自動的に GZIP 展開するのでダウンロードして保存したサーバーのログは GZIP 圧縮前の JSON になっているということのようだった。

f:id:ebc_2in2crc:20200801152646p:plain:w400

結論

サーバーのログサイズはかなり大きいのでローカルにダウンロードすることはめったにないのと、あとたぶん実際にサーバーのログをローカルにダウンロードするときは AWS CLI でダウンロードすると思うので結論としては特に気にしないでよさそう。

参考サイト

AWS CLI v1 => v2 でバイナリ入力パラメータのデフォルトの解釈方法が変わっているメモ。

AWS CLI v1 => v2 で file:// とか使うときのバイナリ入力パラメータのデフォルトの解釈方法が変わっている。v2 を使うときにバイナリ入力パラメータのデフォルトの解釈方法を v1 互換にする方法とかを調べたメモ。

バイナリ入力パラメータのデフォルトの解釈方法

AWS CLI v1 => v2 でバイナリ入力パラメータのデフォルトの解釈方法が変わっている。 AWS CLI v2 を使うときにバイナリ入力パラメータのデフォルトの解釈方法を v1 互換にする方法をメモしておく。

AWS CLI のバージョン。

$ aws --version
aws-cli/2.0.35 Python/3.7.4 Darwin/19.5.0 botocore/2.0.0dev39

AWS CLI v2 はデフォルトで base64エンコードされたテキストに解釈する

AWS CLI v1 は file:// とか使うときのバイナリ入力パラメータをデフォルトで raw データつまりエンコードされていないテキストに解釈したけど、AWS CLI v2 は file:// とか使うときのバイナリ入力パラメータをデフォルトで base64エンコードされたテキストに解釈する。

以下のコードは AWS CLI v1 では意図するとおりに動くけど AWS CLI v2 はエラーになって Invalid base64: "Hello" が表示する。

$ aws kms encrypt --key-id=${KEY_ID} --plaintext="Hello" --query=CiphertextBlob --output=text

Invalid base64: "Hello"

file:// プレフィクスを使っても同じ結果になる。

$ aws kms encrypt --key-id=${KEY_ID} --plaintext=file://<(echo -n "Hello") --query=CiphertextBlob --output=text

Invalid base64: "Hello"

AWS CLI v1 => v2 で file:// とか使うときのバイナリ入力パラメータのデフォルトの解釈方法が変わってしまっているので、v1 のときに作ったツールとかシェルスクリプトを v2 を使うとエラーになったり、意図しない挙動になったりする。 エラーになるのは困るけど意図しない挙動になるともっと困ることが多いと思うので、v1 のときに作ったツールとかを作ったときに意図していた挙動で動かす方法を書いていく。

バイナリ入力パラメータを v1 互換の解釈方法にする

AWS CLI v2 はバイナリ入力パラメータの解釈方法をコマンドのフラグとか config ファイルで指定できる。

コマンドのフラグでバイナリ入力パラメータの解釈方法を指定する

コマンドのフラグでバイナリ入力パラメータの解釈方法を指定するには --cli-binary-format オプションを指定していく。 --cli-binary-format=raw-in-base64-out を指定すると AWS CLI v1 互換の解釈方法になる。

$ aws kms encrypt --key-id=${KEY_ID} --plaintext="Hello" --query=CiphertextBlob --output=text --cli-binary-format=raw-in-base64-out
# 暗号化したテキストが出力

file:// プレフィクスを使っても同じ結果になる。

$ aws kms encrypt --key-id=${KEY_ID} --plaintext=file://<(echo -n "Hello") --query=CiphertextBlob --output=text --cli-binary-format=raw-in-base64-out
# 暗号化したテキストが出力

cofig ファイルでバイナリ入力パラメータの解釈方法を指定する

AWS CLI v2 はバイナリ入力パラメータの解釈方法を config ファイルの cli_binary_format オプションに設定しておくとその解釈方法でバイナリ入力パラメータを解釈する。 cli_binary_format オプションが raw-in-base64-out のときは AWS CLI v2 はバイナリ入力パラメータを raw データとして解釈して、 cli_binary_format オプションが config ファイルにないか cli_binary_format オプションが base64 のときはバイナリ入力パラメータを base64エンコードされたテキストとして解釈する。

[default]
cli_binary_format = raw-in-base64-out

config ファイルを直接いじるかこんな感じのコマンドを実行すればいい。

$ aws configure set cli_binary_format raw-in-base64-out

$ cat ~/.aws/config
[default]
cli_binary_format = raw-in-base64-out
# 省略

$ aws kms encrypt --key-id=${KEY_ID} --plaintext="Hello" --query=CiphertextBlob --output=text
# 暗号化したテキストが出力

$  aws kms encrypt --key-id=${KEY_ID} --plaintext=file://<(echo -n "Hello") --query=CiphertextBlob --output=text
# 暗号化したテキストが出力

自分が普段使ってる環境は config を設定しておくのが手軽だけどシェルスクリプトを作って他の人に使ってもらったり CI で動かすときはバイナリ入力パラメータの解釈方法は config の設定に依存したくないと思うので --cli-binary-format フラグでバイナリ入力パラメータの解釈方法を指定するのがよさそう。

fileb:// プレフィクスを使うと常に raw データとして解釈する

AWS CLI v2 は fileb:// プレフィクスを使うとバイナリ入力パラメータを常に raw データとして解釈する。

$ cat ~/.aws/config
[default]
cli_binary_format = base64

$  aws kms encrypt --key-id=${KEY_ID} --plaintext=fileb://<(echo -n "Hello") --query=CiphertextBlob --output=text --cli-binary-format=base64
# 暗号化したテキストが出力

fileb:// プレフィクスは --cli-binary-format フラグと config ファイルの cli_binary_format オプションで base64 を指定してもバイナリ入力パラメータを常に raw データとして解釈するので、AWS CLI v1 のときに作ったツールとかシェルスクリプトAWS CLI v2 で同じ挙動にするのは fileb:// プレフィクスを使うのが一番楽なような気がする。

環境変数でバイナリ入力パラメータの解釈方法は指定できない

バイナリ入力パラメータの解釈方法は環境変数では指定できないので AWS CLI v2 でバイナリ入力パラメータの解釈方法を指定するのは --cli-binary-format フラグ、config ファイルの cli_binary_format オプションを指定するか、あるいは fileb:// プレフィクスを使っていく。

このエントリには、同等の環境変数はありません。

参考サイト

banner コマンドを Dockerfile にしたメモ。

banner) コマンドを Dockerfile にしたのでメモしておく。

banner コマンドの Dockerfile

仕事をしてるとたまに banner コマンドを使うときがある。 普段は Mac で作業してて Mac に入ってる banner コマンドは BSD 版で縦出力なんだけど、自分は縦出力じゃなくて横出力したいことが多くて banner コマンドを使うときは適当な Linux 機に入って banner コマンドを使ってる。Linux 機に入って banner コマンドを打つのはまあまあ面倒くさいので Dockerfile にした。

Dockerfile

Dockerfile はこんな感じにしてる。

FROM centos:7

RUN yum install -y epel-release && \
        yum install -y banner

COPY docker-entrypoint.sh /usr/local/bin

ENTRYPOINT ["docker-entrypoint.sh"]

docker-entrypoint.sh はこんな感じ。

#!/bin/sh

banner "$@"

使い方

こんな感じで使ってる。

$ docker image build --tag docker-banner .

$ docker container run --rm -it docker-banner Hello

#     #  #######  #        #        #######
#     #  #        #        #        #     #
#     #  #        #        #        #     #
#######  #####    #        #        #     #
#     #  #        #        #        #     #
#     #  #        #        #        #     #
#     #  #######  #######  #######  #######

banner コマンドの入力が複数あると改行する。改行したくなかったら "aaa bbb" みたいにする。

$ docker container run --rm -it docker-banner aaa bbb

   #        #        #
  # #      # #      # #
 #   #    #   #    #   #
#     #  #     #  #     #
#######  #######  #######
#     #  #     #  #     #
#     #  #     #  #     #


######   ######   ######
#     #  #     #  #     #
#     #  #     #  #     #
######   ######   ######
#     #  #     #  #     #
#     #  #     #  #     #
######   ######   ######

$ docker container run --rm -it docker-banner "aaa bbb"

   #        #        #           ######   ######   ######
  # #      # #      # #          #     #  #     #  #     #
 #   #    #   #    #   #         #     #  #     #  #     #
#     #  #     #  #     #        ######   ######   ######
#######  #######  #######        #     #  #     #  #     #
#     #  #     #  #     #        #     #  #     #  #     #
#     #  #     #  #     #        ######   ######   ######

入力が長くて途中で切れちゃうときは --env COLUMNS=100 みたいにして COLUMNS 環境変数を設定して実行すると途中で切れなくなる。

$ docker container run --rm -it docker-banner "Hello World"

#     #  #######  #        #        #######        #     #  #######  ######
#     #  #        #        #        #     #        #  #  #  #     #  #     #
#     #  #        #        #        #     #        #  #  #  #     #  #     #
#######  #####    #        #        #     #        #  #  #  #     #  ######
#     #  #        #        #        #     #        #  #  #  #     #  #   #
#     #  #        #        #        #     #        #  #  #  #     #  #    #
#     #  #######  #######  #######  #######         ## ##   #######  #     #

$ docker container run --rm -it --env COLUMNS=100 docker-banner "Hello World"

#     #  #######  #        #        #######        #     #  #######  ######   #        ######
#     #  #        #        #        #     #        #  #  #  #     #  #     #  #        #     #
#     #  #        #        #        #     #        #  #  #  #     #  #     #  #        #     #
#######  #####    #        #        #     #        #  #  #  #     #  ######   #        #     #
#     #  #        #        #        #     #        #  #  #  #     #  #   #    #        #     #
#     #  #        #        #        #     #        #  #  #  #     #  #    #   #        #     #
#     #  #######  #######  #######  #######         ## ##   #######  #     #  #######  ######

参考サイト

シェルのリダイレクトでわりと使うやつのメモ。

シェルのリダイレクトでわりと使うやつをメモしておく。

シェルのリダイレクト

シェルスクリプトを書くときにわりと使うリダイレクトのやつを書いていく。

/bin/sh のバージョン。普通に bash.

$ /bin/sh --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin19)
Copyright (C) 2007 Free Software Foundation, Inc.

このへんは man sh すると sh は /private/var/select/shシンボリックリンクが実行すると書いてあるので /private/var/select/sh を見たら /bin/bash へのシンボリックリンクになってた。 /bin/sh を実行すると /bin/bash が sh 互換で動く感じ。

It is implemented by re-execing as either bash(1), dash(1), or zsh(1) as determined by the symbolic link located at /private/var/select/sh.

標準出力のリダイレクト

標準出力のリダレクトは > を使う。

# 標準出力をファイルにリダイレクトする
$ echo Hello > stdout.txt
$ cat stdout.txt
Hello

> はリダイレクト先のファイルの中身を上書きする。

$ echo Hello > stdout.txt
$ echo World > stdout.txt
$ cat stdout.txt
World

リダイレクト先のファイルを上書きじゃなくて追記するときは >> を使う。

$ echo Hello > stdout.txt
$ echo World >> stdout.txt
$ cat stdout.txt
Hello
World

標準エラー出力のリダイレクト

標準エラー出力> でリダイレクトするけど >標準エラー出力はリダイレクトしない。 ls /hoge/not/exists みたいに存在しないファイルを ls するとメッセージがプロンプトに表示するしリダイレクト先の stderr.txt は空っぽになる。

$ ls /hoge/not/exists
ls: /hoge/not/exists: No such file or directory
$ cat stderr.txt

標準エラー出力のリダイレクトは 2> を使う。 ls /hoge/not/exists みたいに存在しないファイルを ls するとメッセージがプロンプトに表示されなくてちゃんとリダイレクト先の stderr.txt に入る。

$ ls /hoge/not/exists 2> stderr.txt

$ cat stderr.txt
ls: /hoge/not/exists: No such file or directory

2> はリダイレクト先のファイルを上書きする。リダイレクト先のファイルを上書きじゃなくて追記するときは 2>> を使う。

$ ls /hoge/not/exists 2> stderr.txt
$ ls /fuga/not/exists 2> stderr.txt
$ cat stderr.txt
ls: /fuga/not/exists: No such file or directory

$ ls /hoge/not/exists 2> stderr.txt
$ ls /fuga/not/exists 2>> stderr.txt
$ cat stderr.txt
ls: /hoge/not/exists: No such file or directory
ls: /fuga/not/exists: No such file or directory

標準入力とかのリダイレクトで使うファイルディスクリプタ

標準エラーのリダイレクトで 2> とか 2>> みたいにしたときの 2 はファイルディスクリプタを指定してる。

標準出力とか標準エラー出力のファイルディスクリプタは一般的に以下のようになってるので 2>標準エラー出力をリダイレクトするという意味になる。

ファイルディスクリプタ 対象
0 標準入力
1 標準出力
2 標準エラー出力

あと標準出力のリダイレクトは > とか >> みたいに書いたけど標準出力のファイルディスクリプタ1 なので 1> とか 1>> みたいにしても同じ動きになる。

$ echo Hello 1> stdout.txt
$ echo World 1>> stdout.txt
$ cat stdout.txt
Hello
World

標準入力のリダイレクト

標準入力のリダレクトは < を使う。

$ cat stdout.txt
Hello
World

$ grep Hello < stdout.txt
Hello

ヒアドキュメント

標準入力はヒアドキュメント << をリダイレクトすることができる。

$ cat << EOF
Hello
World
EOF
Hello
World

$ grep Hello << EOF
Hello
World
EOF
Hello

標準出力をファイルにリダイレクトして空っぽのファイルを作る

ファイルを空っぽにするときに echo > stdout.txt みたいにすると stdout.txt の内容は空っぽにならない。

$ echo > stdout.txt
$ ls -l stdout.txt
-rw-r--r--  1 shrimp  staff  1  7 24 14:48 stdout.txt

$ od stdout.txt
0000000    000012
0000001

これ、bash なら echo -n > stdout.txt でファイルを空っぽにできるけど sh で echo -n > stdout.txt をやると -n というファイルになっちゃう。

rm stdout.txt; touch stdout.txt でファイルを削除してから空のファイルを作ってもいいけど :> みたいにするほうが楽なので :> を使うことが多い気がする。

$ :> stdout.txt
$ ls -l stdout.txt
-rw-r--r--  1 shrimp  staff  0  7 24 14:49 stdout.txt

$ od stdout.txt

ちなみに ubuntu/bin/sh が dash のシンボリックリンクになってるんだけど echo -n > stdout.txt で普通にファイルを空っぽに出来ると Twitter で教えてもらった。

docker container run --rm -it ubuntu /bin/sh コマンドで ubuntu の Docker コンテナを起動していろいろ試してみたけどちゃんと echo -n > stdout.txt でファイルを空っぽにできる……

# ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Aug  7  2019 /bin/sh -> dash

# echo -n > stdout.txt
# ls -l stdout.txt
-rw-r--r-- 1 root root 0 Jul 24 10:31 stdout.txt

# cat stdout.txt

参考サイト

Slack メッセージの書式設定に再入門したメモ。

f:id:ebc_2in2crc:20200720232123p:plain

Slack のメッセージの書式設定は Markdown ぽいやつで雰囲気で書いてたけど雰囲気で再入門したのでメモしておく。

Slack メッセージの書式設定

Slack のメッセージの書式は Markdown ぽいやつで設定したりショートカットで設定したり GUI で設定したりできるけど、Markdown ぽいやつだといい感じに箇条書きが書けなかったりするみたいなのでそのへんの書式を設定するやり方を調べたのを書いていく。

Slack は Mac のデスクトップ版でバージョン 4.7.0 を使ってる。

最初にやっておくこと

環境設定 > 詳細設定 を表示して マークアップでメッセージを書式設定する のチェックを外しておく。

このあとの書式設定のやり方は マークアップでメッセージを書式設定する のチェックが入ってないのが前提にしてる。 マークアップでメッセージを書式設定する にチェックを入れないほうがいい感じに書式設定ができるっぽいので (たぶん)

太字

テキストを太字にするには対象のテキストを * (アスタリスク) で囲む。

斜体

テキストを太字にするには対象のテキストを _ (アンダースコア) で囲む。

取り消し線

取り消し線をテキストに付けるには対象のテキストを ~ (チルダ) で囲む。

インラインコード

インラインコードは ``` (バッククォート x3) でインラインコードを始めて ``` (バッククォート x3) でインラインコードを終わる。 Shift + Enter でインラインコードを次の行に継続する。

引用タグ

引用タグはテキストの先頭を > にする。 Shift + Enter で引用タグを次の行に継続する。

順序リスト

テキストの先頭に 1. と半角スペースを入れる。 Shift + Enter で順序リストを次の行に継続する。

箇条書き

テキストの先頭に * と半角スペースを入れる。 Shift + Enter で箇条書きを次の行に継続する。

参考サイト

特定のポートを使ってるプロセスを lsof コマンドで確認する方法。

特定のポートを使ってるプロセスを lsof コマンドで確認する方法をメモしておく。

特定のポートを使ってるプロセスを確認する方法

lsof コマンドを使って特定のポートを使ってるプロセスを確認する方法を書いていく。

lsof コマンド

lsof コマンドは man lsof すると lsof - list open files と表示するとおりオープンしているファイルを表示するコマンド。

Linux はいわゆるファイル以外にもネットワークソケット、デバイスドライバーとかプロセス情報などもファイルとして扱うので、オープンしているファイルとそのファイルをオープンしているプロセスを調べることで特定のポートを使ってるプロセスを調べることができる。

lsof コマンドは -i オプションを指定するとネットワークソケットに関するプロセスだけを表示するので主に -i オプションの指定方法を書いていく。

lsof コマンドのバージョン。

$ lsof -v
lsof version information:
    revision: 4.91
    latest revision: ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/
    latest FAQ: ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/FAQ
    latest man page: ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/lsof_man
    configuration info: libproc-based
    Anyone can list all files.
    /dev warnings are disabled.
    Kernel ID check is disabled.

lsof コマンドの表示項目

lsof コマンドの表示項目について軽くメモしておく。

$ lsof | head -1
COMMAND    PID USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME

それぞれの項目の意味を書いていく。

項目 意味
COMMAND ファイルを開いてるプロセスのコマンド名。e.g. Google, com.docke
PID プロセス ID
USER ユーザー名
FD ファイルディスクリプタ
TYPE 種類。e.g. IPv4, IPv6, unix
DEVICE バイス
SIZE/OFF
NODE プロトコル。e.g. TCP, UDP
NAME ファイル名あるいはポート

-i:<ポート番号> で 特定のポートを使ってるプロセスを確認

-i オプション で -i:<ポート番号> みたいにすると特定のポート番号を使ってるプロセスだけを表示する。

たとえば 8080 番ポートを使ってるプロセスを確認するなら lsof -i:8080 みたいに実行する。

$ lsof -i:8080
COMMAND    PID USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
Google     496  who   21u  IPv6 0xbf915afa7c00c5e1      0t0  TCP localhost:59317->localhost:http-alt (ESTABLISHED)
Google     496  who   22u  IPv6 0xbf915afa7c00d221      0t0  TCP localhost:59318->localhost:http-alt (ESTABLISHED)
com.docke 1511  who   51u  IPv6 0xbf915afa9f554121      0t0  TCP *:http-alt (LISTEN)
com.docke 1511  who   52u  IPv6 0xbf915afa7c00cc01      0t0  TCP localhost:http-alt->localhost:59317 (ESTABLISHED)
com.docke 1511  who   53u  IPv6 0xbf915afa7c00b9a1      0t0  TCP localhost:http-alt->localhost:59318 (ESTABLISHED)

-i:<サービス名> で 特定のポートを使ってるプロセスを確認

ウェルノウンポートが割り当てられてるサービスは -i オプションで -i:<サービス名> みたいにサービス名を指定することもできる。

たとえば ssh (22 番ポート) を使ってるプロセスを確認するなら lsof -i:ssh みたいに実行する。 ウェルノウンポートはポート番号とサービス名のマッピングはわりと自明なのと自分が使ってるプログラムはウェルノウンポートとは違うポートを使ったりするので -i オプションをこの使い方で使うことはあまりない。

$ lsof -i:ssh
COMMAND   PID USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
ssh     17350  who    3u  IPv4 0xbf915afa83a0c291      0t0  TCP xxx.xxx.xxx.xxx:59395->ec2-yyy-yyy-yyy-yyy.ap-northeast-1.compute.amazonaws.com:ssh (ESTABLISHED)

-n オプション: 名前解決をしない

lsof コマンドはデフォルトで接続先ホストの名前解決をするけど -n オプションを指定すると名前解決しなくなる。 lsof コマンドが名前解決しなくなる分、lsof コマンドの実行速度が速くなる (かもしれない)

-n オプションを指定しないと接続先ホストが ec2-yyy-yyy-yyy-yyy.ap-northeast-1.compute.amazonaws.com みたいに名前解決して表示する。

$ lsof -i:22
COMMAND   PID USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
ssh     17350  who    3u  IPv4 0xbf915afa83a0c291      0t0  TCP xxx.xxx.xxx.xxx:59395->ec2-yyy-yyy-yyy-yyy.ap-northeast-1.compute.amazonaws.com:ssh (ESTABLISHED)

-n オプションを指定すると接続先ホストが yyy-yyy-yyy-yyy みたいに IP アドレスが表示する。

$ lsof -n -i:22
COMMAND   PID USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
ssh     17585  who    3u  IPv4 0xbf915afa960b1291      0t0  TCP xxx.xx.xxx.xxx:59623->yyy.yyy.yyy.yyy:ssh (ESTABLISHED)

-P オプション: ポート番号をサービス名に変換しない

lsof コマンドはデフォルトでポート番号をサービス名に変換して表示するけど -P オプションを指定するとポート番号をサービス名に変換しなくなる。 lsof コマンドがポート番号をサービス名に変換しなくなる分、lsof コマンドの実行速度がチョット速くなる (かもしれない)

-P オプションを指定しないと22番ポートが ssh みたいにサービス名に変換して表示する。

$ lsof -n -i:22
COMMAND   PID USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
ssh     17585  who    3u  IPv4 0xbf915afa960b1291      0t0  TCP xxx.xx.xxx.xxx:59623->yyy.yyy.yyy.yyy:ssh (ESTABLISHED)

-P オプションを指定すると22番ポートがそのまま 22 と表示する。 個人的にはポート番号はサービス名に変換しないでそのまま表示するほうが分かりやすいので -P オプションはデフォで指定してる。

$ lsof -P -i:22
COMMAND   PID USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
ssh     17585  who    3u  IPv4 0xbf915afa960b1291      0t0  TCP xxx.xxx.xxx.xxx:59623->ec2-yyy.yyy.yyy.yyy.ap-northeast-1.compute.amazonaws.com:22 (ESTABLISHED)

-i オプションの他の使い方

-i オプションは -iUDP みたいにして UDP のポートを使ってるプロセスだけ表示するとか -i@ec2-yyy-yyy-yyy-yyy.ap-northeast-1.compute.amazonaws.com みたいにして接続先ホストが ec2-yyy-yyy-yyy-yyy.ap-northeast-1.compute.amazonaws.com のプロセスだけ表示するとか -i6 みたいにして IPv6 を使ってるプロセスだけ表示するとかできてかなり便利。

参考サイト

Pixela の CLI ツール pa を作りました。

PixelaCLI ツール pa を作りました。

github.com

pa とは?

paPixelaCLI ツールです。

pa はシェルの補完機能を使ってコマンドとかフラグをサクサクと軽快に入力できて PIxela サービスをとても簡単に利用できます。あと、タイプが苦手でタイプミスが多いという人は結構いると思いますが (自分はタイプがかなり苦手です)、シェルの補完が効くのでタイプ量が必要最小限に抑えることができてタイプミスのイライラから解放されます!

シェルの補完は pa completion zsh みたいなコマンドでシェルの補完スクリプトを生成したのをシェルに読み込ませて利用することができます。 シェルの補完スクリプトの生成は Zsh, Bash, Fish と PowerShell の補完スクリプトの生成に対応しています。

シェルの補完のデモを GIF にしてみました。なんとなくですが雰囲気が伝わると思います。

demo

Pixela とは?

任意の数値を登録してアレのあれっぽくグラフを作れるクールな API サービスです。

詳しくは↓

pixe.la blog.a-know.me

使い方

PIxela の API

こんな感じで使います。

フラグが結構多いですがシェルの補完が効くのでサクサク入力できます。

$ pa graph create \
    --id=your-graph-id \
    --name=your-graph-name \
    --type=int \
    --unit=count \
    --color=ichou

$ pa graph get | jq
{
  "graphs": [
    {
      "id": "your-graph-id",
      "name": "your-graph-name",
      "unit": "count",
      "type": "int",
      "color": "ichou",
      "timezone": "",
      "purgeCacheURLs": null,
      "selfSufficient": "none",
      "isSecret": false,
      "publishOptionalData": false
    }
  ]
}

現時点の Pixela の最新バージョンの v1.18.0 のすべての API をサポートしています。

Pixela のユーザー名とトーク

Pixela のユーザー名は --username フラグで指定して Pixela のトークンは --token フラグで指定します。

$ pa graph get --username=yourname --token=thisissecret

Pixela のユーザー名とトークンは環境変数で指定することもできます。

Pixela のユーザー名は PA_USERNAME 環境変数で指定して Pixela のトークンは PA_TOKEN フラグで指定します。

$ export PA_USERNAME=yourname
$ export PA_TOKEN=thisissecret
$ pa graph get

Pixela のユーザー名とトークンは設定ファイルで指定することもできます。 v1.1.0 以降が設定ファイルに対応しています。

$ cat ~/.pa
username = "yourname"
token = "thisissecret"
$ pa graph get

pa は次の優先順位でユーザー名とトークンを使用します。 それぞれの項目はその下の項目よりも優先されます。

シェルの補完スクリプトの生成

Zsh, Bash, Fish, PowerShell の補完スクリプトを生成して利用できます。

$ pa completion <SHELL> > /path/to/completion

Zsh を使っているならこんな感じのコマンドでシェルの補完が効くようになります。

$ pa completion zsh > ~/.zsh/completions/_pa
$ . ~/.zsh/completions/_pa

インストール方法

Homebrew

$ brew tap ebc-2in2crc/tap
$ brew install pa

Developer

$ go get -u github.com/ebc-2in2crc/pa/...

手動でのインストール

https://github.com/ebc-2in2crc/pa/releases からダウンロードした zip ファイルを展開した中にあるファイルをパスの通ったディレクトリに入れる。

動機

Pixela はシンプルでいろんなことに応用できるとても便利な API サービスです。

普段は pixela4go という Pixela の Go クライアントを使って Pixela のサービスを利用しているのですが「ちょっとしたことを試したり確認するときは CLI があると楽だよなー」と以前から結構感じていました。

実は Pixela は pi という公式 CLI ツールがあります。pi は Pixela を薄くラップした CLI ツールでコマンド体系が分かりやすくて自分もとても便利に使っているのですが、自分はかなりタイプが苦手なこと & pi はシェルの補完が効かないことが少し使いにくさを感じていました。 そんなときにふと、シェルの補完が効かないならシェルの補完が効くようにすればいいじゃん => Pixela との通信部分は pixela4go を使えば CLI 部分を実装するだけでよさそう => 作ってみよう! みたいな勢いで作りました。

pa という名前

コマンドの名前が長いとタイプするのが面倒くさいので短い名前にしようと最初から決めていて、Pixela の先頭1文字と末尾1文字をそれぞれもらって pa という名前にしました。

まとめ

バグとかあると思いますし「こーしたら使いやすくなる」とかあったら issue とか PR 作ったり声かけてもらえると嬉しいです。

ということで Pixela の CLI ツール pa の紹介でした。