Apache 便利コマンド集

コマンドラインで使う Apache 関連の便利コマンド集。

## 構文チェック
```bash
httpd -t
```
```bash:出力例
Syntax OK
```
conf ファイルにシンタックスエラーがないか確認するコマンド。
再起動前に必ず確認しよう。
`service httpd configtest` や `apachectl configtest` でもほぼ同様だが上記の方が打鍵数が少ない。

## 再起動
```bash
httpd -k graceful
```
緩やかな再起動。
前述の構文チェックが自動で走り、シンタックスエラーがあった場合は再起動されない。
`service httpd graceful` や `apachectl graceful` でも同様だが上記の方が打鍵数が少ない。`systemctl graceful httpd` は機能しない。
`graceful` を検証している記事 [^graceful] でうまく動作していない報告もあるので、CentOS 7 では `systemctl reload httpd` の方がいいかもしれない。

[^graceful]: http://www.lesstep.jp/step_on_board/apache/610/

## エラーログ
```bash
tailf /var/log/httpd/error_log
```
```bash:出力例
[Sun Jan 01 09:00:00.054284 2017] [cgi:error] [pid 18504] [client 127.0.0.1:59490] script not found or unable to stat: /var/www/cgi-bin/php.ini
[Sun Jan 01 09:00:00.064974 2017] [autoindex:error] [pid 18504] [client 127.0.0.1:59490] AH01276: Cannot serve directory /var/www/html/: No matching DirectoryIndex (index.html) found, and server-generated directory index forbidden by Options directive
[Sun Jan 01 09:00:00.303906 2017] [core:error] [pid 18501] [client 127.0.0.1:59494] AH00126: Invalid URI in request GET /sdk/%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E/etc/vmware/hostd/vmInventory.xml HTTP/1.1
[Sun Jan 01 09:00:00.304917 2017] [core:error] [pid 18501] [client 127.0.0.1:59496] AH00135: Invalid method in request <script>alert(1)</script> / HTTP/1.1
[Sun Jan 01 09:00:00.311338 2017] [cgi:error] [pid 18501] [client 127.0.0.1:59498] script not found or unable to stat: /var/www/cgi-bin/awstats.pl
[Sun Jan 01 09:00:00.312637 2017] [cgi:error] [pid 18501] [client 127.0.0.1:59498] script not found or unable to stat: /var/www/cgi-bin/awredir.pl
[Sun Jan 01 09:00:00.445709 2017] [core:error] [pid 18501] [client 127.0.0.1:59500] AH00126: Invalid URI in request GET /../../windows/dvr2.ini HTTP/1.1
[Sun Jan 01 09:00:00.446445 2017] [core:error] [pid 18501] [client 127.0.0.1:59502] AH00126: Invalid URI in request GET /htdocs/../../../../../../../../../../../etc/passwd HTTP/1.1
[Sun Jan 01 09:00:00.447084 2017] [autoindex:error] [pid 18501] [client 127.0.0.1:59504] AH01276: Cannot serve directory /var/www/html/: No matching DirectoryIndex (index.html) found, and server-generated directory index forbidden by Options directive
[Sun Jan 01 09:00:00.460959 2017] [core:error] [pid 18501] [client 127.0.0.1:59504] AH00126: Invalid URI in request GET /help/../../../../../../../../../../../../../../../../etc/shadow HTTP/1.1
```
util-linux パッケージに含まれる `tailf` コマンドはファイルの末尾10行を表示し、その後ファイルに追加される行を待ち続ける。`tailf` は `tail -f` と似ているが、ファイルへの追加書き込みがないとファイルへアクセスを行わない。そのためファイルのアクセス時間は更新されず、ログに関る動作が起らない間は定期的なファイルシステムのフラッシュも生じない。[^tailf]

[^tailf]: https://linuxjm.osdn.jp/html/util-linux/man1/tailf.1.html

ただし `tailf` は現在非推奨になっており、2017年3月に util-linux から削除されるらしい。[^tailf-deprecated]

[^tailf-deprecated]: http://man7.org/linux/man-pages/man1/tailf.1.html

`less +F /var/log/httpd/error_log` を使えという話もある。[^less]
[^less]: http://b.hatena.ne.jp/entry/www.brianstorti.com/stop-using-tail/

## コマンド履歴検索
コマンドラインで <kbd>Ctrl</kbd> + <kbd>r</kbd> を押下するとプロンプトが以下のように変化してコマンド履歴の検索モードになる。

```
(reverse-i-search)`':
```

この状態でコマンド履歴から絞り込みたい文字列を入力すると、<kbd>↑</kbd> を連打しなくても簡単に過去のコマンドにたどり着ける。

```text:`gra`で絞り込んだ例
(reverse-i-search)`gra': httpd -k graceful
```

### コメントでタグ付け

コマンドの最後に `#` を入力するとそれ以降はコメントとして無視される。これをタグとして利用して、キーワードを思い出しにくいコマンドの履歴を検索するときに利用することができる。 [^timedia]

[^timedia]: http://labs.timedia.co.jp/2011/12/improve-reusability-of-shells-command-line-history.html

```bash:入力例
httpd -t -D DUMP_CONFIG 2>/dev/null | grep '# In' | awk '{print $4}' #conflist
```
```text:`#conflist`で検索した例
(reverse-i-search)`#conflist': httpd -t -D DUMP_CONFIG 2>/dev/null | grep '# In' | awk '{print $4}' #conflist
```

## ApacheTop
```bash
yum -y install epel-release && yum -y install apachetop
```
```bash
apachetop
```
```bash:出力例
last hit: 06:12:43         atop runtime:  0 days, 00:00:30             06:12:49
All:            5 reqs (   0.2/sec)        332.3K (   14.4K/sec)      66.5K/req
2xx:	   5 ( 100%) 3xx:	0 ( 0.0%) 4xx:     0 ( 0.0%) 5xx:     0 ( 0.0%)
R ( 30s):       5 reqs (   0.2/sec)        332.3K (   11.1K/sec)      66.5K/req
2xx:	   5 ( 100%) 3xx:	0 ( 0.0%) 4xx:     0 ( 0.0%) 5xx:     0 ( 0.0%)

 REQS REQ/S    KB KB/S URL
    2  0.22 123.9 13.8*/
    1  0.04  47.6  2.1 /blog
    1  0.08  61.5  5.1 /news
    1  0.06  99.2  5.5 /news/2016/010102
```
ログを解析して現在のアクセス状況を top コマンドのようにリアルタイムに表示してくれる。
<kbd>d</kbd> キーを押下すると URL, HOST, REFERER に切り替えられる。
<kbd>↑</kbd> <kbd>↓</kbd> キーでマーカー `*` を移動して <kbd>←</kbd> <kbd>→</kbd> キーで一覧表示と詳細表示を切り替えられる。

### ログファイルの指定
```bash
apachetop -f /var/www/vhosts/example.jp/log/access.log
```
デフォルトでは `/var/log/httpd/access_log` が参照されるが、それ以外を指定したい場合は `-f` オプションを使用する。

## セキュリティチェック
```bash
yum -y install epel-release && yum -y install nikto
```
```
nikto -h 127.0.0.1
```
```bash:出力例
- ***** RFIURL is not defined in nikto.conf--no RFI tests will run *****
- ***** SSL support not available (see docs for SSL install) *****
- Nikto v2.1.5
---------------------------------------------------------------------------
+ Target IP:          127.0.0.1
+ Target Hostname:    localhost
+ Target Port:        80
+ Start Time:         2017-01-01 09:00:00 (GMT9)
---------------------------------------------------------------------------
+ Server: Apache/2.4.6 (CentOS)
+ Server leaks inodes via ETags, header found with file /, fields: 0x1111 0x5058a1e728280
+ The anti-clickjacking X-Frame-Options header is not present.
+ Allowed HTTP Methods: OPTIONS, GET, HEAD, POST, TRACE
+ OSVDB-877: HTTP TRACE method is active, suggesting the host is vulnerable to XST
+ OSVDB-3268: /icons/: Directory indexing found.
+ OSVDB-3233: /icons/README: Apache default file found.
+ 4197 items checked: 0 error(s) and 6 item(s) reported on remote host
+ End Time:           2017-01-01 09:00:05 (GMT9) (5 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested
```
[Nikto](http://qiita.com/bezeklik/items/12643654dc0c45f4eb29) というセキュリティ診断ツールが EPEL リポジトリーから簡単にインストールできる。
対応方法などの詳細は「[Apacheセキュリティ設定](http://qiita.com/bezeklik/items/1c4145652661cf5b2271)」を参照。

## ログ解析
```bash
grep 01/Jan/2017:12 /var/log/httpd/access_log | awk -F '"' '{print $2}' | awk '{print $2}' | sort | uniq -c | sort -n -r
```
```bash:出力例
     69 /
     48 /en/
     35 /css/base.css
     23 /favicon.ico
     23 /img/example.jpg
```
2017/01/01の12時台のリクエスト別アクセス数を出力するサンプル。
その他のパターンは「[Apache ログを awk と uniq だけで集計する](http://qiita.com/bezeklik/items/f5c292c4360cde140bef)」を参照。

## 設定ファイルの一覧
```bash
httpd -t -D DUMP_CONFIG 2>/dev/null | grep '# In' | awk '{print $4}'
```
```bash:出力例
/etc/httpd/conf/httpd.conf
/etc/httpd/conf.d/autoindex.conf
/etc/httpd/conf.d/userdir.conf
/etc/httpd/conf.d/welcome.conf
```
その他の情報取得は「[Apache の情報をコマンドラインで取得する](http://qiita.com/bezeklik/items/7bbfcbcfeb05c1d57fec)」を参照。