最近因為在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 地址在此:
gitee:https://gitee.com/jying/xxfpmW
github:https://github.com/jying000/xxfpmW