PHP進(jìn)程守護(hù)和開機(jī)自啟

PHP守護(hù)進(jìn)程的方式

借助nohup 和& 配合使用(驗(yàn)證OK)

在命令后面加上&符合,可以讓啟動(dòng)的進(jìn)程轉(zhuǎn)到后臺(tái)運(yùn)行,而不占用控制臺(tái),控制臺(tái)還可以再運(yùn)行其它的命令。示例如下:

?While(true){

?echotime().PHP_EOL;

?sleep(3);

}

用&方式來啟動(dòng)該進(jìn)程

Php deadloop.php &

查看該進(jìn)程狀態(tài)

Ps aux | grep

這時(shí)我們可以通過fg命令讓進(jìn)程恢復(fù)到普通占用控制臺(tái)的模式

Fg

在命令之前加上nohup ,啟動(dòng)的進(jìn)程將會(huì)忽略linux的掛起信號(hào) (SIGHUP),

那什么情況下會(huì)觸發(fā)linux下SIGHUP信號(hào)呢?

SIGHUP會(huì)在以下3種情況下被發(fā)送給相應(yīng)的進(jìn)程:

1、終端關(guān)閉時(shí),該信號(hào)被發(fā)送到session首進(jìn)程以及作為job提交的進(jìn)程(即用 & 符號(hào)提交的進(jìn)程)

2、session首進(jìn)程退出時(shí),該信號(hào)被發(fā)送到該session中的前臺(tái)進(jìn)程組中的每一個(gè)進(jìn)程

3、若父進(jìn)程退出導(dǎo)致進(jìn)程組成為孤兒進(jìn)程組,且該進(jìn)程組中有進(jìn)程處于停止?fàn)顟B(tài)(收到SIGSTOP或SIGTSTP信號(hào)),該信號(hào)會(huì)被發(fā)送到該進(jìn)程組中的每一個(gè)進(jìn)程。

結(jié)合 1和2 我們知道,不管是否以 & (job方式)啟動(dòng)的進(jìn)程,關(guān)閉終端時(shí)都會(huì)收到 ?SIGHUP 信號(hào) ,那么進(jìn)程收到 SIGHUP 信號(hào)會(huì)如何處理呢?

系統(tǒng)對(duì)SIGHUP信號(hào)的默認(rèn)處理是終止收到該信號(hào)的進(jìn)程。所以若程序中沒有捕捉該信號(hào),當(dāng)收到該信號(hào)時(shí),進(jìn)程就會(huì)退出。

也就是說關(guān)閉終端進(jìn)程會(huì)收到SIGHUP信號(hào),而該信號(hào)的默認(rèn)處理方式就是結(jié)束掉該進(jìn)程,當(dāng)然我們也可以自己捕獲處理該信號(hào),或者忽略它

我們?cè)诿钚羞\(yùn)行該例程,然后直接關(guān)閉掉該shell終端窗口,然后重新打開一個(gè)終端查看這個(gè)進(jìn)程是否還在運(yùn)行:

[root@localhost php]# ps -ef | grepdeadloop.php

root????16112???? 1? 0 17:20 ???????? 00:00:00 php deadloop.php

root????16138 16115? 0 17:24 pts/4??? 00:00:00 grep deadloop.php

[root@localhost php]# cat logs.txt

pid : 16112 receive SIGHUP 信號(hào)

?

可以看到deadloop.php 仍在運(yùn)行,而其父進(jìn)程變成了init 進(jìn)程 (由于其原本父進(jìn)程退出了從而被init進(jìn)程收養(yǎng)),從寫到的文件內(nèi)容也可以看到 關(guān)閉終端進(jìn)程收到了SIGHUP 信號(hào)。其實(shí)我們不必這么麻煩,只需要使用linux提供給我們的nohup命令,但我們使用nohup啟動(dòng)進(jìn)程時(shí),進(jìn)程會(huì)忽略收到的SIGHUP信號(hào),也就不會(huì)退出了,首先去掉剛才的信號(hào)處理代碼。然后nohup運(yùn)行。

并且nohup默認(rèn)會(huì)把程序的輸出重定向到當(dāng)前目錄下的nohup.out文件,如果沒有可寫權(quán)限,則寫入$homepath/nohup.out

所以當(dāng)我們組合nohup 和 & 兩種方式時(shí),啟動(dòng)的進(jìn)程不會(huì)占用控制臺(tái),也不依賴控制臺(tái),控制臺(tái)關(guān)閉之后進(jìn)程被1號(hào)進(jìn)程收養(yǎng),成為孤兒進(jìn)程,這就和守護(hù)進(jìn)程的機(jī)制非常類似了。

nohup php deadloop.php >logs.txt2>error.txt &

其中>logs.txt 重定向標(biāo)準(zhǔn)輸出,2>error.txt重定向標(biāo)準(zhǔn)錯(cuò)誤輸出。

第二種實(shí)現(xiàn)方式(未驗(yàn)證)

就是根據(jù)守護(hù)進(jìn)程的規(guī)則和特點(diǎn)通過代碼來實(shí)現(xiàn),守護(hù)進(jìn)程最大的特點(diǎn)就是脫離了用戶終端和會(huì)話。

想要使用這種方式需要安裝

yum?install?php70w-process

$pid = pcntl_fork();

if ($pid == -1)

{

???throw new Exception('fork子進(jìn)程失敗');

}

elseif ($pid > 0)

{

???//父進(jìn)程退出,子進(jìn)程不是進(jìn)程組長(zhǎng),以便接下來順利創(chuàng)建新會(huì)話

???exit(0);

}

// 最重要的一步,創(chuàng)建一個(gè)新的會(huì)話,脫離原來的控制終端

posix_setsid();

// 修改當(dāng)前進(jìn)程的工作目錄,由于子進(jìn)程會(huì)繼承父進(jìn)程的工作目錄,修改工作目錄以釋放對(duì)父進(jìn)程工作目錄的占用。

chdir('/');

/*

?*通過上一步,我們創(chuàng)建了一個(gè)新的會(huì)話組長(zhǎng),進(jìn)程組長(zhǎng),且脫離了終端,但是會(huì)話組長(zhǎng)可以申請(qǐng)重新打開一個(gè)終端,為了避免

?*這種情況,我們?cè)俅蝿?chuàng)建一個(gè)子進(jìn)程,并退出當(dāng)前進(jìn)程,這樣運(yùn)行的進(jìn)程就不再是會(huì)話組長(zhǎng)。

?*/

$pid = pcntl_fork();

if ($pid == -1)

{

???throw new Exception('fork子進(jìn)程失敗');

}

elseif ($pid > 0)

{

???//? 再一次退出父進(jìn)程,子進(jìn)程成為最終的守護(hù)進(jìn)程

???exit(0);

}

// 由于守護(hù)進(jìn)程用不到標(biāo)準(zhǔn)輸入輸出,關(guān)閉標(biāo)準(zhǔn)輸入,輸出,錯(cuò)誤輸出描述符

fclose(STDIN);

fclose(STDOUT);

fclose(STDERR);

/*

?*處理業(yè)務(wù)代碼

?*/

while(TRUE)

{

???file_put_contents('log.txt', time().PHP_EOL, FILE_APPEND);

???sleep(5);

}

開機(jī)自啟動(dòng)

創(chuàng)建sh腳本

賦權(quán)腳本可執(zhí)行的權(quán)限

Chmod +x /usr/share/nginx/html/swoole.php

添加開機(jī)自啟動(dòng)腳本(驗(yàn)證OK)

打開/etc/rc.d/rc.local文件,在末尾添加如下內(nèi)容

echo "/home/yingshan.sh" >>/etc/rc.d/rc.local??

在centos7中,/etc/rc.d/rc.local的權(quán)限被降低了,所以需要執(zhí)行如下命令賦予其可執(zhí)行的權(quán)限

Chmod + x /etc/rc.d/rd.local

方法二(驗(yàn)證OK)

在/etc/rc.d/init.d 下創(chuàng)建test.sh 腳本

#!/bin/bash

# description: 測(cè)試開機(jī)自啟動(dòng)的php腳本

/usr/share/nginx/html/test.php

增加腳本的可執(zhí)行權(quán)限

將腳本添加到開機(jī)自啟動(dòng)項(xiàng)目中去

chkconfig test.sh on

檢查sh腳本

直接運(yùn)行報(bào)如下錯(cuò)誤

這里啊 需要添加的是執(zhí)行的腳本命令?而非腳本本身

不支持chkconfig

#!/bin/sh

#chkconfig: 2345 80 90

#description:auto_run

第一行,告訴系統(tǒng)使用的shell,所有的shell腳本都是這樣。

第二行,chkconfig后面有三個(gè)參數(shù)2345,80和90

告訴chkconfig程序,需要在rc2.d~rc5.d目錄下,創(chuàng)建名字為 S80auto_run的文件連接,連接到/etc/rc.d/init.d目錄下的的auto_run腳本。

第一個(gè)字符是S,系統(tǒng)在啟動(dòng)的時(shí)候,運(yùn)行腳 本auto_run,就會(huì)添加一個(gè)start參數(shù),告訴腳本,現(xiàn)在是啟動(dòng)模式。同時(shí)在rc0.d和rc6.d目錄下,創(chuàng)建名字為K90auto_run的文件連接,第一個(gè)字符為K,個(gè)系統(tǒng)在關(guān)閉系統(tǒng)的時(shí)候,會(huì)運(yùn)行auto_run,添加一個(gè)stop,告訴腳本,現(xiàn)在是關(guān)閉模式。

注意上面的三行是中,地二,第三行是必須的,否則在運(yùn)行chkconfig --add

auto_run時(shí),會(huì)報(bào)錯(cuò)。

Vagrant box 下的文件共享錯(cuò)誤

當(dāng)使用共享文件(夾)時(shí),系統(tǒng)開機(jī)時(shí),優(yōu)先檢測(cè)開機(jī)項(xiàng),執(zhí)行到sh腳本后,如果該腳本指定的文件在共享文件夾下面,則會(huì)提示無法打開該文件,實(shí)際上是因?yàn)槲募蚕硐到y(tǒng)尚未同步,因此找不到該文件,避免這種情況,可以將腳本放在服務(wù)器上。

另外說明下,使用vagrant shutdown后所有的內(nèi)在配置會(huì)丟失,而reboot則不會(huì)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容