Apacheモジュールã®ä½œæˆã¨gdbã¨loggerã§ã®ãƒ‡ãƒãƒƒã‚°æ–¹æ³•
Apacheã®Filterモジュールを作ã£ãŸè©±ã—ã‚’ã—ãŸã‚‰id:c9katayamaã«æƒ…å ±å…¬é–‹ã—ã‚ã¨è¨€ã‚ã‚ŒãŸã¾ã¾ã§ã—ãŸã®ã§å…¬é–‹ã—ã¾ã™ã€‚
C言語ã®å‹‰å¼·ã—よã†ã‹ãªã€Apache2.xã®ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã‚’作ã£ã¦ã¿ã‚ˆã†ã‹ãªã€gdb使ã£ã¦ãƒ‡ãƒãƒƒã‚°ã—ã¦ã¿ã‚ˆã†ã‹ãªã¨è€ƒãˆã¦ãŸäººã«ãŠå‹§ã‚ã§ã™ã€‚
Javaã§ã®Servletã®é–‹ç™ºçµŒé¨“ã®ã‚る人ã§ã‚ã‚Œã°ã€Filterã®å‡¦ç†ã®å‹•ãやリクエストコンテã‚ストã®è€ƒãˆæ–¹ã¯åˆ†ã‹ã‚Šæ˜“ã„ã¯ãšãªã®ã§ã€ã‚¨ãƒ³ãƒˆãƒªã‚’èªã¿çµ‚ã‚ã‚‹é ƒã«ã¯Apacheã®ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã‚’gdbã§ãƒ‡ãƒãƒƒã‚°ã—ãªãŒã‚‰ä½œã‚‹äº‹ãŒå‡ºæ¥ã‚‹ã¯ãšã§ã™ã€‚
mod_orzを作æˆ
今回ã¯mod_orzã¨ã„ã†Apacheモジュールを作æˆã—ã¾ã™ã€‚
Apacheモジュールを作æˆã™ã‚‹éš›ã«ã¯ã€apxsã¨ã„ã†ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«é–‹ç™ºç”¨ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’使用ã—テンプレートを作りã¾ã™ã€‚
# apxs -g -n orz Creating [DIR] orz Creating [FILE] orz/Makefile Creating [FILE] orz/modules.mk Creating [FILE] orz/mod_orz.c Creating [FILE] orz/.deps # ls orz Makefile mod_orz.c modules.mk
コマンド引数-gã§ãƒ†ãƒ³ãƒ—レート出力ã€-nã§ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«åを指定ã™ã‚‹ã¨orzフォルダãŒä½œæˆã•ã‚Œã€ãã®ä¸ã«ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã®ãƒ†ãƒ³ãƒ—レートãŒå‡ºæ¥ä¸ŠãŒã‚Šã¾ã™ã€‚
ã“ã®ã¾ã¾ã§ã‚‚サンプルã¨ã—ã¦å‹•ãã¾ã™ãŒmod_orzらã—ã表示ã•ã›ãŸã„ã®ã§mod_orz.cã®orz_handlerを以下ã®ã‚ˆã†ã«å¤‰ãˆã¾ã™ã€‚
static int orz_handler(request_rec *r) { if (strcmp(r->handler, "orz")) { return DECLINED; } r->content_type = "text/html"; if (!r->header_only) { int i = 0; for (i = 0; i <= 100; i++) { ap_rputs("orz ", r); } } return OK; }
コンパイルã™ã‚‹éš›ã«ã¯make installã§ã‚‚å¯èƒ½ã§ã™ãŒã€apacheã®è¨å®šãƒ•ã‚¡ã‚¤ãƒ«(httpd.conf)ã«LoadModuleãƒ‡ã‚£ãƒ¬ã‚¯ãƒ†ã‚£ãƒ–ã‚’è¿½åŠ ã—modulesディレクトリã«ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã‚‚コピーã—ãŸã„ã®ã§apxsコマンドを使用ã—ã¾ã™ã€‚
# apxs -i -a -c mod_orz.c
コマンド引数-iã§modulesã«ã‚³ãƒ”ーã€-aã§httpd.confã«LodModuleãƒ‡ã‚£ãƒ¬ã‚¯ãƒ†ã‚£ãƒ–è¿½åŠ ã€-cã§ã‚³ãƒ³ãƒ‘イルã§ã™ã€‚
一応ã€nmã§ç¢ºèªã—ã¾ã—ょã†ã€‚
# nm /usr/local/apache2/modules/mod_orz.so | grep orz 00000470 t orz_handler 000016a0 D orz_module 00000430 t orz_register_hooks
ã“ã“ã¾ã§æ¥ãŸã‚‰ã€ã‚ã¨ã¯httpd.confã«ä»¥ä¸‹ã®è¨å®šã‚’è¿½åŠ ã—ã¾ã™ã€‚
<Location "/orz/"> SetHandler orz </Location>
ã“れ㧠/orz/ ã®ãƒªã‚¯ã‚¨ã‚¹ãƒˆã«å¯¾ã—作æˆã—ãŸmod_orzモジュールãŒå‘¼ã³å‡ºã•ã‚Œã¾ã™ã€‚
apacheã‚’å†èµ·å‹•ã—ã€http://アパッãƒã®ã‚µãƒ¼ãƒ/orz/ ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã¨orzãŒ100回表示ã•ã‚Œã¦ã„ã‚‹ã®ãŒåˆ†ã‹ã‚‹ã¨æ€ã„ã¾ã™ã€‚
表示ã•ã‚Œã¦ã„ã¾ã™ãï¼
C言語もApacheモジュール作æˆã‚‚åˆã‚ã¦ã®äººã§ã‚‚5分足らãšã§ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ä½œæˆå‡ºæ¥ãŸã¨æ€ã„ã¾ã™ã€‚
Apacheモジュールã®ãƒ‡ãƒãƒƒã‚°æ–¹æ³•(stderr/ap_log_rerror/customlog/gdb)
Error Log
gdbã§ãƒ‡ãƒãƒƒã‚°ã™ã‚‹å‰ã«ã€ã¾ãšã¯fprintfを使ã£ã¦ãƒ‡ãƒãƒƒã‚°ã—ã¦ã¿ã¾ã™ã€‚
mod_orz.cã®foræ–‡ã®ä¸ã«ä»¥ä¸‹ã‚’è¿½åŠ ã—ループカウンタをデãƒãƒƒã‚°ã—ã¾ã™ã€‚
fprintf(stderr, "i=[%d]\n", i);
è¿½åŠ å¾Œã«apxs -i -a -c mod_orz.cを実行ã—ã€error_logã‚’tailã—ãªãŒã‚‰ãƒ‡ãƒãƒƒã‚°ã—ã¾ã™
å…ˆã»ã©ã®ãƒšãƒ¼ã‚¸ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã¨ã€error_logã«ãƒ«ãƒ¼ãƒ—カウンタãŒè¡¨ç¤ºã•ã‚Œã‚‹ã®ãŒåˆ†ã‹ã‚‹ã¨æ€ã„ã¾ã™ã€‚
※apacheã‚’-X付ãã®å†…部デãƒãƒƒã‚°ç”¨ã¨ã—ã¦ã‚·ãƒ³ã‚°ãƒ«ãƒ—ãƒã‚»ã‚¹ãƒ¢ãƒ¼ãƒ‰ï¼ˆåプãƒã‚»ã‚¹ã¯forkã—ãªã„)ã§å®Ÿè¡Œã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™
Apache API ap_log_rerror
httplog.hã«ã‚ã‚‹ã€Apache APIã®ap_log_rerrorを使ã„ã¾ã™ã€‚
#include "http_log.h" // ã•ã£ãã®ãƒ«ãƒ¼ãƒ—カウンタをap_log_rerrorã§å‡ºåŠ› ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r, "use ap_log_error:[%d]", i);
ap_log_rerrorを使ã†ã¨æ™‚間付ãã§error_logã«å‡ºåŠ›ã•ã‚Œã¾ã™ã€‚
[Mon May 11 23:10:02 2009] [crit] [client 192.168.56.101] use ap_log_error:[100]
第2引数を切り替ãˆã¦info, debguも出力出æ¥ã¾ã™ã€‚
APLOG_MARKマクãƒã¯ãƒ‡ãƒãƒƒã‚°ã—ãŸå ´åˆã«ãƒ•ã‚¡ã‚¤ãƒ«åã¨è¡Œæ•°ã‚‚出力ã•ã‚Œã¾ã™ã€‚
#define APLOG_MARK __FILE__,__LINE__
出力例
[Mon May 11 23:10:02 2009] [debug] mod_orz.c(61): [client 192.168.56.101] 111:[1]
Custom Log
Custom Logã¸ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã‹ã‚‰ãƒã‚°ã‚’出力ã™ã‚‹ã«ã¯ã€ãƒ¡ãƒ¢é ˜åŸŸã§ã‚ã‚‹request_rec->notes(リクエストコンテã‚ストã®ãƒŽãƒ¼ãƒˆï¼‰ã‚’使ã„ã¾ã™ã€‚
Apache API(apr_table_set/apr_table_get)ã«ã¯ã€å†…部ã«key=valueå½¢å¼ã§å€¤ã‚’ä¿æŒã—ã¦ãŠã‘ã‚‹ã®ã§å„フェーズã§å€¤ã‚’共有ã™ã‚‹ã“ã¨ã‚‚å¯èƒ½ã§ã™ã€‚
ã“ã®key=valueå½¢å¼ã®tableを使ã£ã¦ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã‹ã‚‰Custom Logã¸ãƒã‚°å‡ºåŠ›ã‚’è¡Œã„ã¾ã™ã€‚
- httpd.conf(httpd.confã®LogFormatã«ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã‹ã‚‰ã®ãƒ¡ãƒ¢ç”¨ãƒ•ã‚©ãƒ¼ãƒžãƒƒãƒˆã§ã‚ã‚‹%nã‚’è¨å®šï¼‰
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{MyMessage}n\"" common
- mod_orz.c(プãƒã‚°ãƒ©ãƒ ã‹ã‚‰ã¯ãƒŽãƒ¼ãƒˆ(r->notes)ã«ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’è¨å®šã—ã¾ã™ï¼‰
apr_table_set(r->notes, "MyMessage", "CustomeMessage!!!");
192.168.56.101 - - [11/May/2009:23:35:26 +0900] "GET /orz/ HTTP/1.1" 200 404 "CustomMessage"
ã“ã®ã€Hashé ˜åŸŸã‹ã‚‰ã¯ã€ã‚¨ãƒ©ãƒ¼æƒ…å ±ã‚‚å–得出æ¥ã¾ã™ã€‚
err_msg = apr_table_get(r->notes, "error-notes");
但ã—ã€ã“ã®tabelã‹ã‚‰å–å¾—ã—ãŸãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã¯ã‚¨ã‚¹ã‚±ãƒ¼ãƒ—ã•ã‚Œã¦ã„ãªã„ã®ã§ç›´æŽ¥HTMLã«å‡ºåŠ›ã™ã‚‹éš›ã¯ã‚¨ã‚¹ã‚±ãƒ¼ãƒ—処ç†ã‚’入れã¦ä¸‹ã•ã„。
gdbã§ãƒ‡ãƒãƒƒã‚°
デãƒãƒƒã‚°ã™ã‚‹éš›ã«ã€ãƒ–レークãƒã‚¤ãƒ³ãƒˆã‚’è¨å®šã—ãŸã„ã€ã‚¹ãƒ†ãƒƒãƒ—実行ã—ãŸã„ã¨ã„ã†æ–¹ã«ã¯gdbã§ã®ãƒ‡ãƒãƒƒã‚°ã‚’ãŠå‹§ã‚ã—ã¾ã™ã€‚
gdbã«é–¢ã—ã¦ã¯ã€ã“ã¡ã‚‰ãŒãŠå‹§ã‚ã§ã™ã€‚
- 作者: リãƒãƒ£ãƒ¼ãƒ‰ã‚¹ãƒˆãƒ¼ãƒ«ãƒžãƒ³,ãƒãƒ¼ãƒ©ãƒ³ãƒ‰ãƒšã‚·ãƒ¥,Richard M. Stallman,Roland H. Pesch,コスモプラãƒãƒƒãƒˆ
- 出版社/メーカー: アスã‚ー
- 発売日: 1999/01
- メディア: å˜è¡Œæœ¬
- 購入: 4人 クリック: 64回
- ã“ã®å•†å“ã‚’å«ã‚€ãƒ–ãƒã‚° (14件) を見る
gdbã‚’èµ·å‹•ã—ã¾ã™
# gdb /usr/local/apache2/bin/httpd
orz_handlerメソッドã«ãƒ–レイクãƒã‚¤ãƒ³ãƒˆã‚’仕掛ã‘ã¾ã™ï¼ˆbã¯breakã®alias)
(gdb) b orz_handler
引数-X付ãã§èµ·å‹•ï¼ˆrã¯runã®alias)
(gdb) r -X
ã“ã®çŠ¶æ…‹ã§ã€http://アパッãƒã‚µãƒ¼ãƒ/orz/ ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã¨ã€ãƒ–ラウザã¯å¿œç”å¾…ã¡ã§gdbã®ã‚³ãƒ³ã‚½ãƒ¼ãƒ«ã«å‡¦ç†ãŒæˆ»ã‚Šã¾ã™ã€‚
Breakpoint 1, orz_handler (r=0x9feb2d0) at mod_orz.c:49 49 if (strcmp(r->handler, "orz")) { (gdb)
ã“ã“ã§ã€ã‚¹ãƒ†ãƒƒãƒ—実行ã—ã¾ã™ï¼ˆnã¯nextã®alias)
(gdb) n 54 if (!r->header_only) { (gdb) n 52 r->content_type = "text/html"; (gdb) n 54 if (!r->header_only) {
ステップ実行ã—ã¦ã„ã‚‹ã®ãŒåˆ†ã‹ã‚‹ã¨æ€ã„ã¾ã™ã€‚ã©ã‚“ã©ã‚“実行ã—ã¦ãƒ«ãƒ¼ãƒ—ã«å…¥ã‚Šã¾ã™
(gdb) n 58 ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r, "use ap_log_error:[%d]", i);
ã“ã®æ™‚ã«ã€ãƒ«ãƒ¼ãƒ—カウンタを表示ã•ã›ã¦ã¿ã¾ã™ï¼ˆpã¯printã®alias)
(gdb) p i $1 = 1
(gdb) n 56 for (i = 0; i <= 100; i++) { (gdb) p i $4 = 4
ã•ã™ãŒã«100回もループã•ã›ã‚‹ã®ã‚‚ã—ã‚“ã©ã„ã®ã§ã€ãƒ«ãƒ¼ãƒ—を抜ã‘ã¾ã™ï¼ˆuã¯untilã®alias)
(gdb) n 56 for (i = 0; i <= 100; i++) { (gdb) u 60 apr_table_set(r->notes, "MyMessage", "CustomMessage");
ã“ã“ã§ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚³ãƒ³ãƒ†ã‚スト(request_rec)ã®ä¸èº«ã‚’見ã¦ã¿ã¾ã™ã€‚p *r ã¨æ‰“ã£ã¦ãã ã•ã„。
(gdb) p *r $5 = {pool = 0x8add298, connection = 0x8ad9458, server = 0x8a2f188, next = 0x0, prev = 0x0, main = 0x0, the_request = 0x8ade0b8 "GET /orz/ HTTP/1.1", assbackwards = 0, proxyreq = 0, header_only = 0, protocol = 0x8ade128 "HTTP/1.1", proto_num = 1001, hostname = 0x8ade4c0 "192.168.56.102", request_time = 1242663142199134, status_line = 0x0, status = 200, method = 0x8ade108 "GET", method_number = 0, allowed = 0, allowed_xmethods = 0x0, allowed_methods = 0x8add470, sent_bodyct = 0, bytes_sent = 0, mtime = 0, chunked = 0, range = 0x0, clength = 0, remaining = 0, read_length = 0, read_body = 0, read_chunked = 0, expecting_100 = 0, headers_in = 0x8add4a0, headers_out = 0x8add930, err_headers_out = 0x8addad8, subprocess_env = 0x8add6e8, notes = 0x8addc30, content_type = 0xf69654 "text/html", handler = 0x8aad910 "orz", content_encoding = 0x0, content_languages = 0x0, vlist_validator = 0x0, user = 0x0, ap_auth_type = 0x0, no_cache = 0, no_local_copy = 0, unparsed_uri = 0x8ade118 "/orz/", uri = 0x8ade120 "/orz/", filename = 0x8ade7f0 "/usr/local/apache2/htdocs/orz", canonical_filename = 0x8ade7f0 "/usr/local/apache2/htdocs/orz", path_info = 0x8ade78d "/", args = 0x0, finfo = {pool = 0x8add298, valid = 7598448, protection = 1877, filetype = APR_NOFILE, user = 0, group = 0, inode = 1579484, device = 64768, nlink = 2, size = 4096, csize = 623422955655647896, atime = 1242586928000000, mtime = 1228576600000000, ctime = 1242545432000000, fname = 0x8ade7f0 "/usr/local/apache2/htdocs/orz", name = 0x8aada00 "/usr/local/apache2/htdocs", filehand = 0x8ade125}, parsed_uri = {scheme = 0x0, hostinfo = 0x0, user = 0x0, password = 0x0, hostname = 0x0, port_str = 0x0, path = 0x8ade120 "/orz/", query = 0x0, fragment = 0x0, hostent = 0x0, port = 0, is_initialized = 1, dns_looked_up = 0, dns_resolved = 0}, used_path_info = 2, per_dir_config = 0x8adeca0, request_config = 0x8addd88, htaccess = 0x0, output_filters = 0x8ade038, input_filters = 0x8ade4d0, proto_output_filters = 0x8ade038, proto_input_filters = 0x8ade4d0, eos_sent = 0}
request_recã«ã¯ã€ã‹ãªã‚Šã®æƒ…å ±ãŒæ ¼ç´ã•ã‚Œã¦ã„ã¾ã™ã€‚apacheã®æ§‹é€ ã®ç†è§£ã‚’æ·±ã‚ã‚‹ã«ã¯gdbã§éƒ½åº¦ç¢ºèªã—ã¦ã¿ã‚‹ã¨è‰¯ã„ã§ã—ょã†ã€‚
見難ã„å ´åˆã«ã¯ã€ä»¥ä¸‹ã®è¨å®š(set print pretty on)ã§æ”¹è¡Œã•ã‚Œè¦‹ã‚„ã™ããªã‚Šã¾ã™ã€‚
(gdb) set print pretty on (gdb) p *r $6 = { pool = 0x8485298, connection = 0x8481458, server = 0x83d7188, next = 0x0, prev = 0x0, main = 0x0, the_request = 0x84860b8 "GET /orz/ HTTP/1.1", assbackwards = 0, proxyreq = 0, header_only = 0, protocol = 0x8486128 "HTTP/1.1", proto_num = 1001, hostname = 0x84864c0 "192.168.56.102", request_time = 1242663810469588, status_line = 0x0, status = 200, method = 0x8486108 "GET", method_number = 0, allowed = 0, allowed_xmethods = 0x0, allowed_methods = 0x8485470, sent_bodyct = 0, bytes_sent = 0, mtime = 0, chunked = 0, range = 0x0, clength = 0, remaining = 0, read_length = 0, read_body = 0, read_chunked = 0, expecting_100 = 0, headers_in = 0x84854a0, headers_out = 0x8485930, err_headers_out = 0x8485ad8, subprocess_env = 0x84856e8, notes = 0x8485c30, content_type = 0x0, handler = 0x8455910 "orz", content_encoding = 0x0, content_languages = 0x0, vlist_validator = 0x0, user = 0x0, ap_auth_type = 0x0, no_cache = 0, no_local_copy = 0, unparsed_uri = 0x8486118 "/orz/", uri = 0x8486120 "/orz/", filename = 0x84867f0 "/usr/local/apache2/htdocs/orz", canonical_filename = 0x84867f0 "/usr/local/apache2/htdocs/orz", path_info = 0x848678d "/", args = 0x0, finfo = { pool = 0x8485298, valid = 7598448, protection = 1877, filetype = APR_NOFILE, user = 0, group = 0, inode = 1579484, device = 64768, nlink = 2, size = 4096, csize = 594853245512864408, atime = 1242586928000000, mtime = 1228576600000000, ctime = 1242545432000000, fname = 0x84867f0 "/usr/local/apache2/htdocs/orz", name = 0x8455a00 "/usr/local/apache2/htdocs", filehand = 0x8486125 }, parsed_uri = { scheme = 0x0, hostinfo = 0x0, user = 0x0, password = 0x0, hostname = 0x0, port_str = 0x0, path = 0x8486120 "/orz/", query = 0x0, fragment = 0x0, hostent = 0x0, port = 0, is_initialized = 1, dns_looked_up = 0, dns_resolved = 0 }, used_path_info = 2, per_dir_config = 0x8486ca0, request_config = 0x8485d88, htaccess = 0x0, output_filters = 0x8486038, input_filters = 0x84864d0, proto_output_filters = 0x8486038, proto_input_filters = 0x84864d0, eos_sent = 0 }
最後ã«c(continue)ã—ã¦å‡¦ç†ã‚’終ã‚らã›ã‚‹ã¨ãƒ–ラウザã«orzãŒè¡¨ç¤ºã•ã‚Œã‚‹ã®ãŒåˆ†ã‹ã‚‹ã¨æ€ã„ã¾ã™ã€‚
(gdb) c Continuing.
gdbã¯ã€ã¨ã¦ã‚‚便利ãªãƒ‡ãƒãƒƒã‚¬ã§ã™ã®ã§è§¦ã£ã¦ã¿ã‚ˆã†ã‹ãªãã¨æ€ã£ã¦ã„ãŸäººã«ã¯ãŠå‹§ã‚ã§ã™ã€‚
çµè«–
Apache Moduleを作æˆã™ã‚Œã°ã€AAA(Access,Authentication,Authorization)Moduleã‚„Filter Moduleãªã©ã„ã‚ã„ã‚ãªç´°ã‹ã„制御を自作ã™ã‚‹äº‹ãŒå¯èƒ½ã§ã™ã€‚
C言語やã‚ã†ã‹ãªãã¨æ€ã£ã¦ã‚‹äººã¯ã€æ˜¯éžè§¦ã£ã¦ã¿ã¦ãã ã•ã„。mod_cache.cãªã©æ—¢å˜ã®ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã®ã‚½ãƒ¼ã‚¹ã‚’èªã‚€ã¨å‚考ã«ãªã‚Šã¾ã™ã€‚
皆ã•ã‚“ç´ æ•µãªmod_xxxを作ã£ã¦ä¸‹ã•ã„。
gdbを使ã£ãŸãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«é–‹ç™ºã‚’好ãã«ãªã‚‹ã©ã“ã‚ã‹ã€Eclipseã‚„NetBeansã€Visual StudioãŒã‚„ã£ã±ã‚Šå‡„ã„ã¨ã„ã†çµè«–ã«è‡³ã£ã¦ã—ã¾ã£ãŸã‚‰ã”ã‚ã‚“ãªã•ã„。