2016-07-10 82 views
-1

我試圖啓動棘輪的chat-server.php文件,該文件需要從php文件啓動套接字服務器,以便每當客戶端訪問頁面服務器啓動,但沒有發生。這chat-server.php文件需要從終端運行,但我試圖在用戶訪問時從主頁面運行它。如何讓腳本在後臺運行 - 不工作

文件結構

./index.php

./config.php

./vendor/(all供應商文件)

./src/MyApp /Chat.php

./js/app.js

./inc/connect.php < --database連接文件

./inc/send-message.php

./inc/startServer.php

./inc/bg。 PHP

./inc/serverStatus.txt

./css/index.css

./css/reset.css

./bin/chat-server.php

的config.php

<?php 
    include_once ("./inc/startServer.php"); 
?> 

聊天server.php

<?php 

    use Ratchet\Server\IoServer; 
    use Ratchet\Http\HttpServer; 
    use Ratchet\WebSocket\WsServer; 
    use MyApp\Chat; 


    if(isset($startNow)){ 

      require dirname(__DIR__) . '/vendor/autoload.php'; 

      $server = IoServer::factory(
       new HttpServer(
        new WsServer(
         new Chat() 
        ) 
       ), 
       8080 
      ); 

      $server->run(); 

    } 

?> 

bg.php

<?php 
    $startNow = 1; 
    include_once ("../bin/chat-server.php"); 
?> 

startServer.php

<?php 

$statusFile = dirname(__FILE__).'/serverStatus.txt'; 
$status = file_get_contents($statusFile); 
if($status == "0"){ 

     function execInBackground($cmd) { 
       if(substr(php_uname(), 0, 7) == "WINDOWS") { 
        pclose(popen('start /B ' . $cmd, 'r')); 
        file_put_contents($statusFile, 1); 
       } 
       else { 
        exec($cmd . ' > /dev/null &'); 
        file_put_contents($statusFile, 1); 
       } 
     } 

     execInBackground("php " . dirname(__FILE__) . "/bg.php"); 

} 

?>

serverStatus.txt

它的默認值已被設置爲

注意:相應地更新了代碼,但現在仍然不起作用。

我對重新啓動服務器以避免任何故障或在所有客戶端離開時如何關閉服務器沒有任何意見。

+0

我真的不知道爲什麼這個問題是downvote,但仍然感謝它。 – Ayan

+0

您正在爲每個客戶啓動一個新服務器?爲什麼你需要手動啓動服務器而不是在後臺運行?這個問題只是尖叫XY問題。 – PeeHaa

+0

@PeeHaa,不,這個代碼應該只爲所有的客戶端啓動一個服務器。看看,有關於服務器狀態的檢查。 – spirit

回答

1

當包括使用相對路徑你必須記住,他們是相對於當前運行文件,不僅僅是當前文件文件。

在你的情況。當您訪問index.php幷包括其中config.php,然後從startServer.php這一切都可以,因爲您包括./inc/startServer.php這是正確的,相對於index.php
但是,如果包含../inc/serverStatus.txt,這是不正確的,因爲您仍在運行index.php,並且相對路徑會解析爲/../inc/serverStatus.txt換句話說,您嘗試訪問的文件比您的DOCUMENT_ROOT高一級。所以你永遠不會進入你的if聲明。
您可以使用一個__FILE__常量,該常數總是會被解析爲當前文件的絕對路徑。所以,你可以改變你的$statusFile

$statusFile = dirname(__FILE__) . '/serverStatus.txt'; 

接下來的事情是關於你的exec()popen(pclose())命令。如果要執行某個不在PATH環境變量中的命令,那麼您的文件的絕對路徑必須爲必須爲。因爲你不知道從哪個文件夾開始。它可能從Apache家庭目錄開始,也可能從用戶的家庭目錄開始。這取決於您的PHP的設置是sapi模塊還是fcgi。無論如何,你需要改變你的execInBackground()

execInBackground("php " . dirname(__FILE__) . "/bg.php"); 

而在你的命令添加一些空間,這樣的:

pclose(popen('start /B ' . $cmd, 'r')); 
exec($cmd . ' > /dev/null &'); 

這樣你不會有可能發生的一些奇怪的錯誤。

在你bg.php你需要改變當前的工作目錄,如:

<?php 
    $startNow = 1; 
    chdir(dirname(__FILE__)); 
    include_once ("../bin/chat-server.php"); 
?> 

這樣,PHP會發現chat-server.php無論從哪個文件夾中,您將運行它的事情。

順便說一句,你是怎麼計劃停止你的服務器? =)


UPDATE:你也有你的功能execInBackground()一個變量範圍問題。您的函數依賴於變量$statusFile,但是該變量在全局範圍中定義,並且在函數內部不可見。要使其可見,在訪問$statusFile之前,必須在您的功能中包含語句global $statusFile;。像這樣:

function execInBackground($cmd) { 
      global $statusFile; 
      if (false !== stripos(PHP_OS, 'win')) { 
       pclose(popen('start /B ' . $cmd, 'r')); 
       file_put_contents($statusFile, 1); 
      } else { 
       exec($cmd . ' > /dev/null &'); 
       file_put_contents($statusFile, 1); 
      } 
    } 

我改變了檢查操作系統的方式,因爲您的方法包含錯誤。


UPDATE2

一系列測試之後,我想通了,PHP腳本在後臺運行(在Windows下),當它不能使用「回聲()」來寫STDOUT。當它發生時,php-script將會靜靜地死去,沒有任何錯誤。因此,將所有echo()都改爲某些日誌功能。

將監聽端口更改爲某些其他可以肯定免費使用的端口,例如50000.因爲8080通常可能已被某些Web服務器或其他服務佔用。

還記得!只有當您擁有自己的服務器(如VPS/VDS或專用服務器)時,您纔可以啓動聊天服務器,公共託管由於安全原因,沒有人會允許您打開某些端口以接收傳入連接。在公共服務器上,出於相同的原因,通常會有禁用的功能,如exec()popen()等。

+0

我真的不知道如何停止服務器。也許當所有的用戶離開它應該停止加我需要一種方式來重新啓動服務器,因爲它以某種方式失敗。 – Ayan

+0

我改變了你說的方式,但它仍然給我'斷開'。 – Ayan

+0

所做的更改造成了一些尷尬的問題。 – Ayan

0

我想你應該閱讀http://php.net/manual/es/function.shell-exec.php

注意,當PHP在安全模式下運行此功能被禁用。

+0

我的本地主機沒有在安全模式下運行,我從http://php.net/manual/en/function.popen.php複製了代碼。這是關於運行一些後臺進程。 – Ayan