PHPデーモンの2つの方式を詳しく解説

墨辰丷
リリース: 2023-03-26 13:22:01
オリジナル
1988 人が閲覧しました

この記事では、PHP デーモンの 2 つの一般的な実装方法を主に紹介し、具体的な例に基づいて PHP デーモンの原理、関連する実装方法、および運用上の注意事項を分析します。

最初の方法は、nohup と & を一緒に使用することです。

コマンドの後にアンパサンドを追加すると、コンソールを占有することなく、開始されたプロセスをバックグラウンドで実行できます。 ここでは、while 無限ループを使用して説明します。

<?php
while(true){
    echo time().PHP_EOL;
    sleep(3);
}
ログイン後にコピー

& メソッドを使用してプロセスを開始します

[root@localhost php]# php deadloop.php &
[1] 3454
[root@localhost php]# ps aux | grep 3454
root   3454 0.0 0.8 284544 8452 pts/0  T  18:06  0:00 php deadloop.php
root   3456 0.0 0.0 103316  896 pts/0  S+  18:08  0:00 grep 3454
[1]+ Stopped         php deadloop.php
[root@localhost php]#
ログイン後にコピー

このとき、コンソールは他のコマンドを実行することもできます。プロセスを通常のコンソール占有モードに戻します。

[root@localhost php]# fg
php deadloop.php
1470996682
1470996685
1470996688
1470996691
ログイン後にコピー

上記は & コマンドの簡単な紹介です

別のコマンドを見てみましょう

コマンドの前に nohup を追加すると、開始されたプロセスは Linux ハング信号 (SIGHUP) を無視します。 Linux での SIGHUP シグナルは、Baidu Encyclopedia から引用したものです:

SIGHUP は、次の 3 つの状況で、対応するプロセスに送信されます:

1. ターミナルが閉じられると、シグナルが送信されます。セッションの最初のプロセスとジョブとして送信されたプロセス (つまり、& 記号で送信されたプロセス)

2. セッションの最初のプロセスが終了すると、セッション内のフォアグラウンド プロセス グループ内のすべてのプロセスにシグナルが送信されます。 3. 親プロセスが終了すると、そのプロセスグループが孤立プロセスグループで、プロセスグループ内のプロセスが停止した場合(SIGSTOP または SIGTSTP シグナルを受信した場合)、プロセスグループ内のすべてのプロセスにシグナルが送信されます。

1 と 2 を組み合わせると、プロセスが & (ジョブ モード) で開始されたかどうかに関係なく、端末を閉じるときに SIGHUP シグナルが受信されることがわかります。それでは、プロセスは SIGHUP シグナルを受信したときに何をしますか? Baidu Encyclopedia から引用した同じ文を参照してください


SIGHUP シグナルのシステムのデフォルトの処理は、シグナルを受信するプロセスを終了することです。したがって、プログラムでシグナルがキャプチャされていない場合、シグナルを受信した時点でプロセスは終了します。

つまり、ターミナルプロセスを閉じると SIGHUP シグナルが受信され、このシグナルのデフォルトの処理方法は、プロセスを終了することです。もちろん、シグナルを自分で処理することも、無視することもできます。上記のループの例に少し改良を加えてみましょう

<?php
declare(ticks = 1);
pcntl_signal(SIGHUP, function(){
    // 这地方处理信号的方式我们只是简单的写入一句日志到文件中
    file_put_contents(&#39;logs.txt&#39;, &#39;pid : &#39; . posix_getpid() . &#39; receive SIGHUP 信号&#39; . PHP_EOL);
});
while(true){
    echo time().PHP_EOL;
    sleep(3);
}
ログイン後にコピー

ただし、プロセスを起動するのに Linux が提供する nohup コマンドを使用するだけです。ターミナルを閉じると、プロセスは SIGHUP シグナルを無視し、終了しません。まず、先ほどのシグナル処理コードを削除します。次に、nohup を実行します。

[root@localhost php]# nohup php deadloop.php
ログイン後にコピー

nohup: 入力を無視し、出力を「nohup.out」に追加します

そして、書き込み権限がない場合、nohup はデフォルトでプログラムの出力を現在のディレクトリの nohup.out ファイルにリダイレクトします。 、その後 $homepath/nohup.out と書き込みます

[root@localhost php]# ls
cmd.sh deadloop.php getPhoto.php nohup.out pics
[root@localhost php]# tail -f nohup.out
1470999772
1470999775
1470999778
1470999781
1470999784
1470999787
1470999790
1470999793
1470999796
1470999799
1470999802
ログイン後にコピー

この時点ではプロセスは終了しませんが、プロセスを作成した親プロセスが終了したため、孤立プロセス (ppid=1) になります。

[root@localhost ~]# ps -ef | grep 3554
root   3554 3497 0 19:09 pts/0  00:00:00 php deadloop.php
root   3575 3557 0 19:10 pts/1  00:00:00 grep 3554
[root@localhost ~]# ps -ef | grep 3554
root   3554   1 0 19:09 ?    00:00:00 php deadloop.php
root   3577 3557 0 19:10 pts/1  00:00:00 grep 3554
[root@localhost ~]#
ログイン後にコピー

結論:

したがって、nohup メソッドと & メソッドを組み合わせると、開始されたプロセスはコンソールを占有せず、コンソールが閉じられた後、プロセスに依存しません。 .1 になり、孤立プロセスになりますが、これはデーモン プロセスのメカニズムと非常によく似ています。

[root@localhost php]# nohup php deadloop.php >logs.txt 2>error.txt &
[1] 3612
[root@localhost php]# ps -ef |grep 3612
root   3612 3557 0 19:18 pts/1  00:00:00 php deadloop.php
root   3617 3557 0 19:19 pts/1  00:00:00 grep 3612
[root@localhost php]#
ログイン後にコピー

ここで、>logs.txt は標準出力をリダイレクトし、2>error.txt は標準エラー出力をリダイレクトします。

上記は最初の実装方法の紹介です。

2つ目の実装方法は、デーモンプロセスのルールや特性に合わせてコードで実装する方法です

デーモンプロセスの最大の特徴は、ユーザー端末とセッション

から分離されていることです。実装されたコード。主要な箇所にコメントが含まれています。

<?php
$pid = pcntl_fork();
if ($pid == -1)
{
  throw new Exception(&#39;fork子进程失败&#39;);
}
elseif ($pid > 0)
{
  //父进程退出,子进程变成孤儿进程被1号进程收养,进程脱离终端
  exit(0);
}
// 最重要的一步,让该进程脱离之前的会话,终端,进程组的控制
posix_setsid();
// 修改当前进程的工作目录,由于子进程会继承父进程的工作目录,修改工作目录以释放对父进程工作目录的占用。
chdir(&#39;/&#39;);
/*
 * 通过上一步,我们创建了一个新的会话组长,进程组长,且脱离了终端,但是会话组长可以申请重新打开一个终端,为了避免
 * 这种情况,我们再次创建一个子进程,并退出当前进程,这样运行的进程就不再是会话组长。
 */
$pid = pcntl_fork();
if ($pid == -1)
{
  throw new Exception(&#39;fork子进程失败&#39;);
}
elseif ($pid > 0)
{
  // 再一次退出父进程,子进程成为最终的守护进程
  exit(0);
}
// 由于守护进程用不到标准输入输出,关闭标准输入,输出,错误输出描述符
fclose(STDIN);
fclose(STDOUT);
fclose(STDERR);
/*
 * 处理业务代码
 */
while(TRUE)
{
  file_put_contents(&#39;log.txt&#39;, time().PHP_EOL, FILE_APPEND);
  sleep(5);
}
ログイン後にコピー
関連する推奨事項:

PHP デーモン化の実装方法

php の 2 つのデーモン メソッド

Linux での PHP バックグラウンド デーモンの実装環境方法

以上がPHPデーモンの2つの方式を詳しく解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!