Integrating proc_open in PHP with JavaScript WebSockets involves using a long-running PHP script as a WebSocket server (using a library like Open Swoole or Ratchet) that then uses proc_open to manage separate, external processes. The output from proc_open is captured by the server-side PHP script and then pushed to the connected JavaScript client(s) via the WebSocket connection.
Directly connecting the JavaScript WebSocket to the pipes created by proc_open in a traditional, short-lived HTTP PHP script is not feasible because a standard PHP script terminates after the HTTP request finishes, closing all pipes. WebSockets require a persistent, dedicated connection.
Server-Side (PHP with Open Swoole)
You will need a dedicated PHP WebSocket server running continuously on its own port (e.g., 8080). This requires a PHP extension like Open Swoole.
server.php:
php

<?php
require __DIR__ . '/vendor/autoload.php';

use OpenSwoole\WebSocket\Server;
use OpenSwoole\Http\Request;
use OpenSwoole\Http\Response;

$server = new Server("0.0.0.0", 8080);

$server->on("Start", function (Server $server) {
   echo "OpenSwoole WebSocket server started at http://0.0.0.0:8080\n";
});

$server->on("Open", function (Server $server, Request $request) {
   echo "Connection open: {$request->fd}\n";
});

$server->on("Message", function (Server $server, \OpenSwoole\WebSocket\Frame $frame) {
   // When a message is received from the JavaScript client, execute a command
   if ($frame->data === "run_command") {
       $cmd = "ls -l"; // Example command
       $descriptorspec = array(
           0 => array("pipe", "r"),
           1 => array("pipe", "w"),
           2 => array("pipe", "w")
       );

       $process = proc_open($cmd, $descriptorspec, $pipes);
       if (is_resource($process)) {
           // Read the output from the command
           $output = stream_get_contents($pipes[1]);
           fclose($pipes[1]);
           proc_close($process);

           // Send the output back to the specific client via WebSocket
           $server->push($frame->fd, "Command Output: " . $output);
       } else {
           $server->push($frame->fd, "Failed to run command.");
       }
   }
});

$server->on("Close", function (Server $server, int $fd) {
   echo "Connection close: {$fd}\n";
});

$server->start();

Run this server from your terminal: php server.php.
Client-Side (JavaScript with HTML)
The JavaScript client will connect to the running PHP WebSocket server using the WebSocket API.
index.html:
html

<!DOCTYPE html>
<html>
<head>
   <title>PHP proc_open with WebSockets</title>
</head>
<body>
   <h1>WebSocket Output</h1>
   <button onclick="runCommand()">Run PHP Command</button>
   <pre id="output"></pre>

   <script>
       const output = document.getElementById('output');
       const socket = new WebSocket('ws://localhost:8080'); // Connect to your PHP server port

       socket.addEventListener('open', function (event) {
           output.textContent += 'CONNECTED\n';
       });

       socket.addEventListener('message', function (event) {
           // Display message received from PHP server
           output.textContent += 'Received: ' + event.data + '\n';
       });

       socket.addEventListener('error', function (event) {
           output.textContent += 'ERROR\n';
       });

       function runCommand() {
           if (socket.readyState === WebSocket.OPEN) {
               socket.send('run_command'); // Send message to trigger command execution on server
               output.textContent += 'Sent: run_command\n';
           } else {
               output.textContent += 'WebSocket is not open.\n';
           }
       }
   </script>
</body>
</html>

Open index.html in your browser. When you click the button, JavaScript sends a message to the PHP WebSocket server, which executes proc_open and returns the output in real-time.