ホームページ php教程 php手册 windows下php-cgi进程守护

windows下php-cgi进程守护

Jun 06, 2016 pm 07:31 PM
php php-cgi windows プロセス

php在linux,unix下有php-fpm,spawn-fcgi等进程守护程序,但是在window下没有。 一般会以下命令启动C:/php5/php-cgi.exe-b127.0.0.1:9000-cC:/php5/php.ini 但是这样受限于php-cgi的PHP_FCGI_MAX_REQUESTS环境变量,默认处理500次后自动退出php-cgi.加之一些非

       php在linux,unix下有php-fpm,spawn-fcgi等进程守护程序,但是在window下没有。
一般会以下命令启动 C:/php5/php-cgi.exe -b 127.0.0.1:9000 -c C:/php5/php.ini 
但是这样受限于php-cgi的PHP_FCGI_MAX_REQUESTS环境变量,默认处理500次后自动退出php-cgi.加之一些非正常原因的异常退出,都会导致php-cgi.exe的退出。所有在window需要进程守护程序,当php-cgi退出后自动打开新的php-cgi进程。
      注意事项:windows建议关闭Dr. Watson,否则 异常的php-cgi无法正常退出。 
http://support.microsoft.com/kb/188296/zh-cn
// FastCGIHelper.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#pragma comment(lib, "ws2_32.lib")

const PCHAR cServiceName="WinFastCGIHelper";

HANDLE hJob;

INT  icount;
INT	 iport;
CHAR ipbuf[32];
CHAR cmdbuf[256];

//---------------------------------------------------------------------------
SERVICE_STATUS ServiceStatus;
SERVICE_STATUS_HANDLE hStatus;

void Install(void);
void Uninstall(void);
void ServiceMain(int argc, char** argv);
void ThreadProc(LPVOID pParam);
void ControlHandler(DWORD request);

//---------------------------------------------------------------------------
int _tmain(int argc, _TCHAR* argv[])
{
    if (argc>1 && _stricmp(argv[1],"/i")==0)
    {
        Install();
    }
    else if (argc>1 && _stricmp(argv[1],"/u")==0)
    {
        Uninstall();
    }
    else
    {
        SERVICE_TABLE_ENTRY ServiceTable[2];
        ServiceTable[0].lpServiceName = cServiceName;
        ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;

        ServiceTable[1].lpServiceName = NULL;
        ServiceTable[1].lpServiceProc = NULL;

        ::StartServiceCtrlDispatcher(ServiceTable);
    }

	return 0;
}

void ServiceMain(int argc, char** argv)
{
    ServiceStatus.dwServiceType  =SERVICE_WIN32;
    ServiceStatus.dwCurrentState =SERVICE_START_PENDING;
    ServiceStatus.dwControlsAccepted  = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
    ServiceStatus.dwWin32ExitCode     = 0;
    ServiceStatus.dwServiceSpecificExitCode = 0;
    ServiceStatus.dwCheckPoint = 0;
    ServiceStatus.dwWaitHint   = 0;

    hStatus = ::RegisterServiceCtrlHandler(cServiceName, (LPHANDLER_FUNCTION)ControlHandler);
    if (hStatus == NULL)    return;

    if (GetLastError()!=NO_ERROR)
	{ 
        ServiceStatus.dwCurrentState = SERVICE_STOPPED;
        ::SetServiceStatus(hStatus, &ServiceStatus);
        return; 
    }

	CHAR cConfigName[256];
	ZeroMemory(cConfigName,256);
	DWORD dwSize=GetModuleFileName(NULL,cConfigName,256);
    while(dwSize>0 && cConfigName[dwSize]!='\\')
        cConfigName[dwSize--]=0;

	strcat_s(cConfigName,"config.ini");

	icount=GetPrivateProfileInt("setup","CmdCount",1,cConfigName);
	GetPrivateProfileString("setup","CmdPath","",cmdbuf,256,cConfigName);
	
	if(icount<1) icount=1;
	if(icount>32) icount=32;

	iport =GetPrivateProfileInt("setup","Port",9000,cConfigName);
	GetPrivateProfileString("setup","IP","127.0.0.1",ipbuf,32,cConfigName);

	WSADATA wsa_data; 
	WSAStartup(0x0202, &wsa_data);

	SOCKADDR_IN listen_addr;
	listen_addr.sin_family		=AF_INET;
	listen_addr.sin_addr.S_un.S_addr= inet_addr(ipbuf);
	listen_addr.sin_port		= htons(iport);

	DWORD s=socket(AF_INET,SOCK_STREAM,IPPROTO_IP);
	if(bind(s, (struct sockaddr*)&listen_addr, sizeof(struct sockaddr_in)) || listen(s,16) ){
        ServiceStatus.dwCurrentState = SERVICE_STOPPED;
        ::SetServiceStatus(hStatus, &ServiceStatus);
        return; 
	}
	
	CHAR strtmp[128];
	ZeroMemory(strtmp,128);

	GetPrivateProfileString("env","PHPRC",".",strtmp,127,cConfigName);
	SetEnvironmentVariable("PHPRC",strtmp);

	GetPrivateProfileString("env","PHP_FCGI_MAX_REQUESTS","5000",strtmp,127,cConfigName);
	SetEnvironmentVariable("PHP_FCGI_MAX_REQUESTS",strtmp);

	hJob=CreateJobObject(NULL,NULL);

	JOBOBJECT_EXTENDED_LIMIT_INFORMATION limit;
	QueryInformationJobObject(hJob, JobObjectExtendedLimitInformation, &limit, sizeof(limit), NULL);
	limit.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
	SetInformationJobObject(hJob, JobObjectExtendedLimitInformation, &limit, sizeof(limit));

	ServiceStatus.dwCurrentState = SERVICE_RUNNING;
    SetServiceStatus(hStatus, &ServiceStatus);

	for(int i=0;i<icount;i++)
		CloseHandle(CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadProc,(LPVOID)s,0,0));
	
	WaitForSingleObject(hJob, INFINITE);
	
	closesocket(s);
	WSACleanup();
    
    ServiceStatus.dwWin32ExitCode = 0;
    ServiceStatus.dwCurrentState  = SERVICE_STOPPED;
    SetServiceStatus(hStatus, &ServiceStatus);
}
//---------------------------------------------------------------------------
void  ThreadProc(LPVOID pParam)
{
	STARTUPINFO si; 
	PROCESS_INFORMATION pi;   

	while(ServiceStatus.dwCurrentState == SERVICE_RUNNING)
	{
		ZeroMemory(&si,sizeof(STARTUPINFO));
		ZeroMemory(&pi,sizeof(PROCESS_INFORMATION));

		si.cb = sizeof(STARTUPINFO);
		si.dwFlags 	= STARTF_USESTDHANDLES;
		si.hStdInput  = (HANDLE)pParam;
		si.hStdOutput = INVALID_HANDLE_VALUE;
		si.hStdError  = INVALID_HANDLE_VALUE;

		if(0==CreateProcess(NULL,cmdbuf,NULL,NULL,TRUE, 
			CREATE_NO_WINDOW | CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB ,NULL,NULL,&si,&pi))
				break;

		AssignProcessToJobObject(hJob, pi.hProcess);
		ResumeThread(pi.hThread);

		WaitForSingleObject(pi.hProcess, INFINITE);

		CloseHandle( pi.hProcess);
		CloseHandle( pi.hThread );
	}
}
//---------------------------------------------------------------------------
void ControlHandler(DWORD request)
{
   switch(request)
   {
      case SERVICE_CONTROL_STOP:
        ServiceStatus.dwWin32ExitCode = 0;
        ServiceStatus.dwCurrentState  = SERVICE_STOPPED;
        SetServiceStatus(hStatus, &ServiceStatus);

		CloseHandle(hJob);
        return;

      case SERVICE_CONTROL_SHUTDOWN:
        ServiceStatus.dwWin32ExitCode = 0;
        ServiceStatus.dwCurrentState  = SERVICE_STOPPED;
        SetServiceStatus(hStatus, &ServiceStatus);

		CloseHandle(hJob);
        return;
    } 

    ::SetServiceStatus (hStatus, &ServiceStatus);
}
//---------------------------------------------------------------------------
void Install(void)
{
    char  szFilePath[256];
    SC_HANDLE hSCM,hService;

    ZeroMemory(szFilePath,256);
    GetModuleFileName(NULL,szFilePath,256);

    hSCM=::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
	SC_LOCK sclLock = LockServiceDatabase(hSCM); 

    hService = ::CreateService( hSCM, cServiceName, cServiceName,
        SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,SERVICE_DEMAND_START,
            SERVICE_ERROR_NORMAL, szFilePath, NULL, NULL,NULL, NULL, NULL);

	SERVICE_DESCRIPTION sdBuf;
	sdBuf.lpDescription = "php fastcgi process helper for windows";
	ChangeServiceConfig2(hService,SERVICE_CONFIG_DESCRIPTION,&sdBuf);

	::CloseServiceHandle(hService);   
	::UnlockServiceDatabase(sclLock); 

    ::CloseServiceHandle(hSCM);
    printf("Service Install OK !!!");
}

//---------------------------------------------------------------------------
void Uninstall(void)
{
    SERVICE_STATUS sStatus ;
    SC_HANDLE hSCM=::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    SC_HANDLE hService=::OpenService(hSCM, cServiceName, SERVICE_STOP | DELETE);

    if (hService==NULL)
    {
        printf("Service Open Error !!!");
    }
    else
    {
        ::ControlService(hService, SERVICE_CONTROL_STOP, &sStatus);
        ::DeleteService(hService);
        printf("Service Uninstall OK !!!");
    }

    ::CloseServiceHandle(hService);
    ::CloseServiceHandle(hSCM);
}
//---------------------------------------------------------------------------
ログイン後にコピー
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットな記事タグ

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Ubuntu および Debian 用の PHP 8.4 インストールおよびアップグレード ガイド Ubuntu および Debian 用の PHP 8.4 インストールおよびアップグレード ガイド Dec 24, 2024 pm 04:42 PM

Ubuntu および Debian 用の PHP 8.4 インストールおよびアップグレード ガイド

Bybit Exchangeの最新バージョンを更新する方法は?更新されていない場合、影響はありますか? Bybit Exchangeの最新バージョンを更新する方法は?更新されていない場合、影響はありますか? Feb 21, 2025 pm 10:54 PM

Bybit Exchangeの最新バージョンを更新する方法は?更新されていない場合、影響はありますか?

Deepseek Webバージョンの入り口Deepseek公式ウェブサイトの入り口 Deepseek Webバージョンの入り口Deepseek公式ウェブサイトの入り口 Feb 19, 2025 pm 04:54 PM

Deepseek Webバージョンの入り口Deepseek公式ウェブサイトの入り口

DeepSeekをインストールする方法 DeepSeekをインストールする方法 Feb 19, 2025 pm 05:48 PM

DeepSeekをインストールする方法

PIノードティーチング:PIノードとは何ですか? PIノードをインストールしてセットアップする方法は? PIノードティーチング:PIノードとは何ですか? PIノードをインストールしてセットアップする方法は? Mar 05, 2025 pm 05:57 PM

PIノードティーチング:PIノードとは何ですか? PIノードをインストールしてセットアップする方法は?

PHP 開発用に Visual Studio Code (VS Code) をセットアップする方法 PHP 開発用に Visual Studio Code (VS Code) をセットアップする方法 Dec 20, 2024 am 11:31 AM

PHP 開発用に Visual Studio Code (VS Code) をセットアップする方法

PHPでHTML/XMLを解析および処理するにはどうすればよいですか? PHPでHTML/XMLを解析および処理するにはどうすればよいですか? Feb 07, 2025 am 11:57 AM

PHPでHTML/XMLを解析および処理するにはどうすればよいですか?

Coinsuper Exchangeソフトウェアチャネル公式ウェブサイトの入り口 Coinsuper Exchangeソフトウェアチャネル公式ウェブサイトの入り口 Feb 21, 2025 pm 10:39 PM

Coinsuper Exchangeソフトウェアチャネル公式ウェブサイトの入り口

See all articles