unoh.github.com

コマンドラインで作業する上で知っておくといいテクニック

Thu Mar 29 03:46:34 -0700 2007

ちょうど入社から半年で有給発生しつつも本日が退職日になりましたjokagiです.もう花見の季節ですね!!

ちょうどラボブログの当番のようで,退職記念にjokagiが普段の開発で使っているテクニックとは呼ぶにはおこがましい小手先の技をつらつら書いてみたいと思います. これを覚えればjokagi程度には仕事をこなせるかも!?

コマンドの使い方を覚えよう

基本的なコマンドの使い方やコンソールなどの使い方は書籍いろんなサイトで覚えてください. ここでは一応一通りなんとなくでもコマンドを扱える人がさらに覚えるといいかもしれないことだけを記述します.

また,これからの解説はシェルはbash,その他のコマンドの多くはGNU Toolsと呼ばれることのあるGNU findやcoreutilsなどを用いた環境でのオプション例や実行例になります.

echo

いわゆる指定された文字列を出力するコマンドですね. 知らない人も多いみたいですが,echoも実はいくつかのオプションを受け付けます.

-eバックスラッシュ(半角円記号)に続く文字を特別視する
-n最後に改行文字を入れない

grep(egrep,fgrep,pgrep),fgrep,zgrep

grepはファイル内をパターン検索(意訳的にいうと文字列検索)を行うコマンドです. ここで覚えておくべきオプションは下記のとおりになります.

-i英大小文字を等価に扱う.いわゆる「A」と「a」が同じということを表す
-r検索対象にディレクトリを指定した場合,ディレクトリ内を再帰的に検索する
-E -F -Pパターンの扱いを変える.egrep,fgrep,pgrepはそれぞれ-E,-F,-Pが指定されたときと等価の処理を行う
-v指定キーワードが含まれる行を除外する
-l条件に一致するファイル名だけを出力する

grepはアプリケーションの解析では(多分)非常に基本的かつ重要なコマンドです. 当然これだけでは見つからないものもでてきますが,結構有効です.

find

-type <TYPE>「-type f」でファイルだけを対象に,「-type d」でディレクトリだけを対象にする
-name <NAME><NAME>と一致する名前を対象にする.ワイルドカードを使うことができる
-uid <UID>オーナーユーザーのIDが<UID>のものを対称にする
-gid <GID>オーナーグループのIDが<GID>のものを対称にする
-exec <COMMAND-LINE> \;対象毎に「<COMMAND-LINE>」を実行する.「{}」を含ませると対象が展開される

sed

sedは通常行指向でテキストの置換などを行うときに使用します. しかし,通常その結果は標準出力に出てくるだけですが,-iを使用することで実際に入力に使用したファイルを置換することができます.

-i実行された置換を読み込んだファイルに実際に適用する

diff

-uCVSやsvnなどと近い書式で差分情報を出力する
-r比較として指定された対象がディレクトリだった場合,再帰的に中身を評価する
-Nいずれの比較先にだけ存在するファイルも対象とする

od

オプションに「-tx1」と指定すると1バイトずつ16進数で表示します. なぜそういう挙動になるかはマニュアルなどで調べてください.

sendmail

個人的にはメーラーとしてコマンドsendmailをオプション「-t -i」としてよく使います. その理由はPHPのmail()は通常内部で/同オプションをあわせてusr/sbin/sendmailを使用するからです. この辺について興味がある方は mail()でメールが送信できるかどうかの確認手順 - よくきたWiki やPHPのソースなどを参照してください.

vi,emacs

サーバー上で作業はできるほうがいいですね. 使ったことがないのに好みでどうぞってのは判断がなかなかつかないですね. jokagiはemacsとviは7:3位の割合で併用していますが,emacsは入っていない場合があるので,どっちがいいか判断がつかない方はviをお勧めします.

その他大体の覚えるべきオプション

すべてのコマンドが対応しているわけではないですが,おおよそのコマンドで有効なオプションです.

--オプションの終了を表す
--helpコマンドの使い方を出力する

実用例

メールを送ってみる

コマンドsendmailと併用してメールを送るテストをする
$ echo -e 'From: <from@example.com>\nTo: <to@example.com>\nSubject: test\n\ntest' | /usr/sbin/sendmail -t -i -ffrom@example.com

マルチバイトの中身(バイトストリーム)を見る

ここではechoとodを併用します.余計な改行文字が含まれないようにするためにechoには-nを,バイト表示をするためにodには-tx1を使用します.

マルチバイト文字のバイトストリームを16進数表記で調べる
$ echo -n '在籍中お世話になりました' | od -tx1
 0000000 e5 9c a8 e7 b1 8d e4 b8 ad e3 81 8a e4 b8 96 e8
 0000020 a9 b1 e3 81 ab e3 81 aa e3 82 8a e3 81 be e3 81
 0000040 97 e3 81 9f

Poderosaなど,比較的簡単に文字エンコードを変更できる場合,Poderosa側で16進数にしたい文字エンコードに変更した上で上記のようにコマンドを実行するとお手軽に調べることができる場合があります(環境によってはできない可能性もあります) また,iconvやその他を併用してもいいでしょう.

さらに文字エンコードを変更する
$ echo -n '在籍中お世話になりました' | iconv --from UTF-8 --to EUC-JP | od -tx1
 0000000 ba df c0 d2 c3 e6 a4 aa c0 a4 cf c3 a4 cb a4 ca
 0000020 a4 ea a4 de a4 b7 a4 bf
 0000030

HTMLの生成をしているファイルを特定する

「class="header"」というHTMLタグの属性っぽいものを扱っているファイルを探して出力する
$ fgrep -r 'class="header"' .

あるウェブアプリケーションが出力するHTMLの処理がおかしいときに上記のようにして調べます. おおよそそれっぽいのがでてきたら-lも併用します.

上記に引っかかるファイルのファイル名だけを出力する
$ fgrep -lr 'class="header"' .

ハードコーディングされた値があるファイルを特定する

メールアドレスやドメイン名を固定で記述しているファイルを探して出力する
$ fgrep -r 'example.com' .
$ fgrep -r 'support@example.com' .

適当に開発されたウェブアプリケーションはえてして値がハードコーディングされていることが多いです. それらを定数に置き換えるときも上記のような検索が有効です.

脆弱性を調べる

XSSになりそうなファイルを探して出力する
$ fgrep -ir '<input' . | egrep -i '\$(_GET|_POST)'

よくあるこういう出力をしているファイルを探します.

<input type="name" value="<?=$_GET['name']?>">

上記grepでこういうフォーム要素を出力している可能性のあるファイルを探します.

XSSになりそうなファイルを探して出力する
$ egrep -ir '(select|update|insert)[ \t]+\$' . | grep -iv '</?select'

これでたとえば「select * from users where id = $id」のようなSQL文字列を検索します. これらはプレースフォルダーなどを使用すれば「select ~ where id = ?」などとなるはずなので,変数名は基本的にSQL中に出てくることがないことに着目しています. また,「<select~」などのHTMLは除外しています.

ある名前のファイルやディレクトリを調べる

カレントディレクトリ配下でファイルindex.htmlを調べる
$ find . -type f | fgrep index.html

あるファイルだけ,ディレクトリだけ何々をする

emacsのバックアップを見つける,削除する
$ find . -name '*~'
$ find . -name '*~' -exec rm {} \;
ディレクトリ.svnを削除する
$ find . -name .svn -type d -exec rm -rf {} \;
オーナーがrootなファイルやディレクトリを探す
$ find -uid 0
ついrootで作ってしまったファイルなどのオーナーユーザーをjokagiにする
$ find -uid 0 -exec chown jokagi {} \;

複数のファイルの内容を一気に置換する

「sjis」をすべて「Shift_JIS」にする
$ sed -i 's/sjis/Shift_JIS/g' `grep -irl sjis .`

多分覚えておくといいこと

文字列のクォートについて

文字列をダブルクォートすると,シェルが文字列を評価する場合があるので(「$」とか)個人的にはなるべくシングルクォートを使うことをお勧めします. また,クォート文字を含んだ検索をする正規表現など,エスケープ処理が複雑になってくるとシェルのためのエスケープか正規表現(あるいはその他のための)正規表現かわからなくなってしまうことがあります. そういう時は素直にオプション値をファイルにして読み込むという手段もあります.

コマンドの実行結果をオプション値として取り込む

上記のようにコマンドの実行結果をオプション値で取り込むと便利なことがまれにあります. 実行結果をコマンドラインに取り込む方法はそれ自体をバッククォートでくくることで実現できます.

jokagiがよくやるのは下記のようなパターンです.

拡張子が「.html」のファイルを全部emacsで読み込む
$ emacs `find -name '*.html'`

ファイルがあまりに多いときはより厳密に絞り込むほうがいい場合もあります.

最後に

半年間ではありますが,ウノウでは多くのことを勉強をさせていただきました. jokagiは本日で退職ですが,ノッキングオンという会社に移籍をすることになります. ノッキングオンは広告キャンペーン携帯アフェリエイトなどを運営している企業です. 今後ウノウとノッキングオンはいろいろな面で協力をしていこうということになっていて,今後は両社でいろいろな価値を作って行くことになると思います.

また,jokagi個人もノッキングオンでもウノウ,あるいはこのウノウラボのように自分たちが考えたことを,自分のノウハウを世間と共有できるようなコンテンツや価値を作って行きたいなぁと思います. これから改めてみなさまよろしくお願いいたします. それではあでゅー.