lighttpd與fastcgi+cgilua原理、代碼分析與安裝


 

原理

http://www.cnblogs.com/skynet/p/4173450.html

快速通用網關接口(Fast Common Gateway Interface/FastCGI)是通用網關接口(CGI)的改進,描述了客戶端和服務器程序之間傳輸數據的一種標准。FastCGI致力於減少Web服務器CGI程式之間互動的開銷,從而使服務器可以同時處理更多的Web請求。與為每個請求創建一個新的進程不同,FastCGI使用持續的進程來處理一連串的請求。這些進程由FastCGI進程管理器管理,而不是web服務器。(http://www.dwz.cn/yFMap)

clip_image004

當進來一個請求時,Web 服務器把環境變量和這個頁面請求通過一個unix domain socket(都位於同一物理服務器)或者一個IP Socket(FastCGI部署在其它物理服務器)傳遞給FastCGI進程。

clip_image006

 

l step1. Web 服務器啟動時載入初始化FastCGI執行環境 。 例如IIS ISAPI、apache mod_fastcgi、nginx ngx_http_fastcgi_module、lighttpd mod_fastcgi

 

l step2. FastCGI進程管理器自身初始化,啟動多個CGI解釋器進程並等待來自Web 服務器的連接。啟動FastCGI進程時,可以配置以ip和UNIX 域socket兩種方式啟動。

 

l step3. 當客戶端請求到達Web 服務器時, Web 服務器將請求采用socket方式轉發到 FastCGI主進程,FastCGI主進程選擇並連接到一個CGI解釋器。Web 服務器將CGI環境變量和標准輸入發送到FastCGI子進程。

 

l step4. FastCGI子進程完成處理后將標准輸出和錯誤信息從同一socket連接返回Web 服務器。當FastCGI子進程關閉連接時,請求便處理完成。

 

l step5. FastCGI子進程接着等待並處理來自Web 服務器的下一個連接。

由於 FastCGI 程序並不需要不斷的產生新進程,可以大大降低服務器的壓力並且產生較高的應用效率。它的速度效率最少要比CGI 技術提高 5 倍以上。它還支持分布式的部署, 即 FastCGI 程序可以在web 服務器以外的主機上執行。

 

總結:CGI 就是所謂的短生存期應用程序,FastCGI 就是所謂的長生存期應用程序。FastCGI像是一個常駐(long-live)型的CGI,它可以一直執行着,不會每次都要花費時間去fork一次(這是CGI最為人詬病的fork-and-execute 模式)。

 

代碼分析

1、 lighttpd 啟動過程, 生成fastcgi程序管理器:

對應文件為 mod_fastcgi.c

spawn 模塊, 維護可 生成的 fastcgi程序的個數, 進行循環生產(spawn)!

static int fcgi_restart_dead_procs(server *srv, plugin_data *p, fcgi_extension_host *host) {

fcgi_proc *proc;

for (proc = host->first; proc; proc = proc->next) {
    int status;

 

…..

if (fcgi_spawn_connection(srv, p, host, proc)) {
    log_error_write(srv, __FILE__, __LINE__, "s",
            "ERROR: spawning fcgi failed.");
    return HANDLER_ERROR;
}

 

……

}

 

每一個fastcgi程序生產過程:

fcgi_spawn_connection

static int fcgi_spawn_connection(server *srv,
                 plugin_data *p,
                 fcgi_extension_host *host,
                 fcgi_proc *proc) {

 

 


 

 

在此函數中:

創建lighttpd主程序監聽socket:


if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {
    /* server is not up, spawn it  */
    pid_t child;
    int val;

    if (errno != ENOENT &&
        !buffer_string_is_empty(proc->unixsocket)) {
        unlink(proc->unixsocket->ptr);
    }

    close(fcgi_fd);

    /* reopen socket */
    if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
        log_error_write(srv, __FILE__, __LINE__, "ss",
            "socket failed:", strerror(errno));
        return -1;
    }

    val = 1;
    if (setsockopt(fcgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
        log_error_write(srv, __FILE__, __LINE__, "ss",
                "socketsockopt failed:", strerror(errno));
        close(fcgi_fd);
        return -1;
    }

    /* create socket */
    if (-1 == bind(fcgi_fd, fcgi_addr, servlen)) {
        log_error_write(srv, __FILE__, __LINE__, "sbs",
            "bind failed for:",
            proc->connection_name,
            strerror(errno));
        close(fcgi_fd);
        return -1;
    }

    if (-1 == listen(fcgi_fd, 1024)) {
        log_error_write(srv, __FILE__, __LINE__, "ss",
            "listen failed:", strerror(errno));
        close(fcgi_fd);
        return -1;
    }

 

fork出fastcgi子進程:

#ifdef HAVE_FORK
        switch ((child = fork())) {
        case 0: {
            size_t i = 0;
            char *c;
            char_array env;
            char_array arg;

            /* create environment */
            env.ptr = NULL;
            env.size = 0;
            env.used = 0;

            arg.ptr = NULL;
            arg.size = 0;
            arg.used = 0;

          //  將主程序的生成的  通信socket  fcgi_fd , 作為fastcgi程序的 標准輸入

            if(fcgi_fd != FCGI_LISTENSOCK_FILENO) {
                close(FCGI_LISTENSOCK_FILENO);
                dup2(fcgi_fd, FCGI_LISTENSOCK_FILENO);
                close(fcgi_fd);
            }

            /* we don't need the client socket */
            for (i = 3; i < 256; i++) {
                close(i);
            }

            /* build clean environment */
            if (host->bin_env_copy->used) {
                for (i = 0; i < host->bin_env_copy->used; i++) {
                    data_string *ds = (data_string *)host->bin_env_copy->data[i];
                    char *ge;

                    if (NULL != (ge = getenv(ds->value->ptr))) {
                        env_add(&env, CONST_BUF_LEN(ds->value), ge, strlen(ge));
                    }
                }
            } else {
                for (i = 0; environ[i]; i++) {
                    char *eq;

                    if (NULL != (eq = strchr(environ[i], '='))) {
                        env_add(&env, environ[i], eq - environ[i], eq+1, strlen(eq+1));
                    }
                }
            }

          //  將主程序的生成的 環境 傳入到 fastcgi中。

            /* create environment */
            for (i = 0; i < host->bin_env->used; i++) {
                data_string *ds = (data_string *)host->bin_env->data[i];

                env_add(&env, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
            }

            for (i = 0; i < env.used; i++) {
                /* search for PHP_FCGI_CHILDREN */
                if (0 == strncmp(env.ptr[i], "PHP_FCGI_CHILDREN=", sizeof("PHP_FCGI_CHILDREN=") - 1)) break;
            }

            /* not found, add a default */
            if (i == env.used) {
                env_add(&env, CONST_STR_LEN("PHP_FCGI_CHILDREN"), CONST_STR_LEN("1"));
            }

            env.ptr[env.used] = NULL;

            // 對應lighttpd配置中,設置的cgilua.fcgi腳本對應的路徑

            parse_binpath(&arg, host->bin_path);

            /* chdir into the base of the bin-path,
             * search for the last / */
            if (NULL != (c = strrchr(arg.ptr[0], '/'))) {
                *c = '\0';

                /* change to the physical directory */
                if (-1 == chdir(arg.ptr[0])) {
                    *c = '/';
                    log_error_write(srv, __FILE__, __LINE__, "sss", "chdir failed:", strerror(errno), arg.ptr[0]);
                }
                *c = '/';
            }

            reset_signals();

          //  啟動fastcgi程序

            /* exec the cgi */
            execve(arg.ptr[0], arg.ptr, env.ptr);

            /* log_error_write(srv, __FILE__, __LINE__, "sbs",
                    "execve failed for:", host->bin_path, strerror(errno)); */

            exit(errno);

            break;
        }
        case -1:
            /* error */
            break;
        default:
            /* father */

            /* wait */
            select(0, NULL, NULL, NULL, &tv);

            switch (waitpid(child, &status, WNOHANG)) {
            case 0:
                /* child still running after timeout, good */
                break;
            case -1:
                /* no PID found ? should never happen */
                log_error_write(srv, __FILE__, __LINE__, "ss",
                        "pid not found:", strerror(errno));
                return -1;
            default:
                log_error_write(srv, __FILE__, __LINE__, "sbs",
                        "the fastcgi-backend", host->bin_path, "failed to start:");
                /* the child should not terminate at all */
                if (WIFEXITED(status)) {
                    log_error_write(srv, __FILE__, __LINE__, "sdb",
                            "child exited with status",
                            WEXITSTATUS(status), host->bin_path);
                    log_error_write(srv, __FILE__, __LINE__, "s",
                            "If you're trying to run your app as a FastCGI backend, make sure you're using the FastCGI-enabled version.\n"
                            "If this is PHP on Gentoo, add 'fastcgi' to the USE flags.");
                } else if (WIFSIGNALED(status)) {
                    log_error_write(srv, __FILE__, __LINE__, "sd",
                            "terminated by signal:",
                            WTERMSIG(status));

                    if (WTERMSIG(status) == 11) {
                        log_error_write(srv, __FILE__, __LINE__, "s",
                                "to be exact: it segfaulted, crashed, died, ... you get the idea." );
                        log_error_write(srv, __FILE__, __LINE__, "s",
                                "If this is PHP, try removing the bytecode caches for now and try again.");
                    }
                } else {
                    log_error_write(srv, __FILE__, __LINE__, "sd",
                            "child died somehow:",
                            status);
                }
                return -1;
            }

            /* register process */
            proc->pid = child;
            proc->is_local = 1;

            break;
        }
#endif
    } else {

 

生成程序運行結構(以nginx圖借用):

分別對應靜態代碼的三個部分:

1、 lighttpd部分  對應 Nginx框

2、 mod_fastcgi 對應 socket和 fastcgi wrapper部分,  在主程序中負責 各個fastcgi程序管理。

3、 application 對應 fastcgi程序,對應 多個lua XXX進程。

Image result for fastcgi

 

當連接到來后, mod_fastcgi通過此函數處理連接,

static handler_t fcgi_handle_fdevent(server *srv, void *ctx, int revents) {

---》

mod_fastcgi_handle_subrequest

---》分配cgi子進程

* as soon as hctx->host is unassigned, decrease the load again */
fcgi_host_assign(srv, hctx, host);

 

---》 向cgi進程中寫數據

static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) {

 

---》 創建cgi環境

if (-1 == fcgi_create_env(srv, hctx, hctx->request_id)) return HANDLER_ERROR;

fcgi_set_state(srv, hctx, FCGI_STATE_WRITE);

---》添加環境

FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf)),con)

s = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s)),con)

 

環境傳遞?

主程序, 即fastcgi wrapper如何將 非啟動的環境變量 , 傳遞為 cgi程序?

 

注意到, cgi程序啟動時候, 第三個參數, 是環境變量指針:

/* exec the cgi */
execve(arg.ptr[0], arg.ptr, env.ptr);

 

此env為fork后生成的局部變量:

#ifdef HAVE_FORK
        switch ((child = fork())) {
        case 0: {
            size_t i = 0;
            char *c;
            char_array env;
            char_array arg;

            /* create environment */
            env.ptr = NULL;
            env.size = 0;
            env.used = 0;

            arg.ptr = NULL;
            arg.size = 0;
            arg.used = 0;

然后

只有繼承當前 進程環境的 操作:

/* build clean environment */
if (host->bin_env_copy->used) {
    for (i = 0; i < host->bin_env_copy->used; i++) {
        data_string *ds = (data_string *)host->bin_env_copy->data[i];
        char *ge;

        if (NULL != (ge = getenv(ds->value->ptr))) {
            env_add(&env, CONST_BUF_LEN(ds->value), ge, strlen(ge));
        }
    }
} else {
    for (i = 0; environ[i]; i++) {
        char *eq;

        if (NULL != (eq = strchr(environ[i], '='))) {
            env_add(&env, environ[i], eq - environ[i], eq+1, strlen(eq+1));
        }
    }
}

/* create environment */
for (i = 0; i < host->bin_env->used; i++) {
    data_string *ds = (data_string *)host->bin_env->data[i];

    env_add(&env, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
}

for (i = 0; i < env.used; i++) {
    /* search for PHP_FCGI_CHILDREN */
    if (0 == strncmp(env.ptr[i], "PHP_FCGI_CHILDREN=", sizeof("PHP_FCGI_CHILDREN=") - 1)) break;
}

/* not found, add a default */
if (i == env.used) {
    env_add(&env, CONST_STR_LEN("PHP_FCGI_CHILDREN"), CONST_STR_LEN("1"));
}

env.ptr[env.used] = NULL;

 

那么環境變量是怎么傳入子進程fastcgi中的呢?

我們注意到 fork之后, 父進程會記錄子進程的id:


    /* register process */
    proc->pid = child;
    proc->is_local = 1;

    break;
}

??? 確實是是個問題!!

 

 

在子程序中,如何獲取環境變量?

答案: environ 全局變量

http://linux.chinaunix.net/techdoc/develop/2007/09/19/968230.shtml

1. get all
進程的環境是一個以NULL字符結尾的字符串之集合。如:
name=something
Linux系統提供了environ指針來訪問其變量內容。
如下程序showenv.c演示了通過environ指針變量訪問環境變量:
extern char** environ;
main()
{
        char** env=environ;
        while(*env)
        {
                printf("%s\n",*env++);
        }
        return;
}
2. add
為進程指定新的環境,需:execle()和execve()  [in ]
如下程序addenv.c 演示了把新的環境傳給上面的showenv.c:
#include
main()
{
        char *argv[]={"showenv.x",NULL},
             *envp[]={"nick=home","home=nick",NULL};
        execve("../exe/showenv.x",argv,envp);
        perror("exeve failed");
        return;
}
結果:
nick=home
home=nick
其實,Linux系統庫stdlib.h提供了putenv(),它完成與addenv同樣的工作。方法為:putenv("newvariable=value");如成功返回0。它只改變調用進程的環境變量,父進程不變。

 

例如  lua的 wsapi.lua的  lfcgi.c的 fastcgi接口的  lua擴展, 也是通過 此方法實現。

 

image

 

 

lighttpd模塊化設計(擴展性設計)

 

此服務器有很多模塊, 都是可以主動注冊的, 根據 lighttpd.conf配置文件, 可以實現 模塊動態庫的 加載:

root@fqs:/usr/local/lighttpd/lib#
root@fqs:/usr/local/lighttpd/lib# ls
mod_access.la     mod_cml.la         mod_expire.la         mod_magnet.la       mod_rrdtool.la       mod_ssi.la            mod_usertrack.la
mod_accesslog.la  mod_cml.so         mod_expire.so         mod_magnet.so       mod_rrdtool.so       mod_ssi.so            mod_usertrack.so
mod_accesslog.so  mod_compress.la    mod_extforward.la     mod_mysql_vhost.la  mod_scgi.la          mod_staticfile.la     mod_webdav.la
mod_access.so     mod_compress.so    mod_extforward.so     mod_mysql_vhost.so  mod_scgi.so          mod_staticfile.so     mod_webdav.so
mod_alias.la      mod_dirlisting.la  mod_fastcgi.la        mod_proxy.la        mod_secdownload.la   mod_status.la
mod_alias.so      mod_dirlisting.so  mod_fastcgi.so        mod_proxy.so        mod_secdownload.so   mod_status.so
mod_auth.la       mod_evasive.la     mod_flv_streaming.la  mod_redirect.la     mod_setenv.la        mod_trigger_b4_dl.la
mod_auth.so       mod_evasive.so     mod_flv_streaming.so  mod_redirect.so     mod_setenv.so        mod_trigger_b4_dl.so
mod_cgi.la        mod_evhost.la      mod_indexfile.la      mod_rewrite.la      mod_simple_vhost.la  mod_userdir.la
mod_cgi.so        mod_evhost.so      mod_indexfile.so      mod_rewrite.so      mod_simple_vhost.so  mod_userdir.so
root@fqs:/usr/local/lighttpd/lib#
root@fqs:/usr/local/lighttpd/lib#

 

mod_fastcgi.c中此模塊對外開放的接口為 模塊注冊函數:

其他定義的函數, 均為 static聲明, 在外部不能直接引用,  只有在此函數中 注冊到 定義好的 插件結構體中, 才有暴漏的資格。

int mod_fastcgi_plugin_init(plugin *p);
int mod_fastcgi_plugin_init(plugin *p) {
    p->version      = LIGHTTPD_VERSION_ID;
    p->name         = buffer_init_string("fastcgi");

    p->init         = mod_fastcgi_init;
    p->cleanup      = mod_fastcgi_free;
    p->set_defaults = mod_fastcgi_set_defaults;
    p->connection_reset        = fcgi_connection_reset;
    p->handle_connection_close = fcgi_connection_close_callback;
    p->handle_uri_clean        = fcgi_check_extension_1;
    p->handle_subrequest_start = fcgi_check_extension_2;
    p->handle_subrequest       = mod_fastcgi_handle_subrequest;
    p->handle_joblist          = mod_fastcgi_handle_joblist;
    p->handle_trigger          = mod_fastcgi_handle_trigger;

    p->data         = NULL;

    return 0;
}

 

配置文件中, 可以定制加載那些模塊! 我們放開了fastcgi


## modules to load
# at least mod_access and mod_accesslog should be loaded
# all other module should only be loaded if really neccesary
# - saves some time
# - saves memory
server.modules              = (
#                               "mod_rewrite",
#                               "mod_redirect",
#                               "mod_alias",
                                "mod_access",
#                               "mod_cml",
#                               "mod_trigger_b4_dl",
#                               "mod_auth",
#                               "mod_status",
#                               "mod_setenv",
                                "mod_fastcgi",
#                               "mod_proxy",
#                               "mod_simple_vhost",
#                               "mod_evhost",
#                               "mod_userdir",
#                               "mod_cgi",
#                               "mod_compress",
#                               "mod_ssi",
#                               "mod_usertrack",
#                               "mod_expire",
#                               "mod_secdownload",
#                               "mod_rrdtool",
                                "mod_accesslog" )

 

那么, lighttpd是怎么實現 模塊注冊的呢?

要看插件模塊是怎么實現的? 插件模塊相當於模塊的基礎, 是一個基礎設施, 基礎模塊, 底層模塊, 可以類比為自然科學中的基礎科學,  計算機科學與技術, 與數學的關系。  按照面向對象設計中 DIP原則(依賴倒置原則), 則應該是高層模塊, 即抽象模塊, 底層模塊依賴高層模塊, 具體模塊依賴抽象模塊, 反過來則不為好的設計, 即如果 高層模塊(抽象模塊)中含有 低層模塊(具體模塊), 例如  plugin模塊含有 fastcgi模塊的信息!

 

高層模塊定義接口, 對應的是  plugin 數據結構!

低層模塊, 實現plugin這個數據結構。例如 fastcgi實現了這個插件接口規范。

 

扯遠了, 那個plugin模塊怎么實現模塊的動態加載的呢?

開頭是 插件加載接口

int plugins_load(server *srv) {


實現是: 對於配置中聲明的 模塊, 進行遍歷, 記住模塊名為 module


for (i = 0; i < srv->srvconf.modules->used; i++) {
    data_string *d = (data_string *)srv->srvconf.modules->data[i];
    char *module = d->value->ptr;

 

構造需要加載模塊的全路徑: xxx/mod_fastcgi.so


        buffer_copy_buffer(srv->tmp_buf, srv->srvconf.modules_dir);

        buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN("/"));
        buffer_append_string(srv->tmp_buf, module);
#if defined(__WIN32) || defined(__CYGWIN__)
        buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN(".dll"));
#else
        buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN(".so"));
#endif

 

使用dlopen接口動態加載so文件:

if (NULL == (p->lib = dlopen(srv->tmp_buf->ptr, RTLD_NOW|RTLD_GLOBAL))) {
    log_error_write(srv, __FILE__, __LINE__, "sbs", "dlopen() failed for:",
        srv->tmp_buf, dlerror());

    plugin_free(p);

    return -1;
}

 

構造需要執行的 mod_init函數:  mod_fastcgi_plugin_init

buffer_reset(srv->tmp_buf);
buffer_copy_string(srv->tmp_buf, module);
buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN("_plugin_init"));

 

找到初始化函數指針:

#if 1
        init = (int (*)(plugin *))(intptr_t)dlsym(p->lib, srv->tmp_buf->ptr);
#else
        *(void **)(&init) = dlsym(p->lib, srv->tmp_buf->ptr);
#endif

 

調用初始化函數:

if ((*init)(p)) {
    log_error_write(srv, __FILE__, __LINE__, "ss", module, "plugin init failed" );

    plugin_free(p);
    return -1;
}

 

加載完畢的模塊注冊到插件管理系統中:

        plugins_register(srv, p);

 

static int plugins_register(server *srv, plugin *p) {
    plugin **ps;
    if (0 == srv->plugins.size) {
        srv->plugins.size = 4;
        srv->plugins.ptr  = malloc(srv->plugins.size * sizeof(*ps));
        srv->plugins.used = 0;
    } else if (srv->plugins.used == srv->plugins.size) {
        srv->plugins.size += 4;
        srv->plugins.ptr   = realloc(srv->plugins.ptr, srv->plugins.size * sizeof(*ps));
    }

    ps = srv->plugins.ptr;
    ps[srv->plugins.used++] = p;

    return 0;
}

 

安裝

lighttpd安裝

http://www.lighttpd.net/

http://redmine.lighttpd.net/projects/lighttpd/wiki

 

1、 先執行

./configure --prefix=/usr/local/lighttpd

 

缺少pcre庫處理方法:

http://stackoverflow.com/questions/2263404/what-package-i-should-install-for-pcre-devel

apt-cache search pcre | grep -- -dev
apt-get install libpcre3-dev
 
遇到缺少zlib庫的情況:
configure: error: zlib-headers and/or libs where not found, install them or build with --without-zlib
 apt-cache search zlib | grep -- -dev
apt-get install  zlib1g-dev
 
遇到bzip2庫缺少情況:
configure: error: bzip2-headers and/or libs where not found, install them or build with --without-bzip2
apt-get install libbz2-dev
 
 

2、 編譯安裝

make

make install

 

安裝wsapi

help報錯:

root@fqs:/home/share/wsapi-master/wsapi-master# ./configure --help
./configure: 3: [: --help: unexpected operator
Trying to find where you installed Lua...
Illegal option --
./configure: 22: [: .: unexpected operator
Lua not found, please install Lua 5.1 (and put in your PATH)
root@fqs:/home/share/wsapi-master/wsapi-master#

 

查看confiure為 需要指定lua路徑名

root@fqs:/home/share/wsapi-master/wsapi-master# cat configure
#!/bin/sh

if [ $1 == "--help" ]; then
  echo "Usage: configure lua51"
  echo "where lua51 is the name of your Lua executable"
  exit 0
fi

echo "Trying to find where you installed Lua..."

if [ $1 != "" ]; then
  lua=$1
else
  lua="lua51"
fi

lua_bin=`which $lua`
lua_bin_dir=`dirname $lua_bin`

lua_root=`dirname $lua_bin_dir`

if [ $lua_root != "" ]; then
  echo "Lua is in $lua_root"
  echo "Writing config"
  lua_share=$lua_root/share/lua/5.1
  lua_lib=$lua_root/lib/lua/5.1
  bin_dir=$lua_root/bin
  echo "LIB_OPTION= -shared -fPIC" > config
  echo "LUA_DIR= $lua_share" >> config
  echo "BIN_DIR= $bin_dir" >> config
  echo "LUA_LIBDIR= $lua_lib" >> config
  echo "Now run 'make && sudo make install'"
else
  echo "Lua not found, please install Lua 5.1 (and put in your PATH)"
fi

root@fqs:/home/share/wsapi-master/wsapi-master#

 

然后,添加本機的lua名稱后,提示可以make

root@fqs:/home/share/wsapi-master/wsapi-master# ./configure lua5.1
./configure: 3: [: lua5.1: unexpected operator
Trying to find where you installed Lua...
Lua is in /usr
Writing config
Now run 'make && sudo make install'

 

make后有報錯:

root@fqs:/home/share/wsapi-master/wsapi-master# make
cc   -shared -fPIC -o src/fastcgi/lfcgi.so src/fastcgi/lfcgi.c -lfcgi
src/fastcgi/lfcgi.c:8:24: fatal error: fcgi_stdio.h: No such file or directory
compilation terminated.
Makefile:23: recipe for target 'src/fastcgi/lfcgi.so' failed
make: *** [src/fastcgi/lfcgi.so] Error 1

 

原因是 fastcgi 沒有安裝, 安裝fastcgi庫

root@fqs:/home/share/wsapi-master/wsapi-master# apt-get install libfcgi
Reading package lists... Done
Building dependency tree      
Reading state information... Done
Note, selecting 'libfcgi0ldbl' instead of 'libfcgi'
The following packages were automatically installed and are no longer required:
  linux-headers-4.4.0-21 linux-headers-4.4.0-21-generic linux-image-4.4.0-21-generic linux-image-extra-4.4.0-21-generic
Use 'apt autoremove' to remove them.
The following NEW packages will be installed:
  libfcgi0ldbl
0 upgraded, 1 newly installed, 0 to remove and 71 not upgraded.
Need to get 161 kB of archives.
After this operation, 500 kB of additional disk space will be used.
Get:1 http://us.archive.ubuntu.com/ubuntu xenial/main amd64 libfcgi0ldbl amd64 2.4.0-8.3 [161 kB]
Fetched 161 kB in 2min 17s (1,168 B/s)                                                                                                                                                       
Selecting previously unselected package libfcgi0ldbl.
(Reading database ... 131376 files and directories currently installed.)
Preparing to unpack .../libfcgi0ldbl_2.4.0-8.3_amd64.deb ...
Unpacking libfcgi0ldbl (2.4.0-8.3) ...
Processing triggers for man-db (2.7.5-1) ...
Setting up libfcgi0ldbl (2.4.0-8.3) ...
Processing triggers for libc-bin (2.23-0ubuntu3) ...

make install // 安裝 wsapi腳本文件

make install-fcgi // 安裝 libfcgi庫

 

cgilua安裝

http://luaforge.net/projects/cgilua/

解壓直接 make

 

examples文件夾中的 index.lp文件, 需要將首行申明修改為 cgilua.fcgi

#!/usr/bin/env cgilua.fcgi

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>

 

訪問:

http://192.168.1.108:8081/index.lp

顯示:

image

 

lighttpd配置

以cgilua安裝包中的example為例子運行。

 

設置web腳本根目錄 && 錯誤日志路徑

## a static document-root, for virtual-hosting take look at the
## server.virtual-* options
server.document-root        = "/home/share/cgilua-master/cgilua-master/examples"

## where to send error-messages to
server.errorlog             = "/home/share/cgilua-master/cgilua-master/examples/lighttpd.error.log"

 

錯誤日志內容:

root@fqs:/home/share/cgilua-master/cgilua-master/examples# cat lighttpd.error.log
2016-07-03 16:24:22: (log.c.194) server started
2016-07-03 17:35:25: (request.c.311) fd: 7 request-len: 151 \nGET /hello.html HTTP/1.1\r\nUser-Agent: Wget/1.17.1 (linux-gnu)\r\nAccept: */*\r\nAccept-Encoding: identity\r\nHost: localhost:8081\r\nConnection: Keep-Alive\r\n\r\n
2016-07-03 17:35:25: (response.c.336) -- splitting Request-URI
2016-07-03 17:35:25: (response.c.337) Request-URI     :  /hello.html
2016-07-03 17:35:25: (response.c.338) URI-scheme      :  http
2016-07-03 17:35:25: (response.c.339) URI-authority   :  localhost:8081
2016-07-03 17:35:25: (response.c.340) URI-path (raw)  :  /hello.html
2016-07-03 17:35:25: (response.c.341) URI-path (clean):  /hello.html
2016-07-03 17:35:25: (response.c.342) URI-query       :  
2016-07-03 17:35:25: (mod_access.c.138) -- mod_access_uri_handler called
2016-07-03 17:35:25: (response.c.465) -- before doc_root
2016-07-03 17:35:25: (response.c.466) Doc-Root     : /home/share/cgilua-master/cgilua-master/examples
2016-07-03 17:35:25: (response.c.467) Rel-Path     : /hello.html
2016-07-03 17:35:25: (response.c.468) Path         : 
2016-07-03 17:35:25: (response.c.516) -- after doc_root
2016-07-03 17:35:25: (response.c.517) Doc-Root     : /home/share/cgilua-master/cgilua-master/examples
2016-07-03 17:35:25: (response.c.518) Rel-Path     : /hello.html
2016-07-03 17:35:25: (response.c.519) Path         : /home/share/cgilua-master/cgilua-master/examples/hello.html
2016-07-03 17:35:25: (response.c.536) -- logical -> physical
2016-07-03 17:35:25: (response.c.537) Doc-Root     : /home/share/cgilua-master/cgilua-master/examples
2016-07-03 17:35:25: (response.c.538) Basedir      : /home/share/cgilua-master/cgilua-master/examples
2016-07-03 17:35:25: (response.c.539) Rel-Path     : /hello.html
2016-07-03 17:35:25: (response.c.540) Path         : /home/share/cgilua-master/cgilua-master/examples/hello.html
2016-07-03 17:35:25: (response.c.557) -- handling physical path

 

將lp中添加到默認顯示文件中:

# files to check for if .../ is requested
index-file.names            = ( "index.php", "index.html", "index.lp",
                                "index.htm", "default.htm" )

 

訪問記錄日志:


#### accesslog module
accesslog.filename          = "/home/share/cgilua-master/cgilua-master/examples/access.log"

 

 

日志內容:

root@fqs:/home/share/cgilua-master/cgilua-master/examples# cat access.log
127.0.0.1 localhost:8081 - [03/Jul/2016:17:35:25 +0800] "GET /hello.html HTTP/1.1" 200 21 "-" "Wget/1.17.1 (linux-gnu)"
127.0.0.1 localhost:8081 - [03/Jul/2016:17:36:24 +0800] "GET /hello.html HTTP/1.1" 200 13 "-" "Wget/1.17.1 (linux-gnu)"
127.0.0.1 localhost:8081 - [03/Jul/2016:17:39:09 +0800] "GET /hello.html HTTP/1.1" 200 13 "-" "Wget/1.17.1 (linux-gnu)"
127.0.0.1 localhost:8081 - [03/Jul/2016:17:40:11 +0800] "GET /hello.html HTTP/1.1" 200 13 "-" "Wget/1.17.1 (linux-gnu)"
192.168.1.104 192.168.1.108:8081 - [03/Jul/2016:17:41:13 +0800] "GET /hello.html HTTP/1.1" 200 13 "-" "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0"
192.168.1.104 192.168.1.108:8081 - [03/Jul/2016:17:41:13 +0800] "GET /favicon.ico HTTP/1.1" 404 345 "-" "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0"
192.168.1.104 192.168.1.108:8081 - [03/Jul/2016:17:41:13 +0800] "GET /favicon.ico HTTP/1.1" 404 345 "-" "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0"

 

將lp后綴添加到需要fastcgi處理的列表中:


##
# which extensions should not be handle via static-file transfer
#
# .php, .pl, .fcgi are most often handled by mod_fastcgi or mod_cgi
static-file.exclude-extensions = ( ".php", ".pl", ".fcgi", ".lp" )

 

綁定端口修改:

## bind to port (default: 80)
server.port                = 8081

 

調試打印功能打開

## enable debugging
debug.log-request-header   = "enable"
debug.log-response-header  = "enable"
debug.log-request-handling = "enable"
debug.log-file-not-found   = "enable"

 

lp處理句柄描述

fastcgi.server             = ( ".lp" =>
                               ( "localhost" =>
                                 (
                                   "socket" => "/tmp/lp-fastcgi01.socket",
#                                   "bin-path" => "/usr/local/lib/luarocks/rocks/cgilua/5.1.4-2/bin/cgilua.fcgi"
                                   "bin-path" => "/home/share/cgilua-master/cgilua-master/src/launchers/cgilua.fcgi"
                                 )
                               )
                            )

 

運行

 

在 lighttpd.conf 所在目錄執行:

/usr/local/lighttpd/sbin/lighttpd  -f lighttpd.conf

 

查看lighttpd

root@fqs:/home/share/cgilua-master/cgilua-master/examples# ps aux | grep lighttpd
root      2449  0.0  0.2  24084  2260 ?        S    17:38   0:00 /usr/local/lighttpd/sbin/lighttpd -f lighttpd.conf
root      2541  0.0  0.1  14228  1028 pts/1    S+   18:55   0:00 grep --color=auto lighttpd
root@fqs:/home/share/cgilua-master/cgilua-master/examples#
root@fqs:/home/share/cgilua-master/cgilua-master/examples#

 

查看CGI程序

root@fqs:/home/share/cgilua-master/cgilua-master/examples# ps aux | grep lua
root      2450  0.0  0.3  22940  2844 ?        S    17:38   0:00 lua /home/share/cgilua-master/cgilua-master/src/launchers/cgilua.fcgi
root      2452  0.0  0.3  22940  2884 ?        S    17:38   0:00 lua /home/share/cgilua-master/cgilua-master/src/launchers/cgilua.fcgi
root      2454  0.0  0.3  22940  2852 ?        S    17:38   0:00 lua /home/share/cgilua-master/cgilua-master/src/launchers/cgilua.fcgi
root      2456  0.0  0.5  23868  3824 ?        S    17:38   0:00 lua /home/share/cgilua-master/cgilua-master/src/launchers/cgilua.fcgi
root      2539  0.0  0.1  14228  1088 pts/1    S+   18:54   0:00 grep --color=auto lua
root@fqs:/home/share/cgilua-master/cgilua-master/examples#

 

完整配置

http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs_ConfigurationOptions

 

# lighttpd configuration file
#
# use it as a base for lighttpd 1.0.0 and above
#
# $Id: lighttpd.conf,v 1.7 2004/11/03 22:26:05 weigon Exp $

############ Options you really have to take care of ####################

## modules to load
# at least mod_access and mod_accesslog should be loaded
# all other module should only be loaded if really neccesary
# - saves some time
# - saves memory
server.modules              = (
#                               "mod_rewrite",
#                               "mod_redirect",
#                               "mod_alias",
                                "mod_access",
#                               "mod_cml",
#                               "mod_trigger_b4_dl",
#                               "mod_auth",
#                               "mod_status",
#                               "mod_setenv",
                                "mod_fastcgi",
#                               "mod_proxy",
#                               "mod_simple_vhost",
#                               "mod_evhost",
#                               "mod_userdir",
#                               "mod_cgi",
#                               "mod_compress",
#                               "mod_ssi",
#                               "mod_usertrack",
#                               "mod_expire",
#                               "mod_secdownload",
#                               "mod_rrdtool",
                                "mod_accesslog" )

## a static document-root, for virtual-hosting take look at the
## server.virtual-* options
server.document-root        = "/home/share/cgilua-master/cgilua-master/examples"

## where to send error-messages to
server.errorlog             = "/home/share/cgilua-master/cgilua-master/examples/lighttpd.error.log"

# files to check for if .../ is requested
index-file.names            = ( "index.php", "index.html", "index.lp",
                                "index.htm", "default.htm" )

## set the event-handler (read the performance section in the manual)
# server.event-handler = "freebsd-kqueue" # needed on OS X

# mimetype mapping
mimetype.assign             = (
  ".pdf"          =>      "application/pdf",
  ".sig"          =>      "application/pgp-signature",
  ".spl"          =>      "application/futuresplash",
  ".class"        =>      "application/octet-stream",
  ".ps"           =>      "application/postscript",
  ".torrent"      =>      "application/x-bittorrent",
  ".dvi"          =>      "application/x-dvi",
  ".gz"           =>      "application/x-gzip",
  ".pac"          =>      "application/x-ns-proxy-autoconfig",
  ".swf"          =>      "application/x-shockwave-flash",
  ".tar.gz"       =>      "application/x-tgz",
  ".tgz"          =>      "application/x-tgz",
  ".tar"          =>      "application/x-tar",
  ".zip"          =>      "application/zip",
  ".mp3"          =>      "audio/mpeg",
  ".m3u"          =>      "audio/x-mpegurl",
  ".wma"          =>      "audio/x-ms-wma",
  ".wax"          =>      "audio/x-ms-wax",
  ".ogg"          =>      "application/ogg",
  ".wav"          =>      "audio/x-wav",
  ".gif"          =>      "image/gif",
  ".jpg"          =>      "image/jpeg",
  ".jpeg"         =>      "image/jpeg",
  ".png"          =>      "image/png",
  ".xbm"          =>      "image/x-xbitmap",
  ".xpm"          =>      "image/x-xpixmap",
  ".xwd"          =>      "image/x-xwindowdump",
  ".css"          =>      "text/css",
  ".html"         =>      "text/html",
  ".htm"          =>      "text/html",
  ".js"           =>      "text/javascript",
  ".asc"          =>      "text/plain",
  ".c"            =>      "text/plain",
  ".cpp"          =>      "text/plain",
  ".log"          =>      "text/plain",
  ".conf"         =>      "text/plain",
  ".text"         =>      "text/plain",
  ".txt"          =>      "text/plain",
  ".dtd"          =>      "text/xml",
  ".xml"          =>      "text/xml",
  ".mpeg"         =>      "video/mpeg",
  ".mpg"          =>      "video/mpeg",
  ".mov"          =>      "video/quicktime",
  ".qt"           =>      "video/quicktime",
  ".avi"          =>      "video/x-msvideo",
  ".asf"          =>      "video/x-ms-asf",
  ".asx"          =>      "video/x-ms-asf",
  ".wmv"          =>      "video/x-ms-wmv",
  ".bz2"          =>      "application/x-bzip",
  ".tbz"          =>      "application/x-bzip-compressed-tar",
  ".tar.bz2"      =>      "application/x-bzip-compressed-tar"
)

# Use the "Content-Type" extended attribute to obtain mime type if possible
#mimetype.use-xattr        = "enable"


## send a different Server: header
## be nice and keep it at lighttpd
server.tag                 = "lighttpd/1.4.11 (Win32)"

#### accesslog module
accesslog.filename          = "/home/share/cgilua-master/cgilua-master/examples/access.log"

## deny access the file-extensions
#
# ~    is for backupfiles from vi, emacs, joe, ...
# .inc is often used for code includes which should in general not be part
#      of the document-root
url.access-deny             = ( "~", ".inc" )

$HTTP["url"] =~ "\.pdf$" {
  server.range-requests = "disable"
}

##
# which extensions should not be handle via static-file transfer
#
# .php, .pl, .fcgi are most often handled by mod_fastcgi or mod_cgi
static-file.exclude-extensions = ( ".php", ".pl", ".fcgi", ".lp" )

######### Options that are good to be but not neccesary to be changed #######

## bind to port (default: 80)
server.port                = 8081

## bind to localhost (default: all interfaces)
#server.bind                = "localhost"

## error-handler for status 404
#server.error-handler-404   = "/error-handler.html"
#server.error-handler-404   = "/error-handler.php"

## to help the rc.scripts
#server.pid-file            = "/var/run/lighttpd.pid"


###### virtual hosts
##
##  If you want name-based virtual hosting add the next three settings and load
##  mod_simple_vhost
##
## document-root =
##   virtual-server-root + virtual-server-default-host + virtual-server-docroot
## or
##   virtual-server-root + http-host + virtual-server-docroot
##
#simple-vhost.server-root   = "/home/weigon/wwwroot/servers/"
#simple-vhost.default-host  = "grisu.home.kneschke.de"
#simple-vhost.document-root = "/pages/"


##
## Format: <errorfile-prefix><status-code>.html
## -> ..../status-404.html for 'File not found'
#server.errorfile-prefix    = "/home/weigon/projects/lighttpd/doc/status-"

## virtual directory listings
#dir-listing.activate       = "enable"

## enable debugging
debug.log-request-header   = "enable"
debug.log-response-header  = "enable"
debug.log-request-handling = "enable"
debug.log-file-not-found   = "enable"

### only root can use these options
#
# chroot() to directory (default: no chroot() )
#server.chroot              = "/"

## change uid to <uid> (default: don't care)
#server.username            = "wwwrun"

## change uid to <uid> (default: don't care)
#server.groupname           = "wwwrun"

#### compress module
#compress.cache-dir         = "/tmp/lighttpd/cache/compress/"
#compress.filetype          = ("text/plain", "text/html")

#### proxy module
## read proxy.txt for more info
#proxy.server               = ( ".php" =>
#                               ( "localhost" =>
#                                 (
#                                   "host" => "192.168.0.101",
#                                   "port" => 80
#                                 )
#                               )
#                             )

#### fastcgi module
## read fastcgi.txt for more info
## for PHP don't forget to set cgi.fix_pathinfo = 1 in the php.ini
#fastcgi.server             = ( ".php" =>
#                               ( "localhost" =>
#                                 (
#                                   "socket" => "/tmp/php-fastcgi.socket",
#                                   "bin-path" => "/usr/local/bin/php"
#                                 )
#                               )
#                            )

fastcgi.server             = ( ".lp" =>
                               ( "localhost" =>
                                 (
                                   "socket" => "/tmp/lp-fastcgi01.socket",
#                                   "bin-path" => "/usr/local/lib/luarocks/rocks/cgilua/5.1.4-2/bin/cgilua.fcgi"
                                   "bin-path" => "/home/share/cgilua-master/cgilua-master/src/launchers/cgilua.fcgi"
                                 )
                               )
                            )

 

#### CGI module
#cgi.assign                 = ( ".pl"  => "/usr/bin/perl",
#                               ".cgi" => "/usr/bin/perl" )
#

#### SSL engine
#ssl.engine                 = "enable"
#ssl.pemfile                = "C:/lighttpd/sbin/server.pem"

#### status module
#status.status-url          = "/server-status"
#status.config-url          = "/server-config"

#### auth module
## read authentication.txt for more info
#auth.backend               = "plain"
#auth.backend.plain.userfile = "lighttpd.user"
#auth.backend.plain.groupfile = "lighttpd.group"

#auth.backend.ldap.hostname = "localhost"
#auth.backend.ldap.base-dn  = "dc=my-domain,dc=com"
#auth.backend.ldap.filter   = "(uid=$)"

#auth.require               = ( "/server-status" =>
#                               (
#                                 "method"  => "digest",
#                                 "realm"   => "download archiv",
#                                 "require" => "user=jan"
#                               ),
#                               "/server-config" =>
#                               (
#                                 "method"  => "digest",
#                                 "realm"   => "download archiv",
#                                 "require" => "valid-user"
#                               )
#                             )

#### url handling modules (rewrite, redirect, access)
#url.rewrite                = ( "^/$"             => "/server-status" )
#url.redirect               = ( "^/wishlist/(.+)" => "http://www.123.org/$1" )
#### both rewrite/redirect support back reference to regex conditional using %n
#$HTTP["host"] =~ "^www\.(.*)" {
#  url.redirect            = ( "^/(.*)" => "http://%1/$1" )
#}

#
# define a pattern for the host url finding
# %% => % sign
# %0 => domain name + tld
# %1 => tld
# %2 => domain name without tld
# %3 => subdomain 1 name
# %4 => subdomain 2 name
#
#evhost.path-pattern        = "/home/storage/dev/www/%3/htdocs/"

#### expire module
#expire.url                 = ( "/buggy/" => "access 2 hours", "/asdhas/" => "access plus 1 seconds 2 minutes")

#### ssi
#ssi.extension              = ( ".shtml" )

#### rrdtool
#rrdtool.binary             = "/usr/bin/rrdtool"
#rrdtool.db-name            = "/var/www/lighttpd.rrd"

#### setenv
#setenv.add-request-header  = ( "TRAV_ENV" => "mysql://user@host/db" )
#setenv.add-response-header = ( "X-Secret-Message" => "42" )

## for mod_trigger_b4_dl
# trigger-before-download.gdbm-filename = "/home/weigon/testbase/trigger.db"
# trigger-before-download.memcache-hosts = ( "127.0.0.1:11211" )
# trigger-before-download.trigger-url = "^/trigger/"
# trigger-before-download.download-url = "^/download/"
# trigger-before-download.deny-url = "http://127.0.0.1/index.html"
# trigger-before-download.trigger-timeout = 10

## for mod_cml
## don't forget to add index.cml to server.indexfiles
# cml.extension               = ".cml"
# cml.memcache-hosts          = ( "127.0.0.1:11211" )

#### variable usage:
## variable name without "." is auto prefixed by "var." and becomes "var.bar"
#bar = 1
#var.mystring = "foo"

## integer add
#bar += 1
## string concat, with integer cast as string, result: "www.foo1.com"
#server.name = "www." + mystring + var.bar + ".com"
## array merge
#index-file.names = (foo + ".php") + index-file.names
#index-file.names += (foo + ".php")

#### include
#include /etc/lighttpd/lighttpd-inc.conf
## same as above if you run: "lighttpd -f /etc/lighttpd/lighttpd.conf"
#include "lighttpd-inc.conf"

#### include_shell
#include_shell "echo var.a=1"
## the above is same as:
#var.a=1

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM