使用GAE Cron Job监测网站运行

偶的博客本身使用的是SiteUptime,但由于是免费账户最短间隔时间是30分钟,统计的数据会跟实际误差很大。正好GAE Cron Job可以用于定时任务,而且GAE可以使用GMAIL发送邮件,于是一个偶自制的山寨版监测系统就上线了,监测频率设置为每5分钟执行一次。
原理很简单,请求首页,如果返回200状态码就认为正常,其余则认为有故障,此时调用邮件发送模块发送邮件通知。这部分代码如下,完整代码不多,贴出也意义不大,请下载浏览。

1
2
3
4
5
6
7
8
9
10
class UptimeCheck(webapp.RequestHandler):
  def get(self):
    url = 'http://ioio.name/'
    result = urlfetch.fetch(url)
    if result.status_code == 200:
      #self.response.out.write(result.content)
      self.response.out.write('Site Online Now:%s'%time.ctime())
    else:
      SendNoticeMail(result.status_code)
      self.response.out.write('Site Offline Now:%s'%time.ctime())

下载 [下载没有找到]
这只是一个单用户版本,将需要监测的URL和邮件发送接收地址改成你自己的后上传至你的GAE即可使用。
-EOF-

我的编程知识体系搭建

看了很多东西,努力的想去尽可能的适应、适用,但不可能也没有那么多精力的去学习多的新的东西。
照目前所学的和工作上的需要,我将C/C++/Python/C#作为我的编程知识体系基本语言。

C/C++:虽然做C/C++开发的很多,但不管是过去现在还是将来,不管在Windows还是在Linux,它都是编程语言中的王者。

Python:快速原型语言,用于实现程序原型。

C#:到目前为止还没用过C#开发,它是我目前刚开始学的语言,但是在Windows上开发(作为Windows程序员),学会一门微软专有的语言也是必要的,何况它的许多高级特性对于开发Windows应用程序很便利。

这四种语言之外暂时不打算学习新的编程语言,并主要使用这四种编程语言完成几乎所有的工作。

同时也将Delphi(Pascal)/Visual Basic将我所使用的编程语言中划掉,前者我自始至终都没有学会,后者一身诟病。

开发程序的同时不使用数据库是必然的,计划使用MS Access/SQLite/MySQL/MS SQL Server作为日常开发数据库。

MS Access:虽然它也是一身诟病,但是当前的工作需要使用它,并且长期一段时间会使用的,因而它还是在我的数据库使用列表中。

SQLite:同样是桌面型数据库,小巧快捷,在以后我单独开发的小型项目或者数据库不是需要很强大的项目中我将使用它以代替MS Access。

MySQL:作为中小型解决方案不错的,这么受宠的数据库我怎么能不使用。

MS SQL Server:主要是与微软的产品结合使用,我还是认为微软的东西要与微软的东西搭配使用才能发挥得好(微软与其它产品总是有这样那样的不兼容,这主要也是为了少折腾)。
-EOF-

Code::Blocks添加Link文件

使用Code::Blocks编译一些代码的时候会出现”undefined reference to `****’”类似的错误,这主要是因为没有添加所需要的Link文件。添加方式如下:

  1. 添加全局作用模式Settings->Compiler and Debugger->Global Compiler Setting->Linker settings选择add找到所有的文件添加进来即可。
  2. 添加项目作用模式Project->Project build options->Linker settings选择add找到所有的文件添加进来即可。

-EOF-

Code::Blocks ConsoleRunner改进版

Code::Blocks是开源的,好处就在于可以随意的修改它,然后自己编译。Code::Blocks默认提供了一个 ConsoleRunner程序,在Windows平台下它可以提供程序的返回码与程序启动到运行结束的时间,很实用。貌似,仅仅是返回码和时间是不够的,偶给它来了个小小的修改,添加了几个小功能:

* 显示程序运行内存使用峰值
* 显示程序运行用户时间
* 显示程序运行内核时间
* 显示程序运行时间(用户时间与内核时间和)

这样改进后更方便更实用了,喜欢自己动手的童鞋可以继续修改添加自己喜欢的功能。
使用方法很简单,下载后直接替换Code::Blocks安装目录下的cb_console_runner.exe文件即可。

以下是源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*
 * This file is part of the Code::Blocks IDE and licensed under the GNU General Public License, version 3
 * http://www.gnu.org/licenses/gpl-3.0.html
 *
 * $Revision: 4909 $
 * $Id: main.cpp 4909 2008-02-27 13:15:26Z mortenmacfly $
 * $HeadURL: svn://svn.berlios.de/codeblocks/tags/8.02/src/tools/ConsoleRunner/main.cpp $
 *Modify by COCO<4341322@gmail.com>
 */
 
#include <stdio.h>
#include <stdlib.h>
#ifndef __WXMSW__
    #define __WXMSW__ 1
#endif
#ifdef __WXMSW__
    #include <windows.h>
    #include <psapi.h>
    #include <time.h>
	#include <conio.h>
	#define wait_key getch
#else
	#define wait_key getchar
#endif
#include <string.h>
 
#ifdef __MINGW32__
int _CRT_glob = 0;
#endif
 
bool hasSpaces(const char* str)
{
	char last = 0;
	while (str && *str)
	{
		if ((*str == ' ' || *str == '\t') && last != '\\')
            return true;
        last = *str++;
	}
	return false;
}
 
int main(int argc, char** argv)
{
	if (argc < 2)
    {
        printf("Usage: cb_console_runner <filename> <args ...>\n");
        return 1;
    }
 
    // count size of arguments
    int fullsize = 0;
    for (int i = 1; i < argc; ++i)
    {
        fullsize += strlen(argv[i]);
    }
    // add some slack for spaces between args plus quotes around executable
    fullsize += argc + 32;
 
    char* cmdline = new char[fullsize];
    memset(cmdline, 0, fullsize);
 
    // 1st arg (executable) enclosed in quotes to support filenames with spaces
    bool sp = hasSpaces(argv[1]);
    if (sp)
        strcat(cmdline, "\"");
    strcat(cmdline, argv[1]);
    if (sp)
        strcat(cmdline, "\"");
    strcat(cmdline, " ");
 
    for (i = 2; i < argc; ++i)
    {
        sp = hasSpaces(argv[i]);
        if (sp)
            strcat(cmdline, "\"");
        strcat(cmdline, argv[i]);
        if (sp)
            strcat(cmdline, "\"");
        strcat(cmdline, " ");
    }
 
    //printf("Would run '%s'\n", cmdline);
    #ifdef __WXMSW__
        //Windows's system() seems to not be able to handle parentheses in
        //the path, so we have to launch the program a different way.
 
        SetConsoleTitle(cmdline);
 
        STARTUPINFO si;
        PROCESS_INFORMATION pi;
 
        ZeroMemory( &si, sizeof(si) );
        si.cb = sizeof(si);
        ZeroMemory( &pi, sizeof(pi) );
 
        // Start the child process.
		clock_t cl = clock();
        CreateProcess( NULL, TEXT(cmdline), NULL, NULL, FALSE, 0,
                       NULL, NULL, &si, &pi );
 
        // Wait until child process exits.
        WaitForSingleObject( pi.hProcess, INFINITE );
 
        PROCESS_MEMORY_COUNTERS memInfo;
        GetProcessMemoryInfo(pi.hProcess,&memInfo,sizeof(memInfo));
        FILETIME ftCreate, ftExit, ftKernel, ftUser;
        GetProcessTimes(pi.hProcess, &ftCreate, &ftExit, &ftKernel, &ftUser);
        LONGLONG tUser64 = *(LONGLONG*) &ftUser;
        LONGLONG tKernel64 = *(LONGLONG*) &ftKernel;
        DWORD tUser, tKernel;
		tUser = (DWORD)(tUser64 / 10000);
        tKernel = (DWORD)(tKernel64 / 10000);
 
        cl = clock() - cl;
        cl *= 1000;
        cl /= CLOCKS_PER_SEC;
 
        // Get the return value of the child process
        DWORD ret;
        GetExitCodeProcess( pi.hProcess, &ret );
 
        // Close process and thread handles.
        CloseHandle( pi.hProcess );
        CloseHandle( pi.hThread );
 
        printf("\nProcess returned %ld (0x%lX)   execution time : %0.3f s", ret, ret, ((float)cl)/1000);
        printf("\nPeakWorkingSetSize : %d K ~ %d Mb",memInfo.PeakWorkingSetSize/1024,memInfo.PeakWorkingSetSize/1024/1024);
        printf("\nUser Time:%d ms ~ %0.3f S Kernel Time:%d ms ~ %0.3f S\nTotal Time:%d ms ~ %0.3f S",tUser,tUser/1000.0,tKernel,tKernel/1000.0,tUser+tKernel,(tUser+tKernel)/1000.0);
        printf("\nPress any key to continue.\n");
    #else
        int ret = system(cmdline);
        printf("\nPress ENTER to continue.\n");
    #endif
 
    wait_key();
 
    delete[] cmdline;
    return ret;
}

-EOF-

两款开源IDE

搞开发离不开好的IDE,搞C++开发更离不开。除了微软的VC外,Code::Blocks和Dev-C++也是不错的选择。而且Code::Blocks和Dev-C++都是开源的,偶尔无聊的时候,还可以捣鼓捣鼓它的源代码,自己编译。

我个人推荐使用Code::Blocks,因为它还是跨平台的,拥有Windows、Linux、Mac OS X三大主流操作系统版本,就算以后换平台,工具也不用换。Dev-C++采用Delphi开发,虽然说现在Delphi的开发人员还有很大一部分,但是随着Delphi的没落,Delphi是早该淘汰的了,而且Dev-C++自20040904出了4.9.9.2版以后再也没有更新过,估计更新的希望也就不大了,对于这么一款方便的IDE来说,也是一个遗憾。
更遗憾的一点是这两款IDE集成的GCC版本较老(Code::Blocks使用GCC3.4.5,Dev-C++使用GCC3.4.2),不过喜欢自己动手的同学可以自己下载最新的GCC替换之。
好了,萝卜白菜各取所爱吧。
Code::Blocks
Dev-C++
-EOF-