PHP 程式跑在 Windows 服務上

sunrise丶發表於2019-07-12

專案在window上後臺執行Workerman,避免命令列視窗給別人關閉,並且系統重啟時自動執行專案。我一開始想的是用計劃任務來做,但是總監建議用服務或第三方軟體來控制,所以開啟了探索之路。

  • php:workerman3.5

  • 伺服器:Windows Server2008

搜尋了php的擴充套件,發現有一個擴充套件:win32service,可以利用此擴充套件生成一個執行php的服務,可以避免命令列視窗給別人關閉,同樣可以系統重啟自動執行,於是開始了摸索之路,原本以為會很順利的,但是並沒有....

從網上搜了個程式碼來使用,自己改了下..

class WinService
{
    //服務名稱
    private $name = 'forWorkerman3';
    //定義服務名稱
    private $info_name = "forWorkerman3";
    //定義php.exe存放路徑
    private $path = "E:\php\php-7.2.1-nts\php.exe";
    //定義所要執行的程式
    private $params = "E:\phpwork\process\start.php";

    public function install()
    {
        /* 註冊服務  */
        $server = win32_create_service(array(
            'service' => $this->name,
            'display' => $this->info_name,
            'path' => $this->path,
            'params' => $this->params,
        ));

        if ($server !== true) {
            return "安裝失敗" . "\t 錯誤程式碼:" . dechex($server);
        }

        return '服務建立成功!';

    }

    /* 移除服務 */
    public function uninstall()
    {
        $removeService = win32_delete_service($this->name);
        $log = '';
        switch ($removeService) {
            case 1060:
                $log = '服務不存在';
                break;
            case 1072:
                $log = '服務無法解除安裝 ';
                break;
            case 0:
                $log = "服務解除安裝成功";
                break;
            default    :
                break;
        }
        return $log;
    }

    public function restart()
    {
        /* 重啟服務 */
        $svcStatus = win32_query_service_status($this->name);

        if ($svcStatus == 1060) {
            return "服務[" . $this->name . "]未被安裝,請先安裝";

        }
        if ($svcStatus['CurrentState'] == 1) {
            return $this->start();
        }

        $stop = win32_stop_service($this->name);
        if ($stop != 0) {
            return "服務正在執行,請重試! ";
        } else {
            return $this->start();
        }
    }

    public function start()
    {
        $start = win32_start_service($this->name);
        if ($start != 0) {
            return " 服務正在執行中! ";
        }
        return " 服務已啟動! ";

    }

    public function stop()
    {
        $stop = win32_stop_service($this->name);
        if ($stop != 0) {
            return "服務未啟動";
        }
        return "服務已停止";

    }
}

$service = new WinService();

if (php_sapi_name() !== 'cli') {
    trigger_error("指令碼只能執行在cli模式下");
    exit();
}
$log = '';
switch ($argv[1]) {
    case "install" :
        $log = $service->install();
        break;
    case "uninstall" :
        $log = $service->uninstall();
        break;
    case "start":
        $log = $service->start();
        break;
    case "stop":
        $log = $service->stop();
        break;
    case "restart":
        $log = $service->restart();
        break;
    default:
        var_dump("無事發生...");
}
echo $log;

然而是我太年輕了,執行普通的php程式是沒有任何問題的,但是執行workerman卻無法正常執行。實際上測試到的結果是,在開啟服務的期間,workerman實際上是執行成功了,但是卻無法一直保持著服務開啟的狀態。找了許久的解決方法也沒找到,所以就放棄了。

在網上搜解決保持服務開啟的解決方案時候,意外發現有軟體可以幫我生成一個服務,這個軟體就是Nssm。下載好之後用命令列執行nssm.exe install <服務名稱>

NSSM 生成 Windows 服務

這個介面就是這個軟體的gui了。按照自己的需求開啟

NSSM 生成 Windows 服務

選擇自己要執行的檔案

NSSM 生成 Windows 服務

點選install service即可安裝成服務了

如果要解除安裝服務執行nssm.exe remove <服務名稱>

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章