最近因为在win 服务器搭建php服务,发现php-cgi.exe 很容易崩溃,看cpu和硬盘都没有暴涨,也不知道啥原因,网上查发现有一款xxfpm 小应用可以解决这个问题,但这个应用是2011年开发的,虽然作者在github上的最新更新时间是5年前,但还是预留了一些小问题,作为完美主义者决定改进下。
主要问题有2:
1、该工具不是双击启动,需要cmd启动,但这样启动不能后台运行。
2、从评论看而且我也亲自尝试后确认,该工具在关机或重启时会弹出未能成功关闭的错误窗口,虽然只是一闪而过。作者给的答复是关机前应先手动关闭xxfpm。
针对问题1,网上关于后台运行的解决方式都是用一个RunHiddenConsole.exe 程序来控制,但是这个RunHiddenConsole.exe 身出何处,我实在是没找到,,,对于来源不明工具的使用还是要谨慎的。但好在一下子就找到了另一个宝贝: *.vbe 或 *.vbs 文件。查资料VBS的全称是:Microsoft Visual Basic Script Edition(微软基于VB的脚本语言)。vbe是vbs的密文版,右键编辑看不到明文,但我可能是直接手动编辑的原因,发现两者都可以编辑明文。
vbe使用方式为,在php-cgi.exe 所在文件夹下新建两个文件 php-cgi-start.bat 和 php-cgi.start.vbe,内容如下:
php-cgi-start.bat 内容:
php-cgi.exe -b 127.0.0.1:9000 -c php.ini
php-cgi-start.vbe 内容:
DIM objShell set objShell = wscript.createObject("wscript.shell") iReturn = objShell.Run("cmd.exe /C php-cgi-start.bat", 0, TRUE)
双击php-cgi-start.vbe 则可以启动php-cgi.exe 后台运行。
对于vbe 后台运行 xxfpm 是一样的方法:
首先需要将 xxfpm 和 pthreadGC2.dll 放到php-cgi.exe 所在的文件夹下,pthreadGC2.dll 为 xxfpm引用的类库,是必须文件。网上以前的介绍是将该文件添加进注册表,本人发现并不需要,只要跟xxfpm放在同一个文件夹下即可,而且作者已经将pthreadGC2.dll上传到了github上,无需去别的资源下载。
然后我们创建 xxfpm.bat 和 xxfpm.vbe 文件,内容如下:
xxfpm.bat 内容:
xxfpm "php-cgi.exe -c php.ini" -n 3 -p 9000
xxfpm.vbe 内容:
DIM objShell set objShell = wscript.createObject("wscript.shell") iReturn = objShell.Run("cmd.exe /C xxfpm.bat", 0, TRUE)
双击xxfpm.vbe后查看任务管理器,发现xxfpm和n个php-cgi.exe 已经在运行而且没有弹出任何窗口。
对应问题2,想到的自然是在关机前通知xxfpm关闭进程,于是开始了漫漫学习之路~~~~~~~~~
从xxfpm 源文件main.c可知,该程序为C语言所做,但是我对C一无所知啊,这次肯定是要改源码的。为了荣誉,不是,为了完美主义,只能硬着头皮硬上了。
本来我学习的第一语言是C#,虽然现在工作上已经不用它了,但平时还会开发点winform小玩意,所以电脑上还有vs2015的开发环境,自然而然本次首选开发C的工具就是它了。
然后遇到了第一个问题,创建完C语言项目,添加main.c 文件后发现缺少很多h头文件,里面原来即有win32的也有linux环境的头文件,于是把linux的那些头文件都删掉,然后又通过网上说的管理NuGet程序包添加pthread引用文件,编译后又报 timespec 已定义,注释掉该定义又报其它一堆错误。。。最终只得放弃vs开发。。。
重新看了一遍xxfpm作者的文章,说是借鉴了 cygwin 里的一些源码,cygwin是什么?原来是一个在windows模仿linux环境的工具,果断安装!!!
安装完成并配置环境变量后编写了第一个hello world程序,并通过 gcc hello.c -o hello 生成可执行文件hello.exe,但是,该文件移植到别的电脑运行提示缺少cygwin1.dll的引用!!!以为是参数有误,于是学习了该语法的各个参数-egcsoW等使用,发现还是不行。。。网上又找了一堆都是复制粘贴的资料,有的说把cygwin1.dll 文件复制到系统目录下,但是这治标不治本啊,总不能让所有使用的人都配置cygwin1.dll文件吧(虽然也可以,但那太差劲了!),还有一种说法是在编译的时候加入 -mno-mingw,试了下提示没有该参数,然后又查资料说cygwin早已抛弃了该参数,于是一下子又陷入了窘境没了方向。。。
忽然想到作者的博客里会不会有介绍到自己的开发环境,毕竟所有的人都是从一步步搭建环境开始的,于是翻看了作者所有除了跟照片有关的博客,果然有所发现,在某个评论里有人问用的什么开发工具,作者说是mingw32 ,纳尼,这又是个啥,,,原来它是一个在windows环境编译gcc的工具,而且比cygwin更适合windows环境!
于是又是一通安装,但是因为墙的原因,只安装成功了gcc 和 g++,而gdb始终安装不上,官网的gdb资源后缀是lzma,查了下也是一种压缩文件,但是还需要特殊的解压命令,而gdb是用来调试的,所以不安装对编译也没有影响,果断不安装。将原来的cygwin从环境变量里移除,改为mingw32绑定系统环境变量,仍然可以在cmd使用gcc
再一次踏上编译之路。还是缺少pthread头文件,从网上搜到需要将pthread对应文件添加到对应的文件夹下,其中 (pthread.h 、 sched.h、semaphore.h)三个 头文件放到 MinGW/include文件夹,libpthreadGC2.a 放到 MinGW/lib文件夹下并重命名为libpthread.a。然后满怀信心的编译 gcc -o main main.c -lpthread,结果又报一堆问题如:undefined reference to `WSACleanup@0',搜了下是缺少win32的库引用,需要加 -lWs2_32,加上后果然编译成功!!!!开心的像个宝宝!!!!
最终编译成功语句:
gcc -o main main.c -lpthread -lWs2_32
拷贝生成的main.exe文件到php文件夹下执行没问题!!!
接下来是修改源文件添加关机或重启时关闭xxfpm进程。
其实在改用cygwin之前,尝试在vs里编译过一个C启动停止winform的实例,在关机或重启时确实能捕捉到关闭通知,然后可以执行阻断或其他的一些操作,但xxfpm不是winform的,所以代码还不能直接拿来用,得另查代码。
xxfpm源码中启用进程用的是 createProcess,按此查相应关闭进程的方法,要么是 TerminateProcess,要么是ExitProcess,但这两个显然都是主动调用的,并不能像winform那样主动监听关机消息。。。然后有个说主动监听的函数是SetConsoleCtrlHandler,测试发现并没有用!!!!经过再三努力,也没有找到有用的信息,有资料说createProcess 创建的进程是无法做到的(希望有C++相关方面的大神帮忙解答下有没有想要的方法),所以又懵了,像一只失去梦想的咸鱼。。。。
当我准备放弃时,忽然发现经过我删减只保留win的代码在关机时没有弹出错误窗口!!!!!开机又试了一次原xxfpm又报错,再试一次自己编译的果然不报错!!!!所以问题是在专用于linux那段代码在win上有问题,没有去挨个验证具体是哪一段的问题,但现在删掉后是没有问题啦!!!!开心,关机,改天再续!!!!
经过前面编译和测试文章一开始的两个问题都解决了,但后台运行后如果报错无法知晓,于是觉得给它添加写日志到文件的功能,经过一番学习已实现,其中运行(启动和重启)日志记录在log.txt中,错误日志记录在 error_log.txt 中。由于只保留了win版本功能,故编译后执行文件命名为xxfpmW。
原 xxfpm 链接地址:https://github.com/78/xxfpm
新 xxfpmW 地址在此: