我有一台运行在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_PID
和SSH_AUTH_SOCK
,等等。我对更改背景不太了解,但我猜它涉及到D-Bus,可能需要DBUS_SESSION_BUS_ADDRESS
、KONSOLE_DBUS_SERVICE
、KONSOLE_DBUS_SESSION
和KONSOLE_DBUS_WINDOW
之类的东西。可能还有很多其他的。请注意,这些变量中的一些在每次登录时都会更改,因此您不能在PHP端对它们进行硬编码。
对于测试来说,直接从用户会话启动自己的Web服务器可能更简单。(即,不要使用系统端口,它必须按您的方式运行。您需要在备用端口上运行它,如8080)。手动启动的web服务器将具有所需的所有"上下文"。我会提到websocketd,因为它刚刚问世,看起来很整洁。
对于"生产",您可能需要始终在用户上下文中运行一个守护程序,并让web服务器与该守护程序对话,以便在用户上下文内"完成任务"。
PHP的system
只返回执行的最后一行:
返回值:成功时返回命令输出的最后一行,失败时返回FALSE。
您很可能希望使用exec
或passthru
。exec
有一个可选参数,用于将输出放入数组中。你可以内爆输出并用它来回应它
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"也可能有助于。。。希望能有所帮助。