搜索
首页php教程php手册windows下php-cgi进程守护

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

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

安全考试浏览器

安全考试浏览器

Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。

SublimeText3 英文版

SublimeText3 英文版

推荐:为Win版本,支持代码提示!

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )专业的PHP集成开发工具