読者です 読者をやめる 読者になる 読者になる

臥薪嘗胆

インフラエンジニアのあれこれ

mod_mruby install してみた

mod_mruby

なぜやるのか?

インフラエンジニアをやっていて、かゆいところに手が届かないことがたくさんあって
もどかしい思いをずっとしてきた。
でもいまは時代が変わったようで、自分でmoduleを作らなくても
チョイチョイっとかゆいところに手が届くそうだ
そうmrubyならね!
この流れ(あってる?)に乗り遅れるな!

で、matsumoto-r さん作の mod_mrubyを使ってみよう

親切にここに書かれていたので、この通りにする。

結果、test.rbが動くまではサクッとできる。 あとは何をしたいか。 ちょっとこれから考えてみよう。

以下やったログ

apacheいれとく

sudo yum install httpd.x86_64
sudo yum install httpd-devel.x86_64

mod_mrubyのsrcをもってくる

git clone git://github.com/matsumoto-r/mod_mruby.git

テストとビルド

cd mod_mruby
sh test.sh
sh build.sh

私はvagrant環境で試した 以下にビルド後の.soファイルができてた

ls -la /home/vagrant/mod_mruby/src/.libs/mod_mruby.so

これをコピってあげた。

cp /home/vagrant/mod_mruby/src/.libs/mod_mruby.so /usr/lib64/httpd/modules/
chown root: /usr/lib64/httpd/modules/mod_mruby.so

コンフもマニュアルのとおりに

[root@localhost mod_mruby]# cat /etc/httpd/conf.d/mruby.conf
LoadModule mruby_module modules/mod_mruby.so
<Location /mruby-test>
    mrubyHandlerMiddle /etc/httpd/conf.d/test.rb cache
</Location>

予め準備されているものを読み込むべくコピー

cp -p test/test.rb /etc/httpd/conf.d/
chown root: /etc/httpd/conf.d/test.rb

apacheを起動

systemctl status httpd.service
systemctl start httpd.service

curl してみた結果

[root@localhost mod_mruby]# curl http://127.0.0.1/mruby-test
# mod_mruby Test Page
__mod_mruby test start.__
## Apache Class Test
- Server: Apache
- Apache version: Apache/2.4.6 (CentOS)
- Apache build: Nov 19 2015 21:43:13
- module name: mod_mruby
- module version: 1.13.10
- syslogger function: OK
- errlogger function: OK
- OK status = 0
- DECLINED status = -1
- HTTP_OK status = 200
- HTTP_SERVICE_UNAVAILABLE status = 503
## Request Class Test
- filename = /var/www/html/mruby-test
- uri = /mruby-test
- ---- request_rec changed ----
- filename = /var/www/html/index.html
- uri = /index.html
r.document_root: /var/www/html
r.document_root: /tmp
## Server Class Test
- document_root = /var/www/html
- error_fname = logs/error_log
- hostname = localhost.localdomain
- timeout = 60000000
## Connection Class Test
- remote_ip 127.0.0.1
- local_ip 127.0.0.1
- keepalives = 0
##Notes Class Test
- memo = hello
## Env Class Test
- AUTHOR = matsumoto_r
- SERVER_SOFTWARE = Apache/2.4.6 (CentOS)
- env hash size = 25
- env key = UNIQUE_ID val = VsMsFszCek7oPhdkOOPzNAAAAAM
- env key = HTTP_USER_AGENT val = curl/7.29.0
- env key = HTTP_HOST val = 127.0.0.1
- env key = HTTP_ACCEPT val = */*
- env key = PATH val = /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
- env key = SERVER_SIGNATURE val =
- env key = SERVER_SOFTWARE val = A p a c h e
- env key = SERVER_NAME val = 127.0.0.1
- env key = SERVER_ADDR val = 127.0.0.1
- env key = SERVER_PORT val = 80
- env key = REMOTE_ADDR val = 127.0.0.1
- env key = DOCUMENT_ROOT val = /var/www/html
- env key = REQUEST_SCHEME val = http
- env key = CONTEXT_PREFIX val =
- env key = CONTEXT_DOCUMENT_ROOT val = /var/www/html
- env key = SERVER_ADMIN val = root@localhost
- env key = SCRIPT_FILENAME val = /var/www/html/index.html
- env key = REMOTE_PORT val = 57100
- env key = GATEWAY_INTERFACE val = CGI/1.1
- env key = SERVER_PROTOCOL val = HTTP/1.1
- env key = REQUEST_METHOD val = GET
- env key = QUERY_STRING val =
- env key = REQUEST_URI val = /mruby-test
- env key = SCRIPT_NAME val = /index.html
- env key = AUTHOR val = matsumoto_r
## Headers_in Class Test
- Accept-Encoding = nil
- Accept-Encoding = gzip
- headers_in hash size = 4
- headers_in key = User-Agent val = curl/7.29.0
- headers_in key = Host val = 127.0.0.1
- headers_in key = Accept val = */*
- headers_in key = Accept-Encoding val = gzip
## Headers_out Class Test
- headers_out hash size = 0
## Scoreboard Class Test
- child pid = 15737
- thread limit    = 1
- server limit    = 256
- cpu load        = 792739788800
- load avereage   = [0, 0.0099999997764826, 0.090000003576279]
- total kbyte     = 3
- total access    = 1
- restart time    = 1.4556306719778e+15
- idle worker     = 4
- busy worker     = 1
- uptime          = 710
- access counter  = -1
- scoreboard status hash size = 1
- scoreboard key = 127.0.0.1 val = SERVER_GRACEFUL
- scoreboard counter hash size = 11
- scoreboard key = SERVER_READY val = 4
- scoreboard key = SERVER_STARTING val = 0
- scoreboard key = SERVER_BUSY_READ val = 0
- scoreboard key = SERVER_BUSY_WRITE val = 1
- scoreboard key = SERVER_BUSY_KEEPALIVE val = 0
- scoreboard key = SERVER_BUSY_LOG val = 0
- scoreboard key = SERVER_BUSY_DNS val = 0
- scoreboard key = SERVER_CLOSING val = 0
- scoreboard key = SERVER_DEAD val = 251
- scoreboard key = SERVER_GRACEFUL val = 0
- scoreboard key = SERVER_IDLE_KILL val = 0
## Finfo Class Test
- permission = 1877
- filetype regular file = false
- user = 0
- group = 0
- device = 64768
- inode = 35205976
- nlink = 2
- size = 6
- csize = 0
- atime = 1.447969437e+15
- mtime = 1.447969437e+15
- ctime = 1.4556292035898e+15
__Test Complete. Wellcome to mod_mruby world!!__

Cやってみよう #6

C

前年の続き

だいぶ間が空いてしまった。
2016年、restartです。
続けるように。

mod_vhost_maxclients.c のソースを見ていきましょう。

174   for (i = 0; i < vhost_maxclients_server_limit; ++i) {
175     for (j = 0; j < vhost_maxclients_thread_limit; ++j) {
176       worker_score *ws_record = ap_get_scoreboard_worker(i, j);
177 #ifdef __APACHE24__
178       char *client_ip = r->connection->client_ip;
179 #else
180       char *client_ip = r->connection->remote_ip;
181 #endif
  • 174行目は vhost_maxclients_server_limit まで繰り返しの処理が開始
  • 175行目は vhost_maxclients_thread_limit まで繰り返しの処理が開始
    • 例えば両方のlimitの値が10の場合は、10*10=100回、繰り返すわけですね。
  • 176行目が肝のようだ。
    ap_get_scoreboard_worker この処理で、apacheが持つscoreboardから値を取って
    *ws_record に値を入れている。
    http://apache.org/server-status
    ↑のserver-statusをimageしとけばいいのだろうか。
  • 178,180行目は、接続元のIPを取得している。
183       switch (ws_record->status) {
184          case SERVER_BUSY_READ:
185          case SERVER_BUSY_WRITE:
186          case SERVER_BUSY_KEEPALIVE:
187          case SERVER_BUSY_LOG:
188          case SERVER_BUSY_DNS:
189          case SERVER_CLOSING:
190          case SERVER_GRACEFUL:
  • ws_record->status のstatusで分岐をおこない、以下の状態の時にカウントをしている
#define SERVER_BUSY_READ 3  /* Reading a client request */
#define SERVER_BUSY_WRITE 4 /* Processing a client request */
#define SERVER_BUSY_KEEPALIVE 5 /* Waiting for more requests via keepalive */
#define SERVER_BUSY_LOG 6   /* Logging the request */
#define SERVER_BUSY_DNS 7   /* Looking up a hostname */
#define SERVER_CLOSING 8    /* Closing the connection */
#define SERVER_GRACEFUL 9   /* server is gracefully finishing request */

ここからが本題なのです。

190       case SERVER_GRACEFUL:
191         /* check maxclients per vhost */
192         if (strcmp(vhostport, ws_record->vhost) == 0) {
193           vhost_count++;
194           ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, "DEBUG: (increment %s): %d/%d", vhostport,
195                        vhost_count, scfg->vhost_maxclients);
196           if (vhost_count > scfg->vhost_maxclients) {
197             if (scfg->dryrun > 0) {
198               ap_log_error(
199                   APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
200                   "NOTICE: [DRY-RUN] [VHOST_COUNT] return 503 from %s : %d / %d client_ip: %s uri: %s filename: %s",
201                   vhostport, vhost_count, scfg->vhost_maxclients, client_ip, r->uri, r->filename);
202             } else {
203               ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
204                            "NOTICE: [VHOST_COUNT] return 503 from %s : %d / %d client_ip: %s uri: %s filename: %s",
205                            vhostport, vhost_count, scfg->vhost_maxclients, client_ip, r->uri, r->filename);
206             }
207             return (scfg->dryrun > 0) ? DECLINED : HTTP_SERVICE_UNAVAILABLE;
208           }
209
210           /* check maxclients per ip in same vhost */
211           if (scfg->vhost_maxclients_per_ip > 0) {
212             if (strcmp(client_ip, ws_record->client) == 0) {
213               ip_count++;
214               if (ip_count > scfg->vhost_maxclients_per_ip) {
215                 if (scfg->dryrun > 0) {
216                   ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, "NOTICE: [DRY-RUN] [CLIENT_COUNT] return "
217                                                                             "503 from %s : %d / %d client_ip: %s uri: "
218                                                                             "%s filename: %s",
219                                vhostport, ip_count, scfg->vhost_maxclients_per_ip, client_ip, r->uri, r->filename);
220                 } else {
221                   ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
222                                "NOTICE: [CLIENT_COUNT] return 503 from %s : %d / %d client_ip: %s uri: %s filename: %s",
223                                vhostport, ip_count, scfg->vhost_maxclients_per_ip, client_ip, r->uri, r->filename);
224                 }
225                 return (scfg->dryrun > 0) ? DECLINED : HTTP_SERVICE_UNAVAILABLE;
226               }
227             }
228           }
229         }
230         break;
  • 192行目でリクエストの hoge.com:80 とscoreboardとが一致していれば vhost_count++ をインクリメント。
  • 196行目で設定されているlimit値を超えているかの判定を行っている。
    超えている場合、以下の処理を行う

    • 197行目でドライランかの判定を行い、それぞれでログを出力している
    • 207行目でドライランであれば DECLINED
      ドライランでなければ、 HTTP_SERVICE_UNAVAILABLE = 503 となる
  • 211行目移行は、同一のvhostに対して同じIPからのアクセスを制御する

こんな感じで、このモジュールは書かれていることが分かった。

一旦、おわりー

Cも時間を割けばわかるものなのですね。。 つぎは何しよう。

Cやってみよう #5

C

先日の続き

有識者とはタイミングが合わず、今回も独自の視点からみてみましょう!
その前に、apacheに由来する部分を抑えようと思い立ちました。

request_rec構造体というモノを軽く見てみましょう。
とおもってググったら素晴らしいサイトに出会いました
ここを見れば一発OK!
request_recはもう怖くない。
クライアントから送信された、リクエストの中身が見て取れますね!

ではこちら:mod_vhost_maxclients 続けましょう!

140 static int vhost_maxclients_handler(request_rec *r)
141 {
142   int i, j;
143   int vhost_count = 0;
144   int ip_count = 0;
145   char *vhostport;
146   vhost_maxclients_config *scfg =
147       (vhost_maxclients_config *)ap_get_module_config(r->server->module_config, &vhost_maxclients_module);
  • 140行目は関数の定義
  • 147行目はap_get_module_configで設定を読み込んでいる
    • 読み込んでるものは、ここ(334〜345行目)に定義されているものであろう(詳細不明)
334 #ifdef __APACHE24__
335 AP_DECLARE_MODULE(vhost_maxclients) = {
336 #else
337 module AP_MODULE_DECLARE_DATA vhost_maxclients_module = {
338 #endif
339     STANDARD20_MODULE_STUFF, NULL,         /* create per-dir config structures     */
340     NULL,                                  /* merge  per-dir    config structures  */
341     vhost_maxclients_create_server_config, /* create per-server config
342                                               structures  */
343     vhost_maxclients_create_server_merge_conf,                                  /* merge  per-server config structures  */
344     vhost_maxclients_cmds,                 /* table of config file commands        */
345     vhost_maxclients_register_hooks};

つぎー

149   if (!ap_is_initial_req(r)) {
150     return DECLINED;
151   }
152
153   if (scfg->vhost_maxclients <= 0) {
154     return DECLINED;
155   }
156
157   if (r->hostname == NULL) {
158     return DECLINED;
159   }
160
161   if (!ap_extended_status) {
162     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, "DEBUG: only used when ExtendedStatus On");
163     return DECLINED;
164   }
165
166   /* check ignore extesions */
167   if (check_extension(r->filename, scfg->ignore_extensions)) {
168     return DECLINED;
169   }
  • 149行目のap_is_initial_reqは以下の判定を行う
    • 最初のリクエストであれば、true
    • リダイレクトだったりした場合は、false
      ので、falseの場合は、DECLINED処理終了(mod_vhost_maxclientsの処理終了)となる
  • よってこの辺(149〜169行名)は、変数やリクエストの中身をチェックして、処理できない場合は処理終了としている。

つぎー

171   /* build vhostport name */
172   vhostport = build_vhostport_name(r);
  • 172行目は先週書いたbuild_vhostport_nameからhoge.com:80を取得してる

つぎー。
ここからがこのモジュールのメインの部分であろう。
が、長いので明日に!

Cやってみよう #4

C

先日の続き

おそろしい、C言語は恐ろしい。
たった10数行にも関わらず、頭に入ってこない。
俺の目と頭が連動しない...
慣れるしか無いのか!

112 static int check_extension(char *filename, apr_array_header_t *exts)
113 {
114   int i;
115   for (i = 0; i < exts->nelts; i++) {
116     const char *extension = ((char **)exts->elts)[i];
117     ssize_t name_len = strlen(filename) - strlen(extension);
118     if (name_len >= 0 && strcmp(&filename[name_len], extension) == 0)
119       return 1;
120   }
121   return 0;
122 }
  • 112行目で引数を2つもらう関数を定義してる。返り値はint
  • 115行目のexts->neltsは数値なのであろう。これは配列の要素数なんだろう。
  • 116行目のconst charは読み取り専用の文字列に配列の内容を入れているのだろう!
  • 116行目の(char **)これはなんだ?
    • Dereferencingとな
      • 変数のアドレスから値を取得する
  • 117行目のssize_tは、書き込まれたバイト数,エラー時は-1
  • 117行目はファイル名の文字数から配列の要素の文字数を引いて、name_lenにいれとる。
  • 118行目のstrcmpは文字列比較
  • 結果、この関数は0 or 1を返す

次々

124 static char *build_vhostport_name(request_rec *r)
125 {
126 #ifdef __APACHE24__
127   ssize_t vhostport_len;
128   char *vhostport;
129
130   vhostport_len = strlen(r->hostname) + sizeof(":65536");
131   vhostport = apr_pcalloc(r->pool, vhostport_len);
132   apr_snprintf(vhostport, vhostport_len, "%s:%d", r->hostname, r->connection->local_addr->port);
133
134   return vhostport;
135 #else
136   return (char *)r->hostname;
137 #endif
138 }
  • 124行目で引数を1つもらう関数を定義してる。返り値はchar
  • 124行目のrequest_recapacheの持ってる構造体をrというアドレスに定義?してる
  • #コメントアウトなの?
  • 130行目でvhostport_lenにこの場合はvirtualhostの長さと65536のメモリサイズを足した値を返してる
    • よくわからん
  • 131行目はapr_pcallocで初期化してる
  • 132行目はapr_snprintfぐぐってもわからん。
  • 結局この関数はhoge.com:80みたいなものを返してるのではないだろうか。

ちょっと憶測が多くなってきて、ぐぐっても分からないので有識者に聞こう。。。
聞いたら更新しますからね!

Cやってみよう #3

C

先日の続き

偉大な先輩が言ってた
「時間があったら人のソースを読んで勉強しろ」
ということで、最近話題のソースを読んで勉強します。

お題はこちら:mod_vhost_maxclients
一つのapache複数のバーチャルホストを運用している場合は有用なのではないでしょうか!

C言語、勉強中ですので間違ってるかも知れません。
その時はすみません。
ツッコミお願いします!

情報はググッて仕入れてみます。
まず git cloneしてみよう

git clone https://github.com/matsumoto-r/mod_vhost_maxclients.git

このような内容でした

-rw-r--r--   1 kyswtnb  staff    148 10 13 21:39 .clang-format
drwxr-xr-x  12 kyswtnb  staff    408 10 13 21:39 .git
-rw-r--r--   1 kyswtnb  staff    112 10 13 21:39 .gitignore
-rw-r--r--   1 kyswtnb  staff   6529 10 13 21:39 .travis.yml
-rw-r--r--   1 kyswtnb  staff    175 10 13 21:39 LEGAL
-rw-r--r--   1 kyswtnb  staff   1073 10 13 21:39 MITL
-rw-r--r--   1 kyswtnb  staff   1293 10 13 21:39 Makefile
-rw-r--r--   1 kyswtnb  staff   2224 10 13 21:39 README.md
-rw-r--r--   1 kyswtnb  staff  12179 10 13 21:39 mod_vhost_maxclients.c
drwxr-xr-x  13 kyswtnb  staff    442 10 13 21:39 test

cで書かれているソースは mod_vhost_maxclients.c これですね。
では読んでみましょう。

まず、apache関連のヘッダーファイルを取り込んでます。たぶん。

28 #include "httpd.h"
29 #include "http_config.h"
30 #include "http_request.h"
31 #include "http_protocol.h"
32 #include "http_core.h"
33 #include "http_log.h"
34
35 #include "ap_mpm.h"
36 #include "apr_strings.h"
37 #include "scoreboard.h"

これはわかるぞ!
モジュール名とバージョンですね。

39 #define MODULE_NAME "mod_vhost_maxclients"
40 #define MODULE_VERSION "0.3.2"

これは分からない。。

42 #if (AP_SERVER_MINORVERSION_NUMBER > 2)
43 #define __APACHE24__
44 #endif
  • httpd-2.4.16.tar.gzを落としてきて、grepしたら↓が書いてあった
#define AP_SERVER_MINORVERSION_NUMBER 4
  • #includeしたヘッダーファイルの値を判定してるんですね。
  • 調べてみればわかるもんだ。

↑で定義した__APACHE24__があったらさらに変数を定義

46 #ifdef __APACHE24__
47 #define ap_get_scoreboard_worker ap_get_scoreboard_worker_from_indexes
48 #endif

そんな感じで、定義するところが続きます

50 #define _log_debug                                                                                                     \
51   ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL, "DEBUG: " MODULE_NAME "/" MODULE_VERSION "%s:%d", __func__, __LINE__)
52
53 #ifdef __APACHE24__
54 #include "http_main.h"
55 #else
56 #define ap_server_conf NULL
57 #endif
58
59 #define VHOST_MAXEXTENSIONS 16
60
61 #if !defined(__APACHE24__) && defined(_WIN32)
62 /*
63  * libhttpd.dll does not export following variables.
64  * This won't work correctly, but working well for other functional.
65  */
66 int ap_extended_status = 0;
67 #endif

windows,unix互換のマクロ AP_MODULE_DECLARE_DATA を記述。たぶん。

 69 module AP_MODULE_DECLARE_DATA vhost_maxclients_module;

スタティックな変数を宣言。同時に2つ宣言できるんですね。

 70 static int vhost_maxclients_server_limit, vhost_maxclients_thread_limit;

構造体(変数の塊)を vhost_maxclients_config という名前で定義している

72 typedef struct {
73
74   /* vhost max clinetns */
75   int dryrun;
76   signed int vhost_maxclients;
77   signed int vhost_maxclients_per_ip;
78   apr_array_header_t *ignore_extensions;
79
80 } vhost_maxclients_config;

これがポインタ?
* apr_pool_t bufferの保存場所?
* server_rec apacheが持ってる構造体
* apr_pcalloc メモリ領域を確保 * apr_array_make 配列を作成

ここでは、設定を読み込み領域を定義しているのかな〜と憶測

82 static void *vhost_maxclients_create_server_config(apr_pool_t *p, server_rec *s)
83 {
84   vhost_maxclients_config *scfg = (vhost_maxclients_config *)apr_pcalloc(p, sizeof(*scfg));
85
86   scfg->dryrun = -1;
87   scfg->vhost_maxclients = 0;
88   scfg->vhost_maxclients_per_ip = 0;
89   scfg->ignore_extensions = apr_array_make(p, VHOST_MAXEXTENSIONS, sizeof(char *));
90
91   return scfg;
92 }

ここも↑と同じで設定を読み込む構造体を定義しているように見える

94 static void* vhost_maxclients_create_server_merge_conf(apr_pool_t* p, void* b, void* n)
95 {
96   vhost_maxclients_config *base = (vhost_maxclients_config *)b;
97   vhost_maxclients_config *new = (vhost_maxclients_config *)n;
98   vhost_maxclients_config *scfg = (vhost_maxclients_config *)apr_pcalloc(p, sizeof(*scfg));
99
100   if (new->dryrun > -1) {
101       scfg->dryrun = new->dryrun;
102   } else {
103       scfg->dryrun = base->dryrun;
104   }
105   scfg->vhost_maxclients = new->vhost_maxclients;
106   scfg->vhost_maxclients_per_ip = new->vhost_maxclients_per_ip;
107   scfg->ignore_extensions = new->ignore_extensions;
108
109   return scfg;
110 }

ちょっとここからは難しくなってきたので、仕切りなおしてまた次の日に・・・。
慣れだけなのだろうけど、ぱっとみて何やってるのか把握するのが難しい。
続けよう。

Cやってみよう #2

C

昨日の続き

引数をとって何かを出力する

何作る・・・?

  • 無駄なやつ作る
  • ググッてビビッときたのが、素数checker

ひとまず、引数をとって出力するだけのやつを作ってみる

  • 引数は何個でもOK
  • int count; が無いとコンパイルエラーになった。丁寧。
chk-prime.c: 関数 ‘main’ 内:
chk-prime.c:16:10: エラー: ‘count’ が宣言されていません (この関数内での最初の使用)
     for (count = 1; count < argc; count++){
          ^
chk-prime.c:16:10: 備考: 未宣言の識別子は出現した各関数内で一回のみ報告されます

ひとまず引数をprintするだけの動くもの。

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
    int count;

    for (count = 1; count < argc; count++){
        printf("argv[%d] = %s\n", count, argv[count]);
    }
}
  • argc ・・・ argcはargument countの略です。
  • printf を使って count を添字として配列から出力している

ふむふむ。
ここまではOK。

では引数が素数か否か判定するロジックを入れてみる

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
    int count;
    int divisor;
    int i;
    int x;

    for (count = 1; count < argc; count++){

        divisor = 0;              /* 約数のcount用 */
        x = atoi(argv[count]);    /* 引数を数値にキャストして変数に入れる */

        for (i = 1; i <= x; i++){ /* 引数(int:x)回分処理をする */
            if( x % i == 0 ){
                divisor++;        /* 割り切れた場合、約数をカウントアップ */
            }
        }

        if ( divisor == 2 ){      /* 1と引数自身で割り切れた場合、(2の時)素数 */
            printf("%s is prime\n", argv[count]);
            /*
        } else {
            printf("%s is not prime\n", argv[count]);
            */
        }
    }
}
gcc chk-prime.c -o chk-prime.o

できた

[vagrant@CentOS-71 ctest]$ for i in $(seq 1 100);do     ./chk-prime.o $i; done
2 is prime
3 is prime
5 is prime
7 is prime
11 is prime
13 is prime
17 is prime
19 is prime
23 is prime
29 is prime
31 is prime
37 is prime
41 is prime
43 is prime
47 is prime
53 is prime
59 is prime
61 is prime
67 is prime
71 is prime
73 is prime
79 is prime
83 is prime
89 is prime
97 is prime

よさそう

Cやってみよう #1

C

仕事でほんとに困ったときは

  • C言語わからないのに、C言語のソースを追う必要があるし
  • 何やってるかわからないpatchを充てたりする
  • 最近流行りのmrubyもC言語で書かれているらしいのだ!

だからチョットでもわかるようにC言語の気持ちに近づいてみよう。
といっても何にから手を付けたらよいかわからないので、hellow worldしてみよう

まずここ流し読み。
おっと、helloそのままあるやん。。

見なかったことにして、環境を作ろう

vagrant

vagrant box add CentOS_71 https://github.com/holms/vagrant-centos7-box/releases/download/7.1.1503.001/CentOS-7.1.1503-x86_64-netboot.box
vagrant init CentOS_71
vagrant up CentOS_71
vagrant ssh CentOS_71

環境

[vagrant@CentOS-71 ~]$ uname -a
Linux CentOS-71.local 3.10.0-229.el7.x86_64 #1 SMP Fri Mar 6 11:36:42 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

# gccもはいってた
[vagrant@CentOS-71 ~]$ rpm -qa | grep -w gcc-4.8.3-9.el7.x86_64
gcc-4.8.3-9.el7.x86_64

さっきのサンプルを

mkdir ctest
cd ctest/
cat << 'EOD' > hello.c
#include <stdio.h>

main()
{
    printf("hello, world¥n");
}
EOD
gcc hello.c && echo "OK" || "NG"

できた
実行権限付きだ

[vagrant@CentOS-71 ctest]$ ls -l
合計 16
-rwxrwxr-x 1 vagrant vagrant 8505 106 14:44 a.out
-rw-rw-r-- 1 vagrant vagrant   62 106 14:43 hello.c

実行してみた

[vagrant@CentOS-71 ctest]$ ./a.out
hello, world

ふむ。

明日は引数を取る何かを作ってみよう。