[起源] Linux/Unix でよく使われる httpd や mysqld などのデーモン プロセス (Daemon) は誰もが知っており、Windows でのサービスと同様に常駐メモリで実行されるプログラムです。一般に、デーモン プロセスは C/C++ で記述されており、現在のシェルの下にある親プロセスが強制終了されると、端末上で出力情報を生成しないように子プロセスがバックグラウンドで実行されます。 、ログ ファイルの書き込みには syslog などの関数が使用されます。
php はスクリプト言語であり、php スクリプト エンジンを通じて実行されるため、デーモン プロセスを作成するのは面倒であることがわかっています。今日は、Unix/Linux コマンドを組み合わせてデーモン プロセスの機能を実現します。
[原則] Unix の nohup コマンドの機能は、ファイルがカレント ディレクトリの nohup.out ファイルにある場合、同時にプログラムの出力をすべてハングアップせずに実行することです。書き込み不可なので、<ユーザー ホーム ディレクトリ> /nohup.out ファイルに配置されます。したがって、このコマンドを実行した後、php プログラムはシェル スクリプトを作成し、ループを使用してスクリプトを実行し続けます。その後、ターミナル ウィンドウが閉じているかどうかに関係なく、php スクリプトは実行し続けることができます。もちろん、php プロセスが強制終了されるか、オペレーティング システムが再起動されると、プロセスは自然に終了します。
[機能] PHP スクリプトをデーモンにして何の役に立つのかと、きっと疑問に思うでしょう。もちろん、定期的に実行する必要がある特定の操作を cron で実行できる、最も典型的な関数などもあります。ただし、一般的な Unix サーバーはそう簡単には再起動できません。その他、Telnetが使えるサーバーを作るなど、簡単なサーバー側の機能も作ることができますが、ちょっと実装が複雑です。
[実践] 例 1: ファイルを自動的に生成する 上記のステートメントを証明するために 2 つの例を実行します。まず、1つ目は30秒ごとにファイルを自動生成して永久に実行するというものです。
まず、オペレーティング システムが Unix または Linux (FreeBSD、Redhat、Fedora、SUSE など) であることを確認する必要があります。次に、PHP スクリプト エンジンが /usr/local/php/bin/php にあることを確認する必要があります。スクリプト エンジンがない場合は、実際のパスに応じてインストールしてください。
たとえば、現在のディレクトリが /home/heiyeluren/ の場合、vi または他のエディタを使用して php_daemon1.php というファイルを作成します。
$ vi php_daemon1.php
次に、次のコードを記述します。
#!/usr/local/php/bin/php
<?
set_time_limit(0);
その間(1)
{
@fopen("test_".time().".txt","w");
睡眠(30);
}
?>
次に、vi を保存して終了し、php_daemon1.php ファイルに実行権限を与えます。
$ chmod +x /home/heiyeluren/php_daemon1.php
次に、スクリプトをバックグラウンドで実行し、次のコマンドを実行します。
$ nohup /home/heiyeluren/php_daemon1.php &
上記のコマンドを実行した後、次のプロンプトが表示されるように、最後に & 記号を忘れずに追加してください。
[1] 82480
出力を nohup.out に追加する
車に戻るとシェルプロンプトが表示されます。したがって、上記のヒントは、すべてのコマンド実行の出力情報が、上で説明した nohup.out ファイルに配置されることを意味します。上記のコマンドを実行すると、現在のディレクトリに test_1139901144.txt test_1139901154.txt などのファイルが 30 秒ごとに表示され、プログラムがバックグラウンドで実行されていることがわかります。
では、プログラムの実行を終了するにはどうすればよいでしょうか?最善の方法は、オペレーティング システムを再起動することです。もちろん、これはお勧めできません。プロセスを終了する前に、プロセスの PID 番号がわかっています。 ID を確認するには ps コマンドを使用します。
$ps
PID TT 統計時間コマンド
82374 p3 Ss 0:00.14 -bash (バッシュ)
82510 p3 S 0:00.06 /usr/local/php/bin/php /home/heiyeluren/php_daemon1.php
82528 p3 R+ 0:00.00 ps
上で、php のプロセス ID が 82510 であることがわかりました。そのため、kill コマンドを実行します。
$ キル -9 82510
[1]+ nohup /home/heiyeluren/php_daemon1.php を強制終了しました
このプロンプトが表示されると、プロセスが強制終了されたことがわかります。もう一度 ps を実行すると、プロセスがなくなっていることがわかります。
$ps
PID TT 統計時間コマンド
82374 p3 Ss 0:00.17 -bash (バッシュ)
82535 p3 R+ 0:00.00 ps
ps コマンドでプロセスを直接表示できない場合は、ps コマンドと apos コマンドを 2 つ組み合わせて使用すると、確実にプロセスを表示できるようになります。
上記のプロセスに基づいて、プロセスを拡張して独自の cron プログラムを作成できます。もちろん、これは単なる 1 つの方法です。この例はネットワークに関連しています。サーバー側で大まかにシミュレートされ、サーバー側デーモンの効果を実現するためにバックグラウンドで実行されます。
ホーム ディレクトリ /home/heiyeluren に進み、ファイル php_daemon2.php を編集します。
$ vi php_daemon2.php
次のコードを入力します (コードは PHP マニュアルからのもので、コメントを変更しました)。
#!/usr/local/php/bin/php
<?php
/* http://www.knowsky.com/php.asp設定ではエラーは表示されません*/
エラー報告(0);
/* スクリプトのタイムアウトは無限です*/
set_time_limit(0);
/* 固定クリアを開始します */
ob_implicit_flush();
/* このマシンの IP と開く必要があるポート */
$アドレス = '192.168.0.1';
$ポート = 10000;
/* ソケットを生成します */
if (($sock =socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) < 0) {
echo "socket_create() が失敗しました: 理由: " 。socket_strerror($sock) "n";
}
/* IP アドレスとポートをバインドします */
if (($ret =socket_bind($sock, $address, $port)) < 0) {
echo "socket_bind() が失敗しました: 理由: " 。socket_strerror($ret) "n";
}
/* ソケット接続を監視します */
if (($ret =socket_listen($sock, 5)) < 0) {
echo "socket_listen() が失敗しました: 理由: " 。socket_strerror($ret) "n";
}
/*ユーザー接続を監視するために永久にループします*/
する {
if (($msgsock =ソケット_accept($sock)) < 0) {
echo "socket_accept() が失敗しました: 理由: " 。socket_strerror($msgsock) "n";
壊す;
}
/* 接続しているユーザーにプロンプト情報を送信します*/
$msg = “==========================================rn 「。」
「PHP テスト サーバーへようこそ。rnrn」。
" 終了するには、「quit」と入力します。rn" .
"サーバーをシャットダウンするには、「shutdown」と入力します。rn" 。
"ヘルプ メッセージを表示するには、「help」と入力してください。rn" 。
"==========================================rn" 。
"php>";
ソケット書き込み($msgsock, $msg, strlen($msg));
する {
if (false === ($buf =socket_read($msgsock, 2048, PHP_NORMAL_READ))) {
echo "socket_read() が失敗しました: 理由: " 。socket_strerror($ret) "n";
休憩2;
}
if (!$buf = トリム($buf)) {
続く;
}
/*クライアントが終了コマンドを入力すると、クライアント接続を閉じます*/
if ($buf == '終了') {
壊す;
}
/* クライアントが shutdown コマンドを入力すると、サーバーとクライアントの両方がシャットダウンされます*/
if ($buf == 'シャットダウン') {
ソケットクローズ($msgsock);
休憩2;
}
/* クライアントが help コマンドを入力したときにヘルプ情報を出力します*/
if ($buf == 'ヘルプ') {
$msg = “PHP サーバーのヘルプ メッセージ rnrn”。
" 終了するには、「quit」と入力します。rn" .
"サーバーをシャットダウンするには、「shutdown」と入力します。rn" 。
"ヘルプ メッセージを表示するには、「help」と入力してください。rn" 。
"php>";
ソケット書き込み($msgsock, $msg, strlen($msg));
続く;
}
/*クライアント入力コマンドが存在しない場合のプロンプトメッセージ*/
$talkback = “PHP: 不明なコマンド '$buf'.rnphp> “;
socket_write($msgsock, $talkback, strlen($talkback));
「$bufn」をエコーします。
while (true);
ソケットクローズ($msgsock);
while (true);
/* ソケット接続を閉じる */
ソケットクローズ($sock);
?>
上記のコードを保存して終了します。
上記のコードは、Telnet サーバー側と同様の機能を大まかに完成させます。つまり、サーバー側がプログラムを実行すると、クライアントは通信のためにサーバーの 10000 ポートに接続できます。
実行可能権限をファイルに追加します。
$ chmod +x /home/heiyeluren/php_daemon2.php
サーバー上でコマンドを実行します。
$ nohup /home/heiyeluren/php_daemon2.php &
バックグラウンド操作に入り、Windows クライアントの Telnet を経由して進みます。
C:>テルネット 192.168.0.1 10000
プロンプトが表示された場合:
192.168.0.188 に接続しています...ポート 10000 でホストへの接続を開くことができません: 接続が失敗した場合は、サーバーが開かれていない、または上記のプログラムが正しく実行されていないことを意味します。php に –enable が設定されているかどうかを確認してください。 -ソケット機能。プロンプトが表示された場合:
=========================================
PHP テスト サーバーへようこそ。
終了するには、「quit」と入力します。
サーバーをシャットダウンするには、「shutdown」と入力します。
ヘルプ メッセージを表示するには、「help」と入力します。
=========================================
php>
これは、php> プロンプトの後に、help、quit、shutdown などの 3 つのコマンドを実行できることを意味します。コマンド入力がこれら 3 つ以外の場合は、次のプロンプトが表示されます。
php>asdf
PHP: 不明なコマンド 'asdf'。
help コマンドを実行してヘルプを表示します php> help
PHP サーバーのヘルプ メッセージ
終了するには、「quit」と入力します。
サーバーをシャットダウンするには、「shutdown」と入力します。
ヘルプ メッセージを表示するには、「help」と入力します。
このサーバー側は導入されず、自分で拡張できます。
プロセスの強制終了は例 1 と似ています。
[まとめ] 上記の学習を通じて、PHP が適切に設計されていれば、機能がさらに強力になることがわかりました。ただし、ここでは学習しただけなので、自分で調べて更新することもできます。 。
この記事では PHP の中国語マニュアルを参照しています。マニュアルをもっと読むと非常に役に立ちます。