用PHP打开Linux终端命令


Open Linux terminal command in PHP

我有一台运行在Linux上的服务器,它可以对12个节点(其中运行Linux的12台计算机)执行命令。我最近在服务器上下载了PHP,以创建可以通过打开特定的PHP文件来执行命令的网页。

我使用了exec()passthru()shell_​exec()system()system()是唯一一个返回部分代码的程序。我希望PHP能像linux中的开放式命令一样运行,但我不知道该怎么做!

下面是一个现在发生的事情的例子(Linux直接与PHP):当直接使用linux开放终端命令时:

user@wizard:/home/hyperwall/Desktop> /usr/local/bin/chbg -mt

我得到一个输出:

The following settings will be used:
  option = mtsu   COLOR =    IMAGE = imagehereyouknow!
  NODES  = LOCAL
and additional code to send it to 12 nodes.

现在使用PHP:

switch($_REQUEST['do'])
{ case 'test':
    echo system('/usr/local/bin/chbg -mt');
    break;
}

输出:

The following settings will be used:
  option = mtsu   COLOR =    IMAGE = imagehereyouknow!
  NODES  = LOCAL

然后停下来!有人对发生的事情有解释吗?如何修复?只有系统显示部分代码,其他功能不显示任何内容!

我的第一个想法是它可能是关于std和输出错误。一些软件会转储一些std-out的信息和一些std-in-error的信息。当您没有将stderror重定向到stdout时,大多数系统调用只返回stdout部分。这听起来就是为什么你在终端中看到整个输出,而不能在系统调用中看到。所以试试

 /usr/local/bin/chbg -mt 2>&1  

编辑:也为了暂时的工作,你可以尝试一些其他的事情。例如,将输出重定向到脚本旁边的文件,并在执行命令后读取其内容。通过这种方式,您可以使用exec:

exec("usr/local/bin/chbg -mt 2>&1 > chbg_out");
//Then start reading chbg_out and see is it work

第2版另外,别人为什么不为你工作也没有道理。例如,这段用c编写的代码在stderr中转储一个字符串,在stdout中转储另一个字符串。

#include <stdio.h>
#include<stdlib.h>
int main()
{
    fputs("'nerr'nrro'nrrr'n",stderr);
    fputs("'nou'nuu'nuttt'n",stdout);
    return 0;
}

和这个php脚本,试图通过exec:运行

<?php
exec("/tmp/ctest",&$result);
foreach ( $result as $v )
{
echo $v;
}
#output ouuuuttt
?>

看它仍然会转储stdout。但它没有收到stderr。现在考虑一下:

<?php
exec("/tmp/ctest 2>&1",&$result);
foreach ( $result as $v )
{
    echo $v;
}
//output: errrrorrrouuuuttt
?>

看,这次我们得到了全部输出。

这次系统:

<?php
     echo system("/tmp/ctest 2>&1");
     //output: err rro rrr ou uu uttt uttt
?>

等等。。。

也许您的chbg-mt会将额外的代码写入stderr而不是stdout?尝试在php中执行脚本,如下所示:

/usr/local/bin/chbg -mt 2>&1

其他响应适用于一般建议。但在这种特定情况下,您似乎正在尝试更改桌面上的背景。由于"用户上下文",这需要许多特殊考虑:

  • 首先,您的web服务器可能以不同的用户身份运行,因此没有更改桌面的权限。

  • 其次,程序可能需要来自用户上下文的一些环境变量。例如,X程序需要一个DISPLAY变量,ssh代理需要SSH_AGENT_PIDSSH_AUTH_SOCK,等等。我对更改背景不太了解,但我猜它涉及到D-Bus,可能需要DBUS_SESSION_BUS_ADDRESSKONSOLE_DBUS_SERVICEKONSOLE_DBUS_SESSIONKONSOLE_DBUS_WINDOW之类的东西。可能还有很多其他的。请注意,这些变量中的一些在每次登录时都会更改,因此您不能在PHP端对它们进行硬编码。

对于测试来说,直接从用户会话启动自己的Web服务器可能更简单。(即,不要使用系统端口,它必须按您的方式运行。您需要在备用端口上运行它,如8080)。手动启动的web服务器将具有所需的所有"上下文"。我会提到websocketd,因为它刚刚问世,看起来很整洁。

对于"生产",您可能需要始终在用户上下文中运行一个守护程序,并让web服务器与该守护程序对话,以便在用户上下文内"完成任务"。

PHP的system只返回执行的最后一行:

返回值:成功时返回命令输出的最后一行,失败时返回FALSE。

您很可能希望使用execpassthruexec有一个可选参数,用于将输出放入数组中。你可以内爆输出并用它来回应它

switch($_REQUEST['do'])
{ case 'test':
    exec('/usr/local/bin/chbg -mt', $output);
    echo implode(''n', $output); // Could use <br /> if HTML output is desired
    break;
}

我认为执行的结果可能会在用户之间发生变化。首先,尝试将PHP脚本直接运行到终端php yourScript.php
如果它按预期运行,请转到您的Apache服务并更新它以使用您自己的凭据运行

您正在尝试更改当前登录用户的背景。。。当他们使用桌面时。就像我打字时一样。我最小化了浏览器,"哦,我的桌面背景不一样了"。希望这是为了一些重要的东西,比如当反应堆或过热时它会变红。

不管怎样,我的答案是:

而不是尝试以个人用户身份远程连接和运行项目。设置每个用户在一个重复计时器上运行bash脚本(在他们自己的帐户中,在自己的shell中)。每10分钟说一次。让它选择相同的文件。。从网络位置/somenetworkshare/backgrounds/images/current.png

然后,只需在/somenetworkshare/backgrounds/images/current.png

中更改图像本身,就可以更新所有节点(1到100万)。我不久前写了一篇文章,就是这样做的——你可以运行一个命令解释器(/bin/sh),向它发送命令,读回响应,发送更多命令,等等。它使用proc_open()打开一个子进程并与它对话。

它在http://github.com/andrasq/quicklib,Quick/Proc/Process.php

使用它看起来像(如果你有一个灵活的自动加载器,会更容易;我在Quicklib中也写了一个):

include 'lib/Quick/Proc/Exception.php';
include 'lib/Quick/Proc/Exists.php';
include 'lib/Quick/Proc/Process.php';
$proc = new Quick_Proc_Process("/bin/sh");
$proc->putInput("pwd'n");
$lines = $proc->getOutputLines($nlines = 10, $timeoutSec = 0.2);
echo $lines[0];
$proc->putInput("date'n");
$lines = $proc->getOutputLines(1, 0.2);
echo $lines[0];

输出

/home/andras/quicklib
Sat Feb 21 01:50:39 EST 2015

php和进程之间的通信单元是以换行符结尾的行。所有命令都必须以换行符结尾,并且所有响应都以行为单位检索。别忘了换行符,它们以后很难辨认。

我正在进行一个项目,该项目使用机器a上的终端a输出到机器B上的终端B,目前都使用linux。我没有看到它被提及,但也许你可以在你的网络服务器中使用重定向,比如

switch($_REQUEST['do'])
 { case 'test':
    #process ID on the target (12345, 12346 etc)
    echo system('/usr/local/bin/chbg -mt > /proc/<processID>/fd/1'); 
    #OR
    #device file on the target (pts/0,tty0, etc) 
    echo system('/usr/local/bin/chbg -mt > /dev/<TTY-TYPE>/<TTYNUM>');
    break;
 }

必须正确设置权限才能正常工作。终端中的命令"mesg y"也可能有助于。。。希望能有所帮助。