Cでサーバー監視のプログラムを作ってみよう その6

前回このシリーズは休憩しますと言いましたが、あれは嘘だ。 検証した作業でまだ書いてないことがあったのでたんたんと進めたいと思います・・・。

こないだ作ったプロセス監視のデーモンプログラムですが、system関数でシェルスクリプトを呼び出しているのがとってもとってもx2 気に要らないのだ。

だもんで、シェルスクリプトの部分をどうにかC言語でできないかと思っていろいろ試行錯誤したのだけど、無理だった orz

LoadAverageはgetloadavg() という関数があって簡単に監視はできそうなんだけど、肝心のプロセスの方がなかなかx2 見つからないのだ。

ないなら作ればいいじゃないという、いつものスタンスで行きたいところだけど、これはちょっと終わりなき旅になりそうで手がでない。カバンの中もつくえの中も探し回ってようやくkvm_getprocs(3)というのにたどり着いたんだけど、どうも違うようだ。言い換えれば使いこなせなかったという事だが。

 

前提として監視サーバーからの監視を考えていたので、セキュアにssh接続からリモートの情報を取り出すべく、まずはhttpクライアントを作った。

最初は自分で書いていて、後から参考サイトを見ながらやってみたので結構雑です。ほとんど同じ部分もあるけれど自分でやったところもあるので、いつもより理解度は深まったかなあ。

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
//      FILE *fp;
        int sockfd;
        int len;
        struct sockaddr_in address;
        int result;
        char send_buf[256];

        sockfd = socket(AF_INET, SOCK_STREAM, 0);

        address.sin_family = AF_INET;
        address.sin_addr.s_addr = inet_addr("192.168.24.61");
        address.sin_port = htons(80);
        len = sizeof(address);

        if((result = connect(sockfd, (struct sockaddr *)&address, len)) < 0)
                printf("connect errer\n");
        else{
                sprintf(send_buf, "GET / HTTP/1.1\r\n");
                write(sockfd, send_buf, strlen(send_buf));

                sprintf(send_buf, "Host: 192.168.24.61:80\r\n");
                write(sockfd, send_buf, strlen(send_buf));

                sprintf(send_buf, "\r\n");
                write(sockfd, send_buf, strlen(send_buf));
        }

        while(1){
                char buf[256];
                int read_html;

                read_html = read(sockfd, buf, 256);
                if(read_html > 0){
                        write(1, buf, read_html);
                }else{
                        break;
                }
        }


//      close(sockfd);

        return 0;
}

最後のcloseをコメントアウトしたのは、サーバー側からnetstatでセッションを見ていたら、プログラムが終わったらセッションがちゃんと切れてるので、消してみたままの状態になっています。

ちょっと話が逸れるけど、forkしてconnectするとestablishがガンガン増えていくね。だが今はその話は置いておこう。

実行結果

[takeken@localhost ~]% ./conn_1
HTTP/1.1 200 OK
Date: Sat, 26 Apr 2014 18:11:36 GMT
Server: Apache/2.2.15 (CentOS)
Last-Modified: Wed, 16 Apr 2014 21:43:43 GMT
ETag: "9fbbe-13-4f72fcf7a1767"
Accept-Ranges: bytes
Content-Length: 19
Vary: Accept-Encoding,User-Agent
Content-Type: text/html

<h1>It works!</h1>

サーバーのログは

[root@test2 ~]# cat /var/log/httpd/access_log | tail -1
192.168.24.180 - - [27/Apr/2014:03:11:36 +0900] "GET / HTTP/1.1" 200 19 "-" "-"

こんな感じでtelnetと同じですね。ですねというか、同じようにC言語で作ってるので当然ではある。

ふとconnectはセキュアじゃないなって思ったんだけど、connectはあくまでセッションにかかわるところで、セキュアな通信をするにはまたここから手を加えていく工程が必要なんだという事に気づくまでちょっと時間がかかった。

 

じゃあやっぱりsystem関数でsshを使ってデータを取るのがスマートじゃないかと思ったんだけど。

ソース 鍵は登録済ですよ。

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

int main(void)
{
        system("ssh takeken@192.168.24.61 sudo /bin/cat /var/log/secure");

        return 0;
}

これで試してみたら

[takeken@localhost ~]% ./data_1
sudo: sudo を実行するには tty がなければいけません。すみません

という事らしい。かといってSSHクライアントを作るスキルはまだない。やろうとはしたんだけど、まずPuttyを参考にしようとPuttyのソースをDLしてきて解凍したところで気を失ったようだ。

すいませんって、初めてサーバーに謝られた気がする。
もー、仕方ないなぁ。対象のサーバーに設置するタイプにするかどうか。

ただC言語の中でsystem関数でシェルスクリプトを使うくらいだったら、Perlで書きたい。
監視のところだけスクリプトを使うのはなんかずるい気がして仕方ない。
動けばよかろうなはずなのに、どうしたんだろう。

スマートフォンやiPhoneのアプリで監視ツールを考えていたんだが、描いていたものが色々と破綻してきた。
クラウドみたいにAPIがあればまた別なんだろうけど、うーん、難しいなあ。

C言語でのソケットのべんきょも続けるけど、パーラーたけけんも並行してやっていこうか。

なんて言いながら、JAVAもPerlも本は買っているのだ。うほほ。

 

Similar Posts:


Leave a Reply

Your email address will not be published. Required fields are marked *