Я пытаюсь запустить файл chat-server.php Ratchet, который необходим для запуска сервера сокетов из php-файла, чтобы каждый раз, когда клиент посещал страницу, сервер запускался, но этого не происходило. Этот файл chat-server.php необходимо запустить с терминала, но я пытаюсь запустить его с главной страницы при посещении пользователя.
ФАЙЛОВАЯ СТРУКТУРА
./index.php
./config.php
./ vendor / (все файлы вендора)
./src/MyApp/Chat.php
./js/app.js
./inc/connect.php <- файл подключения к базе данных
./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
НОТА: Обновил код соответствующим образом, но пока не работает.
плюс Я не имею ни малейшего представления о перезапуске сервера в случае каких-либо сбоев или о том, как отключить сервер, когда все клиенты уходят.
Когда вы включаете файлы, используя относительные пути Вы должны помнить, что они относятся к ток Бег файл, не только текущий файл.
В твоем случае. Когда вы получаете доступ 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
home dir или, возможно, началось с домашнего каталога вашего пользователя. Это зависит от настройки вашего 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
неважно, из какой папки вы его запустите.
Кстати, как вы планировали остановить свой сервер? знак равно
ОБНОВИТЬ: Также у вас есть переменная область проблема в вашей функции execInBackground()
, Ваша функция зависит от переменной $statusFile
, но эта переменная определена в глобальный охват и не виден внутри функции. Чтобы сделать это видимым, вы должны включить заявление global $statusFile;
в вашей функции до доступа $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), он не может использовать «echo ()» для записи в STDOUT. Когда это произойдет, php-скрипт молча умрет, без ошибок. Так что поменяй все echo()
в какой-то лог-функции.
Измените порт прослушивания на какой-то другой, это бесплатно, например, 50000. Потому что 8080 часто может быть уже занято некоторым веб-сервером или другим сервисом.
И запомни! Вы можете запустить свой чат-сервер, только если у вас есть собственный сервер (например, VPS / VDS или выделенный сервер) на публичный хостинг никто не позволит вам открыть какой-либо порт для входящих подключений по соображениям безопасности. На общедоступных серверах часто отключаются такие функции, как exec()
, popen()
и похожие по тем же причинам.
Я думаю, что вы должны прочитать http://php.net/manual/es/function.shell-exec.php
Обратите внимание, что эта функция отключена, когда PHP работает в безопасном режиме.