xxfpmW 的誕生過程

  • 2020 年 12 月 29 日
  • 筆記

 

最近因為在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 鏈接地址://github.com/78/xxfpm

新 xxfpmW 地址在此:

gitee://gitee.com/jying/xxfpmW

github://github.com/jying000/xxfpmW