На самом деле я работаю над большим проектом, используя php laravel в качестве бэкэнда и реагируя как интерфейс, в котором я бы загружал zip-файл, содержащий проект реагирования, и как только файл будет загружен, он извлек бы файл, выполнил команду npm start, чтобы начать сервер, а затем с помощью кукловода сделайте снимок экрана живого проекта.
проблема в том, что всякий раз, когда выполняется команда npm start и запускается сервер, код в следующей строке не выполняется, он ждет, пока npm завершит свою работу, или, если бы он уничтожил его вручную из диспетчера задач, он бы затем отреагируйте на следующую строку кода, теперь я не могу опубликовать здесь весь код проекта, поэтому я приведу простой пример:
`<?php
// Execute npm start command in the background
mkdir('hello');
// Start Node.js server in the background using cmd.exe
exec('start /B cmd.exe /C npm start');
mkdir('hi');
?>`
в приведенном выше примере, когда я использую почтальона для запроса на получение, сначала создается «каталог hello», затем запускается сервер реагирования, но «каталог hi» никогда не создавался, пока я не убью процесс узла из диспетчера задач
до сих пор я устал, как и все, и у меня вопрос: невозможно ли сначала создать каталог hello, затем запустить сервер в фоновом режиме и, наконец, создать каталог hi ?? Заранее спасибо.
На компьютере с Linux или Unix вы можете добавить амперсанд (&) после команды, чтобы сделать ее «фоновой». Вместо этой команды
exec('start /B cmd.exe /C npm start');
Добавьте амперсанд:
exec('start /B cmd.exe /C npm start &');
Однако обратите внимание, что команда вернется немедленно, и следующая строка кода может быть выполнена до завершения команды NPM. Возможно, вам придется добавить какой-то цикл, чтобы проверить, завершился ли он каким-либо образом:
while (!npm_has_finished()) // you'd need to write this function
{
usleep(100000); // sleep for 100 milliseconds
}
сработал следующий скрипт:
<?php
// Function to check if a process is running on a given port
function isProcessRunning($port) {
$output = shell_exec("netstat -ano | findstr LISTENING | findstr :$port");
return !empty($output);
}
// Function to kill a process running on a given port
function killProcess($port) {
$output = shell_exec("netstat -ano | findstr LISTENING | findstr :$port");
$lines = explode("\n", $output);
foreach ($lines as $line) {
if (preg_match('/\s+\d+\s+TCP\s+\d+\.\d+\.\d+\.\d+:' . $port . '\s+\d+\.\d+\.\d+\.\d+:0\s+LISTENING\s+(\d+)/', $line, $matches)) {
$pid = trim($matches[1]);
exec("taskkill /F /PID $pid");
return true;
}
}
return false;
}
// Execute mkdir command for hello directory
$resultHello = mkdir('hello');
// Execute npm start command in the background
$command = 'start /B cmd /c "npm start"';
exec($command);
// Wait for the React server to start (up to 60 seconds)
$max_attempts = 12; // Total attempts (each attempt waits for 5 seconds)
$attempts = 0;
while (!isProcessRunning(3000) && $attempts < $max_attempts) {
sleep(5); // Wait for 5 seconds
$attempts++;
}
// If the React server is running, execute mkdir command for hi directory
if (isProcessRunning(3000)) {
$resultHi = mkdir('hi');
if (!$resultHi) {
echo "Error: Failed to create the 'hi' directory.";
}
// Kill the React server process running on port 3000
killProcess(3000);
// Kill the Node.js runtime process
exec("taskkill /F /IM node.exe");
} else {
// If the React server didn't start within the specified time, display an error message
echo "Error: React server did not start within the specified time.";
}
?>
спасибо @S.Imp за идею.
Вы можете попробовать функцию
proc_open
, которая поддерживает неблокирующий подпроцесс.