在PHP中打开Linux终端命令

时间:2015-02-11 23:05:13

标签: php linux

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

我使用了exec()passthru()shell_​exec()system()system()是唯一一个返回部分代码的人。我希望PHP在linux中像开放式termainal命令一样,我无法弄清楚如何做到这一点!

以下是现在正在发生的事情的一个例子(Linux直接与PHP): 直接使用linux open terminal命令时:

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

然后停下来!任何人都有解释发生了什么?以及如何解决它?只有系统显示部分代码,其他功能不显示任何内容!

8 个答案:

答案 0 :(得分:4)

我首先想到的是它可能是关于std和输出错误的东西。有些软件会在std out上转储一些信息,有些则在std错误中转储。当您没有将std错误重定向到std out时,大多数系统调用仅返回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

<强> EDIT2 另外,为什么其他人不为你工作也没有意义。 例如,这段用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
?>

看到它仍然倾倒了标准输出。但它没有收到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
?>

依旧......

答案 1 :(得分:2)

也许你的chbg -mt将额外的代码写入stderr而不是stdout?尝试在php中执行你的脚本:

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

答案 2 :(得分:2)

其他回复适用于通用建议。但在这种特定情况下,您似乎正在尝试更改桌面背景。由于用户上下文&#39;

,这需要许多特殊注意事项
  • 首先,您的网络服务器可能以不同的用户身份运行,因此无权更改您的桌面。

  • 其次,该程序可能需要您的用户上下文中的一些环境变量。例如,X程序需要DISPLAY变量,ssh-agent需要SSH_AGENT_PIDSSH_AUTH_SOCK等等。我对改变背景知之甚少,但我不知道猜测它涉及D-Bus,可能需要DBUS_SESSION_BUS_ADDRESSKONSOLE_DBUS_SERVICEKONSOLE_DBUS_SESSIONKONSOLE_DBUS_WINDOW等内容。可能还有很多其他人。请注意,每次登录时都会更改其中一些变量,因此您无法在PHP端对其进行硬编码。

对于测试,直接从用户会话启动自己的网络服务器可能更简单。 (即不要使用系统一,它必须像你一样运行。你需要在备用端口上运行它,如8080)。您手动启动的网络服务器将具有所有“上下文”功能。它需要。我提到websocketd,因为它刚刚出来,看起来很整洁。

对于&#34; production&#34;,您可能需要始终在用户上下文中运行守护程序,并让Web服务器与该守护程序通信以“完成任务”#39;在你的用户环境中。

答案 3 :(得分:2)

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;
}

答案 4 :(得分:1)

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

答案 5 :(得分:1)

您正在尝试更改当前登录用户的背景...他们正在使用桌面时。就像我正在输入这条消息一样。我最小化了我的浏览器,“我的桌面背景不同”。希望这是重要的事情,比如它在反应堆或过热时会变红。

无论如何我的回答:

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

然后你可以通过改变/somenetworkshare/backgrounds/images/current.png中的图像本身来更新所有节点(1到100万)

答案 6 :(得分:1)

我刚才写过这样的东西 - 你可以运行命令解释器(/ 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和进程之间的通信单元是换行终止行。所有命令必须以换行符终止,并且所有响应都以行为单位检索。不要忘记换行符,之后很难识别。

答案 7 :(得分:0)

我正在开发一个项目,它使用机器A上的终端A输出到机器B上的终端B,现在都使用Linux。我没有看到它提到,但也许你可以使用重定向,在你的网络服务器中使用这样的东西:

>>> listA = [['abc', 'def'], ['ghi', 'klm'], ['nop', 'qrs']]                    >>> [(index,region) for index,region in enumerate(listA)]
[(0, ['abc', 'def']), (1, ['ghi', 'klm']), (2, ['nop', 'qrs'])]
>>> [(index,[(ind,it) for ind,it in enumerate(region)]) for index,region in enumerate(listA)]
[(0, [(0, 'abc'), (1, 'def')]), (1, [(0, 'ghi'), (1, 'klm')]), (2, [(0, 'nop'), (1, 'qrs')])]
>>> [("Region %d"%index,[(ind,it) for ind,it in enumerate(region)]) for index,region in enumerate(listA)]
[('Region 0', [(0, 'abc'), (1, 'def')]), ('Region 1', [(0, 'ghi'), (1, 'klm')]), ('Region 2', [(0, 'nop'), (1, 'qrs')])]

>>> format printing the list comprehension
>>> print "\n".join("Region %d \n%s"%(index,"\n".join("%d %s"%(ind,it) for ind,it in enumerate(region)))  for index,region in enumerate(listA))
Region 0
0 abc
1 def
Region 1
0 ghi
1 klm
Region 2
0 nop
1 qrs

肯定需要正确设置权限才能使其正常工作。终端中的命令“mesg y”也可以帮助......希望有所帮助。