超高速bashオペレーション２


過去に書いた記事を再編して載せてます。
超高速bashオペレーションの続きと補足です。
___

前回は`history`を使ったインクリメンタルサーチのTipsを紹介した。
「知らなかったっす！」といくつかの反響を頂き、併せて使うと捗るぜ！という小技をいくつか紹介しようと思う。
基本的に確実性を高めるために実践している小技たちだ。


# 『簡単フィルタ＆検索機能　grep』

コマンドの後に「`|`（パイプ）」で渡すといろいろと捗る「`grep`」さん。
通常の使い方は、

```bash
$ (command) | grep (keyword)
```

キーワードを否定にしたい場合は、`-v`オプションで  

```bash
$ (command) | grep -v (keyword)
```

よく使うのは、`grep -v grep`で表示させたいものだけに絞る。
例えば

```bash
$ ps -ef | grep java | grep -v grep
```

とすると`java`のキーワードに引っ掛かったプロセスのみ表示される。

よくあるシチュエーションでDBサーバのホスト名とIPなんだっけ？とかなったらどうする？
コメントにDB Serverとか書いてることが多いから、`cat`でhostsファイル開いてパイプで渡して`grep`……。

```bash
$ cat /etc/hosts | grep DB
```

とかやるよね。
ああ、`cat`もメンドクサイ。ｗ
同じことが

```bash
$ grep DB /etc/hosts
```

で出来る。
1文字でも多くキーボードを叩きたくない性質でね……。
１割でも２割でも数が減るなら、それを採用する。
それがオペレーション全体で１割２割になるとその出来た時間で他のこと出来るからね。

`grep`さんはテキストフィルタ機能なんだというところに着目すると別なことも出来る。
例えば、複数のシェルを変更したいのだが変更箇所や変更漏れを探すの手間だなと思うことないだろうか？
ポート番号変更、ホスト名変更など、いろいろとシェルに埋め込まれている場合とかとても面倒だ。
そんなとき、`vi`で文字列検索をしたり、`cat`で`grep`で引っ掛けたり……。（うんざり）
修正漏れはどうやって確認する？ｗ
あるディレクトリにシェルが複数あって、各シェルの特定文字列を検索したいというパターンだと

```bash
$ grep (keyword) /hogehoge/*.sh
```

とかやるとキーワードに引っ掛かった文字列が含まれるファイル名とその行がざっと表示される。
`vi`で編集して、また`grep`で引っ掛けてと繰り返すと変更箇所特定＆変更漏れ確認が同時に出来る。

```bash
$ cd $DOMAIN_HOME
$ grep 7001 *.sh
hoge_start.sh: ～省略～7001～省略～
hoge_stop.sh: ～省略～7001～省略～
moge_stop.sh:～省略～7001～省略～
$ vi hoge_start.sh
$ !gr
grep 7001 *.sh
hoge_stop.sh: ～省略～7001～省略～
moge_stop.sh:～省略～7001～省略～
$ !vi:p
vi hoge_start.sh
$ ^art^op
vi hoge_stop.sh
$ !gr
grep 7001 *.sh
moge_stop.sh:～省略～7001～省略～
$ !vi:p
vi hoge_stop.sh
$ ^h^m
vi moge_stop.sh
$ !gr
grep 7001 *.sh
$
```

てな感じである。
シェル製造の観点からは、埋め込んでしまうのは難があるので、普通やらないけど、プロダクトがインストール時に生成したシェルなどは思いっきり埋め込んでいたりするので、このTipsを覚えておくと作業効率が抜群に上がる。

キーボードを多く叩かない替わりに確実に確認して作業の信頼性を高める。
これが最大のポイントである。


# 『お手軽カウンター　wc』

コマンドの後に「`|`（パイプ）」で渡すといろいろと捗る「`wc`」さん。ｗ

```bash
$ (command) | wc -l
```

で、コマンドの標準出力の引っ掛かった行数

```bash
$ wc -l ファイル名
```

で、ファイルの行数を複数ファイルの場合は最後に合計の行数

```bash
$ wc -w ファイル名
```
で、ファイルの文字数を複数ファイルの場合は最後に合計の文字数

```bash
$ wc -c ファイル名
```
で、ファイルのバイト数を複数ファイルの場合は最後に合計のバイト数

画面指さして数えてないよね？ｗ
オプション見るだけで使えそうだぜ！と思うと思うが、筆者は「-l」を多用する。

例えば、Apacheでhttpdプロセスが50コ上がってるか確認したいとき、

```bash
$ ps -ef | grep httpd | grep -v grep
～（わらわら～）～
$ !! | wc -l
ps -ef | grep httpd | grep -v grep | wc -l
50
$
```

とやるとビシッと確認できる。
違う数値の場合、何らかの問題でプロセスゾンビ化かなと異常も検知出来たり。

例えば、糞長いプロセス名でいくつ上がっているかわからんときとか、

```bash
$ ps -ef | grep java | grep -v grep
～（わらわらわら～）～
$ !! | wc -l
ps -ef | grep java | grep -v grep | wc -l
2
$
```

検索キーワードを追加、修正しながら、自分が納得いくまで確認できる。

`netstat`とかを`grep`で引っ掛けて数数えたりするのにも使えるよね。

Linuxサーバを構築していて、いろんな人間が五月雨て作業し、導入パッケージがわけわかめで環境定義書の直しやサーバ管理が大変なことがあると思うんだが、

```bash
$ !5
```

もとい。ｗｗｗ

```bash
$ rpm -qa --qf '%{name}-%{version}-%{release}.%{arch}.rpm\n'
```

このコマンドで
32bit、64bit、パッケージバージョン詳細など細かく出力してくれる。
テキストエディタにコピペして使うなり、`alias`登録して呼び出すなり、`history`の履歴番号をメモするなりして使ってくれたまえ。
まあ、１度は涙を飲んで打たないとダメだけど。ｗ

```bash
$ !! | wc -l
rpm -qa --qf '%{name}-%{version}-%{release}.%{arch}.rpm\n' | wc -l
```

で導入されているパッケージ数が拾える。
更に詳細は次の項で紹介することにしよう。

丁度、社内メールでのヘルプに載せたので、ついでに書いておくとディレクトリ内の大量ファイルを扱う時、いつも使っているコマンドもより気を遣わないとダンプを吐いてコマンドエラーになったりいろいろと不都合がある。
ディレクトリの内のファイル数を数えたい場合、

```bash
$ ls -f　/hoge | wc -l
```

または、

```bash
$ find /hoge -type f | wc -l
```

`ls`コマンドは内部で勝手にソートが走るので、大量ファイルだと線形に処理が重くなる。
`-f`オプションでソートしない。
まあ、`find`の方が早いですけど。ｗ

コマンドで目視確認もいいけど、更に数を数えてエビデンスに残したりすると正確性は更に向上する。


# 『ソート』

コマンドの後に「`|`（パイプ）」で渡すといろいろと捗る「`sort`」さん。ｗｗｗ

```bash
$ (command) | sort
```

あんまり使う機会はないかな？
オプションがいろいろあり、便利に使える。
前の項の「Linuxサーバを構築していて、いろんな人間が五月雨て作業し、導入パッケージがわけわかめで環境定義書の直しやサーバ管理が大変なことがあると思うんだが、」の詳細を紹介しよう。
そんなにすごいことはやっていない。ｗ
日々の作業終了時に、

```bash
$ rpm -qa --qf '%{name}-%{version}-%{release}.%{arch}.rpm\n' | wc -l
```

の値の確認と

```bash
$ rpm -qa --qf '%{name}-%{version}-%{release}.%{arch}.rpm\n' | sort > /tmp/`hostname`_`date +%Y%m%d%H%M%S`_rpm.txt
```

を実行し、値が違った際に過去に取った結果同士の`diff`を取ると何が追加されて何が削除されたか把握できる。
`sort`するのは、`diff`を取る際に見づらくなったりするのを防ぐのと毎回同じルールで表示した方が都合がよいからだ。
`sort`コマンドもオプションなしでは第一カラム目を辞書順に表示するが、オプションによっては第二カラム目を`sort`出来たり、覚えると効率が上がる。

先ほど、`ls`コマンドが内部で`sort`していると若干触れたが、ソートオプションも用意されている。
現場で目視確認漏れで「ログが出力されていない！」と大騒ぎしていたメンバーがいたのだが、「`ls -l`」の結果が単に新しく出力されたログが一番下に表示されると勘違いしたらしい。
`-t`：タイムスタンプ順でソート
`-r`：逆順にソート
を使用し、「`ls -ltr`」とすると常に一番下が最新に作成されたファイルが表示されることになる。
オプションなしだと辞書順なので注意が必要だ。

```bash
$ ls -ltr
```

尚、筆者は`alias`はほとんど使わない。
`history`とともに紹介されていることが多い`alias`であるが、オペレーションミスを誘いやすいという経験からの結論に達したのでほとんど使用していない。
RedHatでは、「`ll`」に「`ls -l`」が登録されていると思うのだが、aliasでは環境によって自由に設定できる。
＃`vim`→`vi`も登録されてるし、よく使うが。
`alias`と素で叩くか、そのユーザの.bashrc内に記載があるので、オペレーション開始前に確認しておくことをオススメする。
それが面倒な場合は、`alias`は使わない方がいい。
筆者が「`ll`」を使わない理由は、常に隠しファイルやディレクトリも表示し、現在のディレクトリ階層の把握・パーミッション確認や隠しファイルの存在確認を無意識下でやっているからだ。
なので常に「`ls -al`」と隠しファイルも全て表示するようにしている。

```bash
$ ls -al
```
プロダクトが作成する設定ファイルなどは隠しファイルになっていることが多く、アンインストール漏れで隠しファイルを削除し忘れて、再インストール失敗なんてことはざらにあるからだ。
隠しファイルの削除などに便利な正規表現は次回触れようと思う。

オペレーション環境の把握やコマンドの特性、見やすい形でソートして記録するなどすることで、想定外のミスが減り、オペレーション全体から見ると無駄がなくなる。
環境で左右される`alias`など使わずに癖をつけることで、どの環境でも正確にオペレーションが出来る。
※余計にキーボード打ってるじゃないか！と思う方もいると思うが、楽して正確性を得るがポイント。
　大局的にみると`alias`は百害あって一利なしである。（毎回`alias`確認するなら別[他ユーザログイン毎]）


# 『検索くん』

今回最後に触れるのは`find`コマンドだ。
先ほどさらっと触れたので、今回、自分備忘録的に取り上げることにする。
内容的には目から鱗でもなんでもない。
LPICでも学べるし、お題目のLPICじゃ学べないからは外れる。ｗ
環境によって構文が違うので、実は筆者は余り使わない。ｗｗｗ

単純に名前で探すときは、

```bash
$ find (dir) -name (keyword)
```
「.(ドット)」カレントディレクトリ以下検索なので、今いるディレクトリ以下のシェルを検索する場合、

```bash
$ find . -name '*.sh'
```
とすると検索できる。
execオプションと組み合わせると更にいろいろ捗る。
「.(ドット)」カレントディレクトリ以下検索なので、今いるディレクトリ以下のシェルを検索し削除する場合、

```bash
$ find . -name '*.sh' -exec rm -f {} \;
```
検索して表示し、続いて削除なら、

```bash
$ find . -name '*.sh'
$ !! -exec rm -f {} \;
find . -name '*.sh' -exec rm -f {} \;
```
とするのが安心かな。

先ほどのパッケージの管理とともに多人数五月雨環境で取得しておくといいのが、
この1日に修正があったファイル、ディレクトリのリストを取る

```bash
$ find / -mtime -1 -ls > /tmp/`hostname`_`date +%Y%m%d%H%M%S`_find.txt
```
としておいておくと管理に便利であろう。

全ファイル、ディレクトリの詳細リストは

```bash
# ls -alR / > /tmp/`hostname`_`date +%Y%m%d%H%M%S`_ls.txt
```
もいいけど、いろいろとエラーが出てスマートではないかも。

```bash
# find / -ls > /tmp/`hostname`_`date +%Y%m%d%H%M%S`_ls.txt
```
とやるのがいいのかな。

尚、筆者は「`ls -alR`」と「`grep`」を組み合わせて簡単検索してたりもする。
何か特定のファイルが含まれているか、簡易的＆直観的に探して、パスの確認などをしたりする。

```bash
$ ls -alR | grep hoge
```
ととあるディレクトリ以下に目的のファイルがあるか確認して、

```bash
$ ls -alR > /tmp/lsR.txt
$ vi /tmp/lsR.txt
```
とテキストに吐いて、`vi`で検索するのだ。ｗ
どのディレクトリ階層にあるかとかパーミッションを調べてから、そのパスにアクセスしたりしてる。
`find`の構文をよく覚えていないからだけど。ｗ
これは余りスマートではないことは自覚している。


筆者の場合、長く某運用管理ツール導入部隊にいたため、マルチプラットフォーム対応、本番稼働中サーバへの追加導入、限られた時間とかなりハードな状況でのオペレーション経験から蓄積されたノウハウになる。
当時はcsh環境での導入だったのだが、インフラ構築をメインにしてからcshからbashへの適応化したものだ。
コマンドを忘れたら気軽にhelpを見るなど日々の擦りこみも欠かさない。(`ls`とか`ps`って環境によって違うから)
思い込みや癖が不要なトラブルを生むと痛感しているので、常に環境特化にならないように気を付けている。

* 見易さのため「`|`(パイプ)」の前後にスペース入れてますけど、筆者の実オペレーションではスペースすら入れないです。（めんどいからｗ）

2011/11/19 up