2分钟
在1024Code上通过Nginx配置C++的CGI程序实例
在1024Code搭建
Nginx+FastCGI
环境,通过C/C++
编写CGI程序实例,在无框架下初步学习做web
项目,建立对前后端的认知,了解前后端之间如何连接/通信/传参。
准备
要开始搭建,可以要先在1024Code创建一个C++环境的代码空间啦~
安装 Nginx
1024Code 安装软件通过 NixOS 进行安装,所以第一步最简单就是通过 pkgs.nginx
安装了,但是成功安装后,却发现 nginx
的安装路径在 /nix/store/
下,而当前用户无法修改里面的文件,导致无法修改 nginx
的配置。
于是想到通过源码安装 nginx
。首先需要安装依赖环境,通过修改 app目录
下的 .1024nix
然后 nix-shell .1024nix
即可。以下是 .1024nix
文件部分内容。
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
# ...
packages = [
# env
pkgs.gcc11
### 新增的依赖包
pkgs.zlib
pkgs.pcre
### end 新增的依赖包
pkgs.gnumake
pkgs.openssl
pkgs.sqlite
pkgs.mysql57
pkgs.jsoncpp
# ...
];
}
为什么要源码安装 nginx
呢?因为我们可以通过 configure
指定 nginx
的安装路径呀,以下是安装过程的shell命令~
nix-shell .1024nix
mkdir tmp && cd tmp
wget http://nginx.org/download/nginx-1.23.1.tar.gz
tar -zxvf nginx-1.23.1.tar.gz
cd nginx-1.23.1
./configure \
--prefix=/home/runner/app/nginx \
--pid-path=/home/runner/app/run/nginx/nginx.pid \
--lock-path=/home/runner/app/lock/nginx/nginx.lock \
--error-log-path=/home/runner/app/log/nginx/error.log \
--http-log-path=/home/runner/app/log/nginx/access.log \
--with-http_gzip_static_module \
--http-client-body-temp-path=/home/runner/tmp/nginx/client \
--http-proxy-temp-path=/home/runner/tmp/nginx/proxy \
--http-fastcgi-temp-path=/home/runner/tmp/nginx/fastcgi \
--http-uwsgi-temp-path=/home/runner/tmp/nginx/uwsgi \
--http-scgi-temp-path=/home/runner/tmp/nginx/scgi
make && make install
安装完成后,即可以通过命令行启动 niginx
啦~
#启动
/home/runner/app/nginx/sbin/nginx
#停止
/home/runner/app/nginx/sbin/nginx -s stop
#重新加载
/home/runner/app/nginx/sbin/nginx -s reload
安装 FastCGI 环境
需要我们基于C++写的CGI程序实例可以运行,并通过 niginx
访问,还需要搭建 FastCGI
,这里需要 spawn_fcgi
和 fcgiwrap
,都可以通过nix安装啦~
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
# ...
packages = [
# env
pkgs.gcc11
pkgs.zlib
pkgs.pcre
### 新增的依赖包
pkgs.fcgi
pkgs.fcgiwrap
pkgs.spawn_fcgi
### end 新增的依赖包
pkgs.gnumake
pkgs.openssl
pkgs.sqlite
pkgs.mysql57
pkgs.jsoncpp
# ...
];
}
2.然后修改 nginx.conf
,添加对 cgi
的解析:
# ...
http {
# ...
server {
# ...
location ~ \.cgi$ {
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.cgi;
include fastcgi.conf;
}
# ...
}
}
3.启动 fcgiwrap
即可啦~
spawn-fcgi -f fcgiwrap -p 9000
编写基于C++的CGI程序
1.创建一个cpp文件,写上一些内容:
// demo.cpp
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int count = 0;
printf("Content-type: text/html\r\n"
"\r\n"
"<title>CGI Hello!</title>"
"<h1>CGI Hello!</h1>"
"Request number %d running on host <i>%s</i>\n",
++count, getenv("SERVER_NAME"));
return 0;
}
2.然后通过g++
编译成可执行文件发到html
下即可。
g++ demo.cpp -o /home/runner/app/nginx/html/demo.cgi -lfcgi
3.访问 <host>/demo.cgi
即可看到我们写的内容啦~
优化启动命令
1.目前 fcgiwrap
只有启动命令,如果重启还需要通过 ps
参考对应进程号,在通过 kill
干掉。那么我们是否可以通过shell,弄一个类似 nginx
的这种模式呢?以下是我的实现:
# fcgi.sh
#! /bin/sh
DESC="spawn-fcgi daemon"
NAME=spawn-fcgi
BIND_HOST=127.0.0.1
BIND_PORT=9000
DAEMON_PIDFILE=/home/runner/app/run/spawn-fcgi.pid
d_start() {
$NAME -a $BIND_HOST -p $BIND_PORT -f fcgiwrap -P $DAEMON_PIDFILE
}
d_stop() {
kill -9 $(cat $DAEMON_PIDFILE) > /dev/null 2>&1 || echo -n " not running"
rm $DAEMON_PIDFILE
}
case "$1" in
start)
d_start
echo "."
;;
stop)
echo -n "Stopping $DESC: $NAME"
d_stop
echo "."
;;
restart)
echo -n "Restarting $DESC: $NAME"
d_stop
sleep 1
d_start
echo "."
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|restart}" >&2
exit 3
;;
esac
exit 0
2.现在即可通过命令行启动停止 fcgiwrap
啦~
#启动
sh /home/runner/app/fcgi.sh start
#停止
sh /home/runner/app/fcgi.sh stop
#重新加载
sh /home/runner/app/fcgi.sh restart
3.基于pid文件是否存在来判断 fcgiwrap
和 nginx
是否运行,就可以做一个启动命令,绑定到 运行 按钮下
# main.sh
#!/bin/bash
fcgiPidFile="/home/runner/app/run/spawn-fcgi.pid"
nginxPidFile="/home/runner/app/run/nginx/nginx.pid"
if [ -f "$nginxPidFile" ]; then
/home/runner/app/nginx/sbin/nginx -s stop
fi
if [ -f "$fcgiPidFile" ]; then
sh fcgi.sh stop
fi
mkdir -p /home/runner/tmp/nginx && ./nginx/sbin/nginx
sh fcgi.sh start
while true; do
sleep 1
done
4.添加运行命令到.1024
run_command: "sh main.sh"
最后
最后,我基于以上过程搭建了一个简单的博客站点,目前只有首页实现了,感兴趣的可以Fork把剩下的做完~