a我考网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 145|回复: 3

[红旗认证] 用PHP守护Linux/Unix进程

[复制链接]
发表于 2012-8-4 12:16:06 | 显示全部楼层 |阅读模式
 [ 起源 ]Linux/Unix下守护进程(Daemon)大家都知道,比如我们常用的httpd、mysqld等等,就是常驻内存运行的程序,类似于Windows下的服务。一般守护进程都是使用C/C++来写,就是通过fork生成子进程,当前台shell下的父进程被杀掉,子进程就转到后台运行,为了不在终端产生输出信息,就通过syslog等函数来写日志文件。
' |' E2 s) L8 N  我们知道php是脚本语言,通过php的脚本引擎来执行,所以要做成守护进程比较麻烦,我们今天就来结合Unix/Linux的命令来实现我们守护进程的功能。
5 z4 V4 N( Y; O( y" K  [ 原理 ]Unix中的nohup命令的功能就是不挂断地运行命令,同时nohup把程序的所有输出到放到当前目录的nohup.out文件中,如果文件不可写,则放到/nohup.out 文件中。那么有了这个命令以后,我们的php程序就写程shell脚本,使用循环来让我们的脚本一直运行,那么不管我们终端窗口是否关闭,都能够让我们的php脚本一直运行。当然,当我们的php进程被杀或者我们的操作系统重启了,自然就会中止了。$ c" S" Q# Z% T* t: e5 J* I  V/ X
  [ 功能 ]肯定会问,让我们的php脚本做了守护进程又有什么用处呢?当然有,比如最典型的作用,能够基本的替代cron的功能,比如我们需要定期实行的某些操作,完全可以交给它来做,不再需要cron,当然,如果服务器重启就没有办法了,不过,一般的Unix服务器不是那么容易重启的。另外,我们还可以做一个简单的服务器端的功能,比如做一个能够Telnet过去的服务器,嘿嘿,可以做成一个小后门,不过这样实现稍微有点复杂。
" r5 k  i/ ^, b  [ 实践 ]例子一:自动生成文件- z$ r2 p' D" J5 T' t$ i
  我们现在来做两个例子来证明我们上面的说法。首先第一个是每个三十秒自动生成一个文件,永远执行下去。" p) `/ ?$ ]. s9 W+ R$ A/ T9 M* z
  首必须确保操作系统是Unix或者Linux,比如可以是FreeBSD、Redhat、Fedora或者SUSE什么的。然后我们必须确保我们的php脚本引擎是在 /usr/local/php/bin/php,具体路径可以按照你实际路径来写,如果没有脚本引擎,请自行安装。7 p+ I  K/ f9 l4 h% l; ]0 K
  比如当前目录是 /home/heiyeluren/,那么我们使用vi或者其他编辑器编写一个叫做php_daemon1.php的文件:: j+ h) M2 F* k
  $ vi php_daemon1.php: S; q0 m' M5 ^+ R7 O7 W
  然后写入如下代码:
8 W" ?7 [1 H( ~2 |8 m' V  #! /usr/local/php/bin/php; r" J- g5 q0 B2 {9 i
  " O$ e, P( M; N+ m. h3 i
  然后保存并且退出vi,然后赋予php_daemon1.php文件可执行权限:( O& ^2 E, [. I* K4 ?8 r
  $ chmod +x /home/heiyeluren/php_daemon1.php* [* |4 f, c6 h5 D$ c
  然后再让我们的脚本再后台执行,执行如下命令:6 J- z- m% o$ U: s2 Y, c
  $ nohup /home/heiyeluren/php_daemon1.php &
8 ^! N% n  S. K( E6 `  记得最后加上 & 符号,这样才能够跑到后台去运行,执行上述命令后出现如下提示:
+ Y) z' Z  V6 I2 ~- H$ |  [1] 82480
+ w8 t1 m5 Z- w1 h7 z- f: G  appending output to nohup.out
1 T( Q  v6 ]  x  再回后车后将出现shell提示符。那么上面的提示就是说,所有命令执行的输出信息都会放到 nohup.out文件中,这个上面已经讲了。然后执行上面命令后,我们每个三十秒在当前目录就会看到多出以test_开头的文件,比如:test_1139901144.txt test_1139901154.txt等等文件,那么就证明我们的程序已经再后台运行了。
2 ]6 I5 R+ L' N  那么我们如何终止程序的运行呢?最好办法就是重启操作系统,呵呵,当然,这是不可取的,我们可以使用kill命令来杀掉这个进程,杀进程之前自然后知道进程的PID号,就是Process ID,使用ps命令就能够看到了。
7 ^- f( O. J6 G+ A; m  $ ps
回复

使用道具 举报

 楼主| 发表于 2012-8-4 12:16:07 | 显示全部楼层

用PHP守护Linux/Unix进程

  PID TT STAT TIME COMMAND; J# G! S& F) O4 x
  82374 p3 Ss 0:00.14 -bash (bash)# t* G* I) O# A, L) M& W- v
  82510 p3 S 0:00.06 /usr/local/php/bin/php /home/heiyeluren/php_daemon1.php: D+ _9 F; @# G
  82528 p3 R+ 0:00.00 ps/ b' n% B6 P" R6 i1 P
  上面我们已经看到了我们的php的进程id是:82510 ,于是我们再执行kill命令:
, i. n) t$ F$ v" H$ t5 \  $ kill -9 825108 n6 i1 A# A. }+ X
  [1]+ Killed nohup /home/heiyeluren/php_daemon1.php
& g" h; }  o# b' _/ Y) f  看到这么提示就明白这个进程被杀了,再ps,就会发现没有了:, B8 U" `& e2 S
  $ ps1 J  \, m9 u6 b
  PID TT STAT TIME COMMAND
/ l* F0 w  C7 y9 b3 ], q: v- b+ W  82374 p3 Ss 0:00.17 -bash (bash)8 v; o2 Q( I/ H9 d9 t% N
  82535 p3 R+ 0:00.00 ps
6 o  b. J  s; [  如果直接ps命令无法看到进程,那么就使用 ps & apos 两个结合命令来查看,一定能够看到进程。- C4 @* o) L7 w9 d8 \) B
  再上面的基础上进程扩展,能够做成属于自己的cron程序,那就不需要cron啦,当然,这只是一种方式 例子二:服务器端的守护进程* q; c( G  p! o& k
  这个例子跟网络有关,大致就是模拟使用php做服务器端,然后一直后台运行,达到服务器端Daemon的效果。
5 m" B3 \& a: Y8 _  继续在我们的主目录下:/home/heiyeluren,编辑文件php_daemon2.php:) u- V6 }+ i4 u! ~' u; g! X1 j
  $ vi php_daemon2.php3 P! v# o- `) r- ?" C8 p
  输入如下代码(代码来自PHP手册,我进行了修改注释):& Z) f# L) [, h; e1 V. f
  #! /usr/local/php/bin/php* L# [) A; H# u( S, s$ D2 \& _& k5 L2 x
  
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-8-4 12:16:08 | 显示全部楼层

用PHP守护Linux/Unix进程

  /* 监听Socket连接 */
+ f+ ]& P5 X6 @6 @+ P* {  if (($ret = socket_listen($sock, 5)) < 0) {1 c9 w0 ^% ]- C" @+ s
  echo "socket_listen() failed: reason: " . socket_strerror($ret) . "\n";
0 }- B8 [4 R. U  }# F& n$ d9 ?' h# j0 ^) V
  /* 永远循环监接受用户连接 */
6 S0 F3 w, {/ l0 l  do {
8 ^3 ~' |1 G1 g9 K9 `  if (($msgsock = socket_accept($sock)) < 0) {' L# h& e2 q! C
  echo "socket_accept() failed: reason: " . socket_strerror($msgsock) . "\n";
6 X8 ]' L5 }- W# Z  C3 g  break;1 `# J+ a+ m+ |! k/ o4 p/ u
  }7 o( q# X- r" b1 z2 b: p
  /* 发送提示信息给连接上来的用户 */
0 \5 o5 e% M5 F$ U' ~  $msg = "==========================================\r\n" .
. N" q6 U2 g2 K6 N, c! y  z3 O  " Welcome to the PHP Test Server. \r\n\r\n".! A( {) T( t1 ?
  " To quit, type ’quit’. \r\n" .' f' i) Y: z2 t' g+ y1 N* x7 P# e: r, q1 ]
  " To shut down the server type ’shutdown’.\r\n" .: f9 r$ U' T) r. j, o+ A
  " To get help message type ’help’.\r\n" ./ ^' l4 D; B" v% [/ w/ R
  "==========================================\r\n" .  W0 c* K0 K3 i) s
  "php> ";
+ u% M% u  c3 S! k* S: |7 w8 R  socket_write($msgsock, $msg, strlen($msg));
" d. K( W2 z) ^6 E  do {8 P" e7 B5 n, B9 Z# a# l+ I. Y2 `. d
  if (false === ($buf = socket_read($msgsock, 2048, PHP_NORMAL_READ))) {' H: g/ i% h1 [8 t/ E' [! C* i
  echo "socket_read() failed: reason: " . socket_strerror($ret) . "\n";" ^6 }8 k+ p/ I' O0 G% ~
  break 2;1 t3 i6 O8 E$ y; _4 S6 b
  }
0 z5 \- s- C$ v: T6 l7 G3 r/ g/ x  if (!$buf = trim($buf)) {
, r9 Q3 w3 r' Y& T- B6 A2 ~* y  continue;
3 k" A' u& n  p8 N, ~/ _  }2 ]3 J6 K& `) l9 y( k3 p
  /* 客户端输入quit命令时候关闭客户端连接 */
, r& R, D! C& t3 f2 Q5 v9 S' O  if ($buf == ’quit’) {
! r3 y* q* D% L' G1 r1 t1 l  break;
- D, ^. [" m$ n0 N& o8 }0 d4 M  }
; a* ^4 c* V  R5 y; `. ]0 K  /* 客户端输入shutdown命令时候服务端和客户端都关闭 */
- S. s+ _" K* B1 i5 Q+ p! c  if ($buf == ’shutdown’) {
7 T2 S9 u9 P$ M( o  socket_close($msgsock);5 I% p% g' c2 c. L. ?
  break 2;
. ^7 V4 A: A% J( d% i- r  }1 K% _1 b! x0 x( C6 T: p0 [
  /* 客户端输入help命令时候输出帮助信息 */# G, [$ P5 F! P
  if ($buf == ’help’) {1 z. x( k6 o% z$ Y5 x0 Q
  $msg = " PHP Server Help Message \r\n\r\n".
9 f# q7 ~' z1 R  E. c7 s! ?5 m  " To quit, type ’quit’. \r\n" .
) D( J: h) I! E- e1 C  " To shut down the server type ’shutdown’.\r\n" .
7 F8 k9 R  ^* U; Y" }5 g" v  " To get help message type ’help’.\r\n" .
- q$ K$ {2 k# b" {; c5 L/ B& t  "php> ";
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-8-4 12:16:09 | 显示全部楼层

用PHP守护Linux/Unix进程

  socket_write($msgsock, $msg, strlen($msg));
3 w# o+ }- p8 i- h  continue;! M+ q; |$ a1 t- c3 r6 K
  }# e" M0 [4 b+ G! v3 p: L
  /* 客户端输入命令不存在时提示信息 */. M) Z; ?" r% m0 i5 F3 _
  $talkback = "PHP: unknow command ’$buf’.\r\nphp> ";
! l+ X" t9 y! j& G  socket_write($msgsock, $talkback, strlen($talkback));1 t8 I2 u9 L" i( X; Q& e, ^9 y
  echo "$buf\n";
/ p$ x' C3 Y5 u, N; f( i0 O  } while (true);
4 t" G- |4 j! U% _  socket_close($msgsock);6 Z  ~6 m/ f  O& v8 `' @* u
  } while (true);6 o; h; n- h; x' A) W( \
  /* 关闭Socket连接 */
) }  \: u( `! G. N- A  socket_close($sock);) f# s% f! t0 {: F
  ?>- `0 l' ?0 ]$ l5 N4 r' O0 {
  保存以上代码退出。" m3 K$ v8 {6 m
  上面的代码大致就是完成一个类似于Telnet服务器端的功能,就是当服务器端运行该程序的时候,客户端能够连接该服务器的10000端口进行通信。! Y% [) T$ D$ b3 Z# _/ ~8 [/ j- r7 H, i$ Z
  加上文件的可执行权限:* c1 Y% I! P  J! [' K: R
  $ chmod +x /home/heiyeluren/php_daemon2.php) `9 o/ M7 _. P+ Y: k
  在服务器上执行命令:
* `1 }2 b7 I: _. ^+ t  $ nohup /home/heiyeluren/php_daemon2.php &: u# ~8 N' E, V+ E
  就进入了后台运行,我们通过Windows的客户端telnet上去:. P0 f% K, D7 t; ]
  C:\>telnet 192.168.0.1 10000
) `8 ~: b, D9 i' N  o  如果提示:
) w$ o9 A, V9 y2 q5 J; O6 ~/ ]  正在连接到192.168.0.188...不能打开到主机的连接, 在端口 10000: 连接失败
8 H% `. c# M2 u. `( u  则说明服务器端没有开启,或者上面的程序没有正确执行,请检查php是否 --enable-sockets 功能。如果提示:
5 {2 b  m8 ]6 I/ h. X% z) [3 N  ==========================================) U' M" j# M" ^) q3 {
  Welcome to the PHP Test Server.2 G5 a+ i9 n# d& U
  To quit, type ’quit’.& w7 `8 c% `7 I/ H/ V
  To shut down the server type ’shutdown’.2 ^8 c; P: b: W* Q5 r  Q4 J
  To get help message type ’help’., Q" ^9 p2 x; [1 D; }
  ==========================================
! f* `9 t2 B2 K$ ~  php>) H5 o5 u9 @$ h0 q
  则说明顺利连接上了我们的PHP写的服务器端守护进程,在php>提示符后面能够执行help、quit、shutdown等三个命令,如果命令输入不是这三个,则提示:
7 b5 C3 |: G/ s  php> asdf
% p4 p1 |, u' C  Y- F- O+ k1 @* j  PHP: unknow command ’asdf’.
" q% w9 n7 J6 U9 D& H  }  执行help命令可以获取帮助
* J( Y0 b& l0 o4 _  php> help( H6 h" y, |- U1 m2 s; B+ X' U
  PHP Server Help Message1 V$ i2 |& C+ @. w9 E
  To quit, type ’quit’.# j& C* H1 }: g2 K: L
  To shut down the server type ’shutdown’.2 j' o8 J) T7 h! o& R3 q- C/ ?
  To get help message type ’help’.
- l! B3 F0 l3 V) a  这个服务器端就不介绍了,可以自行扩展。! ~- B2 K6 L: o( m. z. u
  杀进程跟例子一类似。
' N. f! H. n! `  D  [ 总结 ]通过以上学习,我们知道php也可以做守护进程,如果设计的好,功能也会比较强大,不过我们这里只是学习而已,可以自行研究更新。- `0 `. e. m% K
  本文参考了php中文手册,多看手册,对自己非常有好处。</p>
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Woexam.Com ( 湘ICP备18023104号 )

GMT+8, 2024-5-3 05:31 , Processed in 0.350111 second(s), 27 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表