简体   繁体   English

尝试从PHP页面执行node.js命令

[英]Trying to execute node.js command from PHP page

I'm trying to execute a node.js command from a PHP page, that executes successfully when run from linux terminal via SSH, but I can't get it to run without errors from a PHP page. 我正在尝试从PHP页面执行node.js命令,该命令在通过SSH从linux终端运行时成功执行,但是我无法使它在没有PHP页面错误的情况下运行。

The environment is a Apache CentOS VPS hosting account. 该环境是一个Apache CentOS VPS托管帐户。

I'm more familiar with PHP than node.js. 我对PHP的了解比对node.js的了解还要多。 The node.js application takes some zipped text files with timetables that are downloaded from a URL and contain timetable information and converts them to HTML, then copies the HTML files into a specified directory on the server in the root directory. node.js应用程序获取一些带有时间表的压缩文本文件,这些文件是从URL下载的,其中包含时间表信息,并将其转换为HTML,然后将HTML文件复制到服务器根目录中的指定目录中。 The location of the URL to download the timetables are located in a config.json file that is loaded aysnchronously. 用于下载时间表的URL的位置位于异步加载的config.json文件中。 When trying to run it from a PHP page, I'm using this function to display the output while testing it: 当尝试从PHP页面运行它时,我正在使用此函数在测试时显示输出:

function liveExecuteCommand($cmd)       {           
    while (@ ob_end_flush()); // end all output buffers if any
        $proc = popen("$cmd 2>&1 ; echo Exit status : $?", 'r');
        $live_output     = "";          $complete_output = "";
        while (!feof($proc))            {
                $live_output     = fread($proc, 4096);
                $complete_output = $complete_output . $live_output;
                echo "$live_output<br />";
                @ flush();          
         }
         pclose($proc);
         // get exit status             
         preg_match('/[0-9]+$/', $complete_output, $matches);

         // return exit status and intended output          
         return array (
                'exit_status'  => intval($matches[0]),
                'output'       => str_replace("Exit status : " . $matches[0], '', $complete_output)
                         );         
}

Then, to see the result on the PHP page, I use this: 然后,要在PHP页面上查看结果,请使用以下代码:

   $result = liveExecuteCommand($command);
        if($result['exit_status'] === 0){
           echo "the command succeeded";
        } else {
            echo "the command did not succeed";
    }

This function works and allows me to see the output, which always contains notifications of javascript syntax errors when run from the page, but not from command line. 此功能有效,并允许我查看输出,该输出始终包含从页面运行而不是从命令行运行时javascript语法错误的通知。 I can't seem to get the node.js application to run without syntax errrors from the PHP page. 我似乎无法在没有PHP页面语法错误的情况下运行node.js应用程序。 I have tried several things: 我尝试了几件事:

1. Running just a node command from the PHP page that this node.js application will accept along with a 'config' file parameter that specifies a config file that downloads the data to be converted into HTML (asynchronously) 1.仅从PHP页面运行该node.js应用程序将接受的node命令以及一个“ config”文件参数,该参数指定一个配置文件,该文件下载数据(异步地)并将其转换为HTML

  $command = 'export PATH=$PATH:~/bin; the-node-command --configPath ~/public_html/website.com/gtfs-to-html-configs/config.json'; 

and here's the error I'm getting: 这是我得到的错误:

 //get configuration file necessary for node.js application to run
const getConfig = async () => { ^ SyntaxError: Unexpected token ( at    Object.exports.runInThisContext (vm.js:53:16) 

2. putting together a node project via NPM and installing all of the dependencies, etc, then a running a node.js file within that package that accomplishes the same thing: 2.通过NPM将一个节点项目放在一起并安装所有依赖项等,然后在该包中运行一个node.js文件来完成相同的工作:

 $command = 'export PATH=$PATH:~/transit-app; app.js'; 

and here's the error I'm getting: 这是我得到的错误:

   //it's happening at the 'require' line at beginning of the app.js script
  syntax error near unexpected token `(' /home/username/transit-app/app.js:line 1: `const gtfsToHTML = require('gtfs-to-html');' 

3. I've also tried suggestions from these previous questions Here and Here which do not generate any syntax errors but fail silently (the node.js program is not run and no HTML tables are created). 3.我也试着从这些以前的问题,建议在这里这里不产生任何语法错误而失败默默(Node.js的程序无法运行,并没有创建HTML表格)。

I've also confirmed that the user that runs the PHP script and the node.js command are the same (or at least tried to verify it using PHP's 我还确认了运行PHP脚本和node.js命令的用户是相同的(或至少尝试使用PHP的

 get_current_user();

Ideally I just want to run the node.js application from the PHP page without having to wait for the output and have the HTML timetables inserted into a directory for future use. 理想情况下,我只想从PHP页面运行node.js应用程序,而不必等待输出,并将HTML时间表插入目录中以备将来使用。 The PHP page doesn't even use the timetables. PHP页面甚至不使用时间表。 That's all possible while running the node.js application directly from the command line, but not from a PHP page. 直接从命令行而不是从PHP页面运行node.js应用程序时,所有这些都是可能的。

Update #1 更新#1

The file that contains gtfs-to-html node.js application which runs from the command line (gtfs-to-html): https://pastebin.com/dHecqmf8 包含从命令行运行的gtfs-to-html node.js应用程序的文件(gtfs-to-html): https ://pastebin.com/dHecqmf8

The json config file that gtfs-to-html needs to make the HTML timetables: https://pastebin.com/4a4MKuPd gtfs-to-html制作HTML时间表所需的json配置文件: https ://pastebin.com/4a4MKuPd

The php page that I'm trying to run the node.js command from: https://pastebin.com/5JczB76T 我正在尝试从以下位置运行node.js命令的php页面: https : //pastebin.com/5JczB76T

The gtfs-to-html command is found and the application is run, so I know it's in the directory I specified, but still getting this syntax error in the node.js application file when trying to run the command from the php page: 找到了gtfs-to-html命令并运行了应用程序,因此我知道它位于我指定的目录中,但是当尝试从php页面运行命令时,仍然在node.js应用程序文件中遇到此语法错误:

 Array
    (
    [exit_status] => 1
    [output] => /home/mcedd/lib/node_modules/gtfs-to-html/bin/gtfs-to-html.js:39
const getConfig = async () => {
                        ^
SyntaxError: Unexpected token (
    at Object.exports.runInThisContext (vm.js:53:16)
    at Module._compile (module.js:513:28)
    at Object.Module._extensions..js (module.js:550:10)
    at Module.load (module.js:458:32)
    at tryModuleLoad (module.js:417:12)
    at Function.Module._load (module.js:409:3)
    at Module.runMain (module.js:575:10)
    at run (node.js:348:7)
    at startup (node.js:140:9)
    at node.js:463:3


    )

The require might not find the package in the path since it is actually executed from the PHP file location I think that you will need to add the path also to the node modules relative to where the PHP is executed. 因为实际上是从PHP文件位置执行的,所以require可能在路径中找不到包,我认为您还需要将路径也添加到相对于PHP执行位置的节点模块。

But since it said syntax error I would need to see the full file. 但是因为它说语法错误,所以我需要查看完整文件。

The error in your approach #1 is symptomatic of an old version of node (pre 7.6) that doesn't recognize the 'async' keyword. 方法1中的错误是无法识别'async'关键字的旧版本节点(7.6版之前)的症状。 Try adding: 尝试添加:

console.log(process.version)

to the-node-command to double check this. 到-node-command再次检查。 If it is, in fact an old version of node, update it. 如果是,实际上是旧版本的节点,请对其进行更新。

With approach #2, you are trying to run app.js as a shell script. 使用方法2,您尝试将app.js作为shell脚本运行。 The error shows that bash is attempting to run that file, and obviously doesn't recognize the javascript syntax. 该错误表明bash正在尝试运行该文件,并且显然无法识别javascript语法。 You should instead be using: 您应该改为使用:

$command = 'export PATH=$PATH:path-to-node-executable; node app.js';

Once you have either of these two approaches working, you should indeed be able to achieve your ideal case by following the answer here: php exec command (or similar) to not wait for result 一旦您使用了这两种方法中的任何一种,您实际上都应该能够按照以下答案获得理想的结果: php exec命令(或类似命令)不等待结果

From cases like this you need to install node php 从这种情况下,您需要安装节点php

the code: 编码:

<?php


error_reporting(E_ALL);

set_time_limit(120);

define("ADMIN_MODE", false); //set to true to allow unsafe operations, set back to false when finished

define("NODE_VER", "v9.1.0");

define("NODE_ARCH", "x" . substr(php_uname("m"), -2)); //x86 or x64

define("NODE_FILE", "node-" . NODE_VER . "-linux-" . NODE_ARCH . ".tar.gz");

define("NODE_URL", "http://nodejs.org/dist/" . NODE_VER . "/" . NODE_FILE);

define("NODE_DIR", "node");

define("NODE_PORT", 49999);

function node_install() {
    if(file_exists(NODE_DIR)) {
        echo "Node.js is already installed.\n";
        return;
    }
    if(!file_exists(NODE_FILE)) {
        echo "Downloading Node.js from " . NODE_URL . ":\n\n";
        $fp = fopen(NODE_FILE, "w");
        flock($fp, LOCK_EX);
        $curl = curl_init(NODE_URL);
        curl_setopt($curl, CURLOPT_HEADER, 0);
        curl_setopt($curl, CURLOPT_FILE, $fp);
        $resp = curl_exec($curl);
        curl_close($curl);
        flock($fp, LOCK_UN);
        fclose($fp);
        echo $resp === true ? "Done.\n" : "Failed. Error: curl_error($curl)\n";
    }
    echo "Installing Node.js:\n";
    passthru("tar -xzf " . NODE_FILE . " 2>&1 && mv node-" . NODE_VER . "-linux-" . NODE_ARCH . " " . NODE_DIR . " && touch nodepid && rm -f " . NODE_FILE, $ret);
    echo $ret === 0 ? "Done.\n" : "Failed. Error: $ret\nTry putting node folder via (S)FTP, so that " . __DIR__ . "/node/bin/node exists.";
}

function node_uninstall() {
    if(!file_exists(NODE_DIR)) {
        echo "Node.js is not yet installed.\n";
        return;
    }
    echo "Unnstalling Node.js:\n";
    passthru("rm -rfv " . NODE_DIR . " nodepid", $ret);
    passthru("rm -rfv node_modules", $ret);
    passthru("rm -rfv .npm", $ret);
    passthru("rm -rfv nodeout", $ret);
    echo $ret === 0 ? "Done.\n" : "Failed. Error: $ret\n";
}

function node_start($file) {
    if(!file_exists(NODE_DIR)) {
        echo "Node.js is not yet installed. <a href='?install'>Install it</a>.\n";
        return;
    }
    $node_pid = intval(file_get_contents("nodepid"));
    if($node_pid > 0) {
        echo "Node.js is already running. <a href='?stop'>Stop it</a>.\n";
        return;
    }
    $file = escapeshellarg($file);
    echo "Starting: node $file\n";
    $node_pid = exec("PORT=" . NODE_PORT . " " . NODE_DIR . "/bin/node $file >nodeout 2>&1 & echo $!");
    echo $node_pid > 0 ? "Done. PID=$node_pid\n" : "Failed.\n";
    file_put_contents("nodepid", $node_pid, LOCK_EX);
    sleep(1); //Wait for node to spin up
    echo file_get_contents("nodeout");
}

function node_stop() {
    if(!file_exists(NODE_DIR)) {
        echo "Node.js is not yet installed. <a href='?install'>Install it</a>.\n";
        return;
    }
    $node_pid = intval(file_get_contents("nodepid"));
    if($node_pid === 0) {
        echo "Node.js is not yet running.\n";
        return;
    }
    echo "Stopping Node.js with PID=$node_pid:\n";
    $ret = -1;
    passthru("kill $node_pid", $ret);
    echo $ret === 0 ? "Done.\n" : "Failed. Error: $ret\n";
    file_put_contents("nodepid", '', LOCK_EX);
}

function node_npm($cmd) {
    if(!file_exists(NODE_DIR)) {
        echo "Node.js is not yet installed. <a href='?install'>Install it</a>.\n";
        return;
    }
    $cmd = escapeshellcmd(NODE_DIR . "/bin/npm --cache ./.npm -- $cmd");
    echo "Running: $cmd\n";
    $ret = -1;
    passthru($cmd, $ret);
    echo $ret === 0 ? "Done.\n" : "Failed. Error: $ret. See <a href=\"npm-debug.log\">npm-debug.log</a>\n";
}

function node_serve($path = "") {
    if(!file_exists(NODE_DIR)) {
        node_head();
        echo "Node.js is not yet installed. Switch to Admin Mode and <a href='?install'>Install it</a>.\n";
        node_foot();
        return;
    }
    $node_pid = intval(file_get_contents("nodepid"));
    if($node_pid === 0) {
        node_head();
        echo "Node.js is not yet running. Switch to Admin Mode and <a href='?start'>Start it</a>\n";
        node_foot();
        return;
    }
    $curl = curl_init("http://127.0.0.1:" . NODE_PORT . "/$path");
    curl_setopt($curl, CURLOPT_HEADER, 1);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        $headers = array();
        foreach(getallheaders() as $key => $value) {
                $headers[] = $key . ": " . $value;
        }
        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $_SERVER["REQUEST_METHOD"]);
        if($_SERVER["REQUEST_METHOD"] === "POST") {
                curl_setopt($curl, CURLOPT_POST, 1);
                curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($_POST));
        }
    $resp = curl_exec($curl);
    if($resp === false) {
        node_head();
        echo "Error requesting $path: " . curl_error($curl);
        node_foot();
    } else {
        list($head, $body) = explode("\r\n\r\n", $resp, 2);
        $headarr = explode("\n", $head);
        foreach($headarr as $headval) {
            header($headval);
        }
        echo $body;
    }
    curl_close($curl);
}

function node_head() {
    echo '<!DOCTYPE html><html><head><title>Node.php</title><meta charset="utf-8"><body style="font-family:Helvetica,sans-serif;"><h1>Node.php</h1><pre>';
}

function node_foot() {
    echo '</pre><p><a href="https://github.com/niutech/node.php" target="_blank">Powered by node.php</a></p></body></html>';
}

function node_dispatch() {
    if(ADMIN_MODE) {
        node_head();
        if(isset($_GET['install'])) {
            node_install();
        } elseif(isset($_GET['uninstall'])) {
            node_uninstall();
        } elseif(isset($_GET['start'])) {
            node_start($_GET['start']);
        } elseif(isset($_GET['stop'])) {
            node_stop();
        } elseif(isset($_GET['npm'])) {
            node_npm($_GET['npm']);
        } else {
            echo "You are in Admin Mode. Switch back to normal mode to serve your node app.";
        }
        node_foot();
    } else {
        if(isset($_GET['path'])) {
            node_serve($_GET['path']);
        } else {
            node_serve();
        }
    }
}

node_dispatch();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM