在PHP中打开Linux终端命令

在PHP中打开Linux终端命令,php,linux,Php,Linux,我有一个运行在Linux上的服务器,它向12个节点(12台运行Linux的计算机)执行命令。我最近在服务器上下载了PHP,以创建可以通过打开特定PHP文件来执行命令的网页 我使用了exec(),passthru(),shell_​exec(),和系统()系统()是唯一返回部分代码的系统。我希望PHP像linux中的OpenTermainal命令一样工作,但我不知道如何做 下面是一个正在发生的事情的示例(Linux直接对PHP): 直接使用linux open terminal命令时: user@

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

我使用了
exec()
passthru()
shell_​exec()
,和
系统()
<代码>系统()是唯一返回部分代码的系统。我希望PHP像linux中的OpenTermainal命令一样工作,但我不知道如何做

下面是一个正在发生的事情的示例(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

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

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

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

我的第一个想法是,它可能与std和输出错误有关。一些软件转储一些关于std out和一些in std错误的信息。当您没有将std error重定向到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;
}
#包括
#包括
int main()
{
FPUT(“\nerr\nrro\nrr\n”,标准);
fputs(“\nou\nuu\nuttt\n”,标准输出);
返回0;
}
这个php脚本试图通过exec运行:

<?php

exec("/tmp/ctest",&$result);

foreach ( $result as $v )
{
echo $v;
}
#output ouuuuttt
?>

看,它还是把标准输出。但它没有收到标准。 现在考虑这个问题:

<?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
?>


等等…

我认为执行的结果可以在用户之间改变。 首先,尝试将PHP脚本直接运行到终端
PHP yourScript.PHP


如果它按预期运行,请转到您的Apache服务,并将其更新为使用您自己的凭据运行

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

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

  • 其次,该程序可能需要用户上下文中的一些环境变量。例如,X程序需要一个
    DISPLAY
    变量,ssh代理需要
    ssh\u-agent\u-PID
    ssh\u-AUTH\u-SOCK
    ,等等。我对改变背景知之甚少,但我猜它涉及到D-Bus,这可能需要类似
    DBUS-SESSION\u-Bus-ADDRESS
    KONSOLE\u-DBUS-SERVICE
    KONSOLE\u DBUS\u会话
    ,以及
    KONSOLE\u DBUS\u窗口
    。可能还有很多其他的。请注意,这些变量中的一些在您每次登录时都会发生更改,因此您无法在PHP端硬编码它们

对于测试,从用户会话开始启动自己的Web服务器可能更简单。(也就是说,不要使用system one,它必须像您一样运行。您需要在备用端口(如8080)上运行它)。手动启动的web服务器将具有它所需的所有“上下文”。我要说的是,它刚出来,看起来很整洁


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

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

我的回答是:

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


然后,您只需在/somenetworkshare/backgrounds/images/current.png中更改图像本身,就可以更新所有节点(1到100万个)。我不久前写了一篇文章,就是这样做的——您可以运行命令解释器(/bin/sh),发送命令,读取响应,发送更多命令,等等。它使用
proc\u open()
打开子进程并与其对话

它位于Quick/Proc/Process.php

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

输出

/home/andras/quicklib
Sat Feb 21 01:50:39 EST 2015
php和进程之间的通信单元是换行符终止的行。所有命令都必须换行终止,所有响应都以行为单位检索。不要忘记换行符,它们很难在以后识别。

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

返回值:成功时返回命令输出的最后一行,失败时返回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;
}
开关($\u请求['do']))
{案例“测试”:
exec('/usr/local/bin/chbg-mt',$output);
回声脉冲
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;
}
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;
 }