日期:2012-03-04 05:41:00  来源:本站整理

windows下的Nginx和php搭配php-cgi.exe自动关闭退出的完善办理办法[服务器安全]

赞助商链接



  本文“windows下的Nginx和php搭配php-cgi.exe自动关闭退出的完善办理办法[服务器安全]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:

 php-cgi.exe在windows+nginx平台下常常自动退出,网上搜到的大部份办理办法都是近似上面的批处理(代码以下)文件暂时办理一下,但假如用户在网站登录的话,用户就会忽然挂掉.

@echo off
:main
set jinchengshuliang=0
set jinchengshuliangxiaxian=2
for /f %%i in ('tasklist /nh^|findstr /i /s /c:"php-cgi.exe"') do set /a jinchengshuliang+=1

if %jinchengshuliang% lss %jinchengshuliangxiaxian% (   
goto youwenti
) else (
goto meiwenti
)  

:youwenti
echo 进程丧失,目前增添5个进程
RunHiddenConsole.exe  php\php-cgi.exe -b 127.0.0.1:9000 -c php\php.ini
RunHiddenConsole.exe  php\php-cgi.exe -b 127.0.0.1:9000 -c php\php.ini
RunHiddenConsole.exe  php\php-cgi.exe -b 127.0.0.1:9000 -c php\php.ini
RunHiddenConsole.exe  php\php-cgi.exe -b 127.0.0.1:9000 -c php\php.ini
RunHiddenConsole.exe  php\php-cgi.exe -b 127.0.0.1:9000 -c php\php.ini
ping 127.1 -n 8
goto main

:meiwenti
echo 正常运行中!
ping 127.1 -n 8
goto main

  最好的办理办法是用windows下的php-cgi进程管理器,该进程管理器需求用到pthreadGC2.dll.源码和编译文件在本文末尾供应下载.经测试,支持Win32和Linux-x86平台.关于用php的人,有了这个东西来保护一定数目的进程,就可以制服常常崩溃退出的php-cgi啦!

 

以下是xxfpm进程管理器的操作参数:

Usage: xxfpm path [-n number] [-i ip] [-p port]
Manage FastCGI processes.

-n, --number number of processes to keep
-i, --ip ip address to bind
-p, --port port to bind, default is 8000
-u, --user start processes using specified linux user
-g, --group start processes using specified linux group
-r, --root change root direcotry for the processes
-h, --help output usage information and exit
-v, --version output version information and exit

  第一个写得对比尺度的终端利用程序,我是看了cygwin的里的一些源代码,然后学会了若何利用getopt,算是写得对比尺度的,但是代码也不短.

利用例子:

xxfpm z:/php5/php-cgi.exe -n 5 -p 8080
有人问,若何给程序加入参数?这个不难,利用双引号便可,途径要用"/"而不用"\".比方要指定php.ini的途径,可以用下面例子:
xxfpm "z:/php5/php-cgi.exe -c z:/php5/php.ini" -n 5 -i 127.0.0.1 -p 8080

保护进程原理:

  Windows上利用CreateProcess成立进程,利用Wait For Single Object等候进程完毕;Linux上利用fork和execl成立进程,利用waitpid等候进程完毕.Linux的版本多了在成立子进程的时刻可以设置进程限制,可以以受限用户方法来运行.

   当进程管理器被关闭的时刻,它所成立的全部子进程也必须被关闭.Windows上利用JobObject这个东西来把子进程与管理器的进程产生关联,感 谢iceboy供应的资料!Linux上通过捕捉关闭信号,然后给全部子进程发送SIGTERM来完毕子进程.详见源代码:

#ifdef __WIN32__

#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0500
#endif //_WIN32_WINNT

#include <windows.h>
#include <winsock.h>
#include <wininet.h>
#define SHUT_RDWR SD_BOTH

#ifndef JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
#define JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE (0x2000)
#endif
HANDLE FcpJobObject;

#else

#include <sys/socket.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <grp.h>
#include <pwd.h>
#include <unistd.h>
#define closesocket close

#endif //__WIN32__


#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>

#define MAX_PROCESSES 1024
static const char version[] = "$Revision: 0.01 $";
static char* prog_name;
int number = 1;
int port = 8000;
char *ip = "127.0.0.1";
char *user = "";
char *root = "";
char *path = "";
char *group = "";
int listen_fd;
struct sockaddr_in listen_addr;
int process_fp[MAX_PROCESSES];
int process_idx = 0;
pthread_t threads[MAX_PROCESSES];

static struct option longopts[] =
{
 {"help", no_argument, NULL, 'h'},
 {"version", no_argument, NULL, 'v'},
 {"number", required_argument, NULL, 'n'},
 {"ip", required_argument, NULL, 'i'},
 {"port", required_argument, NULL, 'p'},
 {"user", required_argument, NULL, 'u'},
 {"group", required_argument, NULL, 'g'},
 {"root", required_argument, NULL, 'r'},
 {NULL, 0, NULL, 0}
};

static char opts[] = "hvnipugr";

static void usage(FILE* where)
{
 fprintf(where, ""
  "Usage: %s path [-n number] [-i ip] [-p port]\n"
  "Manage FastCGI processes.\n"
  "\n"
  " -n, --number  number of processes to keep\n"
  " -i, --ip      ip address to bind\n"
  " -p, --port    port to bind, default is 8000\n"
  " -u, --user    start processes using specified linux user\n"
  " -g, --group   start processes using specified linux group\n"
  " -r, --root    change root direcotry for the processes\n"
  " -h, --help    output usage information and exit\n"
  " -v, --version output version information and exit\n"
  "", prog_name);
 exit(where == stderr ? 1:0);
}

static void print_version()
{
 printf("%s %s\n\
FastCGI Process Manager\n\
Copyright 2010 Xiaoxia.org\n\
Compiled on %s\n\
", prog_name, version, __DATE__);
 exit(0);
}

static int try_to_bind()
{
 listen_addr.sin_family = PF_INET;
 listen_addr.sin_addr.s_addr = inet_addr( ip );
 listen_addr.sin_port = htons( port );
 listen_fd = socket(AF_INET, SOCK_STREAM, 0);

			
 if (-1 == bind(listen_fd, (struct sockaddr*)&listen_addr, sizeof(struct sockaddr_in)) ) {
  fprintf(stderr, "failed to bind %s:%d\n", ip, port );
  return -1;
 }

			
 listen(listen_fd, MAX_PROCESSES);
 return 0;
}

static void* spawn_process(void* arg)
{
 int idx = process_idx ++, ret;
 while(1){
#ifdef __WIN32__
  STARTUPINFO si={0};
  PROCESS_INFORMATION pi={0};
  ZeroMemory(&si,sizeof(STARTUPINFO));
  si.cb = sizeof(STARTUPINFO);
  si.dwFlags = STARTF_USESTDHANDLES;
  si.hStdInput  = (HANDLE)listen_fd;
  si.hStdOutput = INVALID_HANDLE_VALUE;
  si.hStdError  = INVALID_HANDLE_VALUE;
  if(0 == (ret=CreateProcess(NULL, path,
   NULL,NULL,
   TRUE, CREATE_NO_WINDOW | CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB,
   NULL,NULL,
   &si,&pi)) ){
   fprintf(stderr, "failed to create process %s, ret=%d\n", path, ret);
   return NULL;
  }

			
  /* Use Job Control System */
  if(!AssignProcessToJobObject(FcpJobObject, pi.hProcess)){
   TerminateProcess(pi.hProcess, 1);
   CloseHandle(pi.hProcess);
   CloseHandle(pi.hThread);
   return NULL;
  }

			
  if(!ResumeThread(pi.hThread)){
   TerminateProcess(pi.hProcess, 1);
   CloseHandle(pi.hProcess);
   CloseHandle(pi.hThread);
   return NULL;
  }

			
  process_fp[idx] = (int)pi.hProcess;
  WaitForSingleObject(pi.hProcess, INFINITE);
  process_fp[idx] = 0;
  CloseHandle(pi.hThread);
#else
  ret = fork();
  switch(ret){
  case 0:{ //child
   /* change uid from root to other user */
   if(getuid()==0){ 
                struct group *grp = NULL;
                struct passwd *pwd = NULL;
    if (*user) {
     if (NULL == (pwd = getpwnam(user))) {
      fprintf(stderr, "[fcgi] %s %s\n", "can't find username", user);
      exit(-1);
     }

     if (pwd->pw_uid == 0) {
      fprintf(stderr, "[fcgi] %s\n", "what? dest uid == 0?" );
      exit(-1);
     }
    }

    if (*group) {
     if (NULL == (grp = getgrnam(group))) {
      fprintf(stderr, "[fcgi] %s %s\n", "can't find groupname", group);
      exit(1);
     }

     if (grp->gr_gid == 0) {
      fprintf(stderr, "[fcgi] %s\n", "what? dest gid == 0?" );
      exit(1);
     }
     /* do the change before we do the chroot() */
     setgid(grp->gr_gid);
     setgroups(0, NULL);

     if (user) {
      initgroups(user, grp->gr_gid);
     }
    }
    if (*root) {
     if (-1 == chroot(root)) {
      fprintf(stderr, "[fcgi] %s %s\n", "can't change root", root);
      exit(1);
     }
     if (-1 == chdir("/")) {
      fprintf(stderr, "[fcgi] %s %s\n", "can't change dir to", root);
      exit(1);
     }
    }

    /* drop root privs */
    if (*user) {
     setuid(pwd->pw_uid);
    }
   }

			
   int max_fd = 0, i=0;
   // Set stdin to listen_fd
   close(STDIN_FILENO);
   dup2(listen_fd, STDIN_FILENO);
   close(listen_fd);
   // Set stdout and stderr to dummy fd
   max_fd = open("/dev/null", O_RDWR);
   close(STDERR_FILENO);
   dup2(max_fd, STDERR_FILENO);
   close(max_fd);
   max_fd = open("/dev/null", O_RDWR);
   close(STDOUT_FILENO);
   dup2(max_fd, STDOUT_FILENO);
   close(max_fd);
   // close other handles
   for(i=3; i<max_fd; i++)
    close(i);
   char *b = malloc(strlen("exec ") + strlen(path) + 1);
   strcpy(b, "exec ");
   strcat(b, path);

			
   /* exec the cgi */
   execl("/bin/sh", "sh", "-c", b, (char *)NULL);
   exit(errno);
   break;
  }
  case -1:
   fprintf(stderr, "[fcgi] fork failed\n");
   return NULL;
  default:{
   struct timeval tv = { 0, 100 * 1000 };
   int status;
   select(0, NULL, NULL, NULL, &tv);
   switch(waitpid(ret, &status, WNOHANG)){
   case 0:
    printf("[fcg] spawned process %s: %d\n", path, ret);
    break;
   case -1:
    fprintf(stderr, "[fcgi] waitpid failed\n");
    return NULL;
   default:
    if (WIFEXITED(status)) {
      fprintf(stderr, "[fcgi] child exited with: %d\n", WEXITSTATUS(status));
    } else if (WIFSIGNALED(status)) {
      fprintf(stderr, "[fcgi] child signaled: %d\n", WTERMSIG(status));
    } else {
      fprintf(stderr, "[fcgi] child died somehow: %d\n", status);
    }
    return NULL;
   }
   //wait for child process to exit
   process_fp[idx] = ret;
   waitpid(ret, &status, 0);
   process_fp[idx] = 0;
  }
  }
#endif
 }
}

static int start_processes()
{
 int i;
 pthread_attr_t attr;
 pthread_attr_init(&attr);
 pthread_attr_setstacksize(&attr, 64*1024); //64KB
 for(i=0; i<number; i++){
  if( pthread_create( &threads, &attr, spawn_process, NULL ) == -1 ){
   fprintf(stderr, "failed to create thread %d\n", i);
  }
 }

			
 for(i=0; i<number; i++){
  pthread_join(threads, NULL);
 }
 return 0;
}

#ifdef __WIN32__
void init_win32()
{
 /* init win32 socket */
 static WSADATA wsa_data; 
 if(WSAStartup((WORD)(1<<8|1), &wsa_data) != 0)
  exit(1);
 JOBOBJECT_EXTENDED_LIMIT_INFORMATION limit;
 FcpJobObject = (HANDLE)CreateJobObject(NULL, NULL);
 if(FcpJobObject == NULL) 
  exit(1);

			
 /* let all processes assigned to this job object
  * being killed when the job object closed */
 if (!QueryInformationJobObject(FcpJobObject, JobObjectExtendedLimitInformation, &limit, sizeof(limit), NULL)) {
  CloseHandle(FcpJobObject);
  exit(1);
 }

 limit.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;

 if (!SetInformationJobObject(FcpJobObject, JobObjectExtendedLimitInformation, &limit, sizeof(limit))) {
  CloseHandle(FcpJobObject);
  exit(1);
 }
}
#endif //__WIN32__

#ifndef __WIN32__
void before_exit(int sig)
{
 signal(SIGTERM, SIG_DFL);
 /* call child processes to exit */
 kill(0, SIGTERM);
}
#endif

int main(int argc, char **argv)
{
 prog_name = strrchr(argv[0], '/');
 if(prog_name == NULL)
  prog_name = strrchr(argv[0], '\\');
 if(prog_name == NULL)
  prog_name = argv[0];
 else
  prog_name++;

			
 if(argc == 1)
  usage(stderr);

			
 path = argv[1];

			
 opterr = 0;

			
 char* p;

 for(;;){
  int ch;
  if((ch = getopt_long(argc, argv, opts, longopts, NULL)) == EOF)
   break;
  char *av = argv[optind];
  switch(ch){
  case 'h':
   usage(stdout);
   break;
  case 'v':
   print_version();
   break;
  case 'n':
   number = atoi(av);
   if(number > MAX_PROCESSES){
    fprintf(stderr, "exceeds MAX_PROCESSES!\n");
    number = MAX_PROCESSES;
   }
   break;
  case 'u':
   user = av;
   break;
  case 'r':
   root = av;
   break;
  case 'g':
   group = av;
   break;
  case 'i':
   ip = av;
   break;
  case 'p':
   port = atoi(av);
   break;
  default:
   usage(stderr);
   break;
  }
 }

#ifdef __WIN32__
 init_win32();
#else
 /* call child processes to exit */
 signal(SIGTERM, before_exit);
 signal(SIGINT, before_exit);
 signal(SIGABRT, before_exit);
#endif

			
 int ret;
 ret = try_to_bind();
 if(ret != 0)
  return ret;
 ret = start_processes();
 if(ret !=0)
  return ret;

			

			
#ifdef __WIN32__
 CloseHandle(FcpJobObject);
 WSACleanup();
#endif
 return 0;
}

  以上是“windows下的Nginx和php搭配php-cgi.exe自动关闭退出的完善办理办法[服务器安全]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
  • Windows 8调整回收站大小的办法
  • Windows8常常呈现无呼应且无法关闭的问题办理办法
  • windows 2003翻开本地用户和组提醒无权限的办理办法
  • Windows Server 2012虚拟机的导入本领
  • 若何办理Windows 8在桌面上老是显示大小写锁定和数字锁定图标的问题
  • 若何对Windows Server 2008上的ARP缓存举行管理的步骤
  • Windows8激活办法 用Skype免费打英国电池激活的办法教程(图文)
  • Windows 8怎样启用.net framework 3.5的办法介绍
  • Windows8无法更新驱动的办理办法(图文教程)
  • 平板电脑里装的Windows 8 Metro版的操作指南
  • 在Windows7中将U盘用BitLocker加密的操作步骤
  • 在固态硬盘上若何安装Windows 7
  • 本文地址: 与您的QQ/BBS好友分享!
    • 好的评价 如果您觉得此文章好,就请您
        0%(0)
    • 差的评价 如果您觉得此文章差,就请您
        0%(0)

    文章评论评论内容只代表网友观点,与本站立场无关!

       评论摘要(共 0 条,得分 0 分,平均 0 分) 查看完整评论
    Copyright © 2020-2022 www.xiamiku.com. All Rights Reserved .