2015-02-11 275 views
5

我有一臺運行在Linux上的服務器,它執行12個節點(12臺運行Linux的計算機)的命令。我最近在服務器上下載了PHP,通過打開特定的PHP文件來創建可以執行命令的網頁。在PHP中打開Linux終端命令

我用exec(),passthru(),shell_​exec()system()system()是唯一一個返回我的代碼的一部分。我希望PHP在Linux中像開放性的termainal命令一樣行事,我無法弄清楚如何做到這一點!

這是現在發生的事情(Linux的直接與PHP)的例子: 當使用直接Linux開放源終端命令:

[email protected]:/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 

並停止!任何人都有解釋發生了什麼?以及如何解決它?只有系統顯示部分代碼,其他功能不顯示任何內容!

+1

您是否使用過'strace'來確定它卡住了什麼?以調試模式運行Web服務器以將其限制爲單個進程。 – 2015-02-15 16:59:10

+3

你正在運行哪個Web服務器?在哪個用戶的網絡服務器上運行?如果它運行在「nobody」或類似環境下,您確定該用戶可以執行chbg命令​​嗎? – 2015-02-15 17:10:59

+2

什麼是「以及將其發送到12個節點的附加代碼」。 ??它來自哪裏? – Nimrod007 2015-02-15 17:40:00

回答

4

我首先想到的是它可以是關於性病和輸出錯誤。有些軟件會轉儲一些標準錯誤信息。如果不是將std錯誤重定向到標準輸出,大多數系統調用僅返回標準輸出部分。這聽起來就是你爲什麼在終端看到整個輸出並且不能在系統調用中看到的原因。通過 也爲臨時工作,你可以嘗試一些其他的東西: 因此,與

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

等等...

+0

很好的答案,很好的備份與例子。 – 2015-02-21 20:42:22

+0

:)謝謝@scrowler – madz 2015-02-22 08:21:45

2

也許您的chbg -mt將其他代碼寫入stderr而不是stdout?嘗試執行你的腳本PHP內部像這樣:

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

我認爲,執行的結果,可以在用戶之間變化。 首先,嘗試直接運行PHP腳本到你的終端php yourScript.php
如果運行正常,去你的Apache服務和更新它用自己的憑據運行

2

其他的反應是好普通的通知。但在這種特定情況下,您似乎試圖在桌面上更改背景。這需要因「用戶上下文」有特殊的考慮:

  • 首先,你的Web服務器可能運行作爲不同的用戶,所以也就沒有權限更改您的桌面。

  • 其次,該程序可能需要您的用戶環境中的一些環境變量。例如,X程序需要DISPLAY變量,ssh-agent需要SSH_AGENT_PIDSSH_AUTH_SOCK等。我對改變背景知之甚少,但我猜測它涉及D-Bus,可能需要諸如DBUS_SESSION_BUS_ADDRESSKONSOLE_DBUS_SERVICEKONSOLE_DBUS_SESSIONKONSOLE_DBUS_WINDOW。可能還有很多其他的。請注意,這些變量中的一些會在您每次登錄時發生變化,因此您無法在PHP端對它們進行硬編碼。

對於測試,從用戶會話啓動自己的Web服務器可能會更簡單。 (即不要使用系統,它必須像你一樣運行,你需要在備用端口上運行它,比如8080)。您手動啓動的Web服務器將擁有所需的所有「上下文」。我會提到websocketd,因爲它剛剛出來,看起來很整齊。

對於「生產」,您可能需要始終在用戶上下文中運行守護進程,並讓Web服務器與該守護進程對話以在用戶上下文中「完成任務」。

+0

對我而言,「桌面」問題與假設無關,可能只是示例問題的一部分。真正的問題是關於爲什麼Linux命令行和PHP執行的Linux命令之間存在不一致。我認爲你首先想到的是,一個不同的用戶正在使用PHP來運行你通常在Linux控制檯中使用的事實,這是最謹慎和重要的一點。爲了保持一致性,可能需要運行你的Linux命令,因爲運行PHP的用戶可以進一步模擬PHP系統調用的行爲。 – 2015-02-21 20:48:50

1

您正嘗試更改當前登錄用戶的背景......當他們使用桌面時。就像我輸入這條消息一樣。我最小化瀏覽器,'我的桌面背景不同'。希望這是對重要的東西,當反應堆或過熱時它會變紅。

反正我的回答:

,而不是試圖遠程連接和運行的項目,如個人用戶。設置每個用戶在重複定時器上運行bash腳本(在他們自己的帳戶中,在他們自己的shell中)。每10分鐘說一次。讓它從網絡位置選擇SAME文件.. /somenetworkshare/backgrounds/images/current.png

然後,您可以通過更改/ somenetworkshare/backgrounds中的圖像本身來更新所有節點(1到100萬) /images/current.png

+0

「許多一次請求」方法的缺點是,你需要引入1到100萬次所需的處理時間並以保證的速度降低您的整體性能,而「一對多推動」方法只在需要時降低。 – 2015-02-21 20:44:35

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和過程是換行符終止行。所有命令必須以換行符終止,並且所有響應都以行爲單位進行檢索。不要忘記換行符,事後很難識別。

+0

這是作爲你工作的腳本的廣告而不是 – 2015-02-21 20:46:01

+0

這個問題的答案,是的,我回答說:「我希望PHP在Linux下像打開termainal命令一樣行動」而不滾動閱讀其餘部分詳細。我認爲這會有所幫助;沒有意識到這不是問題。 – Andras 2015-02-21 21:51:50

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

我正在使用機器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」也可以幫助...希望有所幫助。