2013-12-15 79 views
0

我有一個unix腳本,下面運行一個python程序,需要10分鐘才能完成一些數據處理,它工作正常。我想從一個php網頁運行這個腳本。PHP如何運行一個.sh腳本從php網頁調用python程序

run_virt_da_py.sh

#! /bin/bash 

# activate virtual environment 
cd /Users/data/myproject 
source bin/activate 

# virtualenv is now active 

python iterate_dir_analyse_files_1.py 

echo "data analysis completed ok" 

上面的腳本運行「完美」使用命令行使用下列命令手動從終端上運行OSX 10.6蘋果MAC運行它時。下面顯示了輸入命令後的提示。

[~]% cd myproject 
[myproject]% source bin/activate 
(myproject)[myproject]% sh run_virt_da_py.sh 

然而,當我嘗試從PHP運行.SH腳本失敗下面的腳本返回的Python程序,沒有其他的第一回聲聲明。

<html lang="en"> 
    <head> 
     <title>Data_analysis</title> 
    </head> 
    <body> 
    <?php 
    echo " data analysis script started "; 
    echo shell_exec('sh /Users/Data/myproject/run_virt_da_py.sh'); 
    echo "data analysis script may have completed"; 
    ?> 
    </body> 
</html> 

研究 我一直在使用,系統,中繼,EXEC,對了shell_exec不使用的virtualenv和沒有問題的腳本嘗試。

  1. 任何幫助,解決方案,方法或指針的歡迎。 在此先感謝。
+1

也許問題出現在用戶腳本運行的時候。當你從命令行運行它時,在用戶的操作下運行它?當你從PHP運行它時,它可能會運行在你的httpd用戶下,這可能沒有足夠的權限?嘗試使用shell腳本中的「whoami」來查看您實際運行的用戶,並嘗試從命令行下的同一用戶下運行腳本以查看發生了什麼。 –

回答

1

爲什麼你想在10分鐘內發出網絡請求? PHP並不意味着這一點。例如,我已經看到了一些後臺進程,例如生成要下載的文件,需要花費很長時間甚至更長時間才能完成,用戶可以等待它,但肯定它不會被信任,進程可能因多種原因而死亡(硬件限制,配置限制,網絡故障等),甚至更多,在共享服務器將明確殺死你的進程,無論配置是什麼。

在專用或VPS中,確定您可以修改指令並允許您的腳本永久運行,但問題不在於如何去做,但如果那是您需要的方法。也許是這樣,我不會說這是絕對禁止的方法,但可能不是。替代方案可能是:

  1. 有一個cronjob定期運行你的SH。當有網絡請求時,您可以提供預先計算的數據。
  2. 如果你不想讓它產生太頻繁,你可以讓它經常運行,但檢查它是否實際上繼續運行或沒有,可能檢查數據庫或文件,然後當有請求,從PHP你改變那個數據庫字段或那個文件的值,所以cron知道它必須運行。
  3. 具有PHP啓動SH,但在異步線程,因此在PHP executiom結束inmediately,通知該數據正在被處理的用戶,與實際過程是在後臺運行

這是一個真正常見的方法,你可以在很多網站上看到它,例如在你的服務器上看到它,如果你要求一些重要的東西,它們會生成它並在它準備好時通知你。或者當你想要備份你的數據時,你也可以在Facebook上做同樣的事情。業務智能系統和分析數據的系統也使用後臺進程,而不是生成預先計算好的數據,因此用戶進程可以是輕量級的。

在企業級應用程序中,我用這種繁重的過程來做的事情就是有一個鏈接,用於訪問最後生成的數據(通知其日期),頻繁運行的進程以及強制新的鏈接過程即將啓動。

由此,您將獲得更可靠的系統,同時最大限度地減少兩位用戶同時在不同計算機上分析相同數據的可能性,這意味着需要兩個10分鐘的過程來獲取相同的數據。

UPDATE

如果你不真的需要讓用戶實時看到該過程的結果,那麼它更容易。我不得不說這是一個類似crons,因爲在系統增長的時候,幫助你保持整個過程的順序和控制。但是如果你現在不想要它,你可以嘗試直接從php啓動後臺進程。試試這個代碼(我很多年前使用過它,但我想它會起作用)。對於Unix和Windows服務器都很好。

/** 
* execute $cmd in the background without PHP waiting for it to finish 
*/ 
function execInBackground($cmd) { 
    if (substr(php_uname(), 0, 7) == "Windows"){ 
     pclose(popen("start /B ". $cmd, "r")); 
    } 
    else { 
     exec($cmd . " > /dev/null &"); 
    } 
} 

所以,開始你的命令,你必須做的:

<html lang="en"> 
<head> 
    <title>Data_analysis</title> 
</head> 
<body> 
<?php 
echo " data analysis script started "; 
echo execInBackground('sh /Users/Data/myproject/run_virt_da_py.sh'); 
echo "data analysis script has been started"; 
?> 
</body> 
</html> 

當然,因爲它是在後臺線程運行,你不直接完成該過程時知道,所以你必須在sh腳本的末尾添加一些adicional動作,例如啓動另一個需要使用通知過程的php,例如發送電子郵件,更新數據庫等等。

+0

您的觀點3。就是我想要做的。用戶不會看到這個頁面。這個腳本是數據分析程序的一部分。 python程序輸出大量必須傳遞給數據庫的文件。我只是尋找一種方法來從PHP啓動腳本,我可以檢查過程是否在別處完成。你能解釋還是指向異步線程的方向,或者我可以如何做你所說的並且讓php只是在異步線程中啓動shell。 –

+0

@GeorgeThompson你是否有理由需要一個實際的頁面來做到這一點? PHP支持CLI模式,如果您安裝/編譯它,那麼您可以使用cron作業直接執行腳本,而不必像這樣訪問網頁。我也不太肯定你的分析腳本是幹什麼的,但是用python做這件事可能不是一個好辦法。你有沒有想過ETL或其他一些用於數據分析的框架/語言/平臺?只是我的兩分錢。 – Zarathuztra

3

像GoDaddy(在共享主機上)的一些主機在PHP中對exec函數有限制。

另一點是,你需要配置的php.ini增加你的超時max_execution_time = 1200,默認情況下,的php.ini有60秒超時,你的腳本會死。

我認爲你已經到達你的腳本,但你並沒有等待完成。嘗試在你的php的頂部添加一些代碼來編寫一個「Hello world」文件來測試它。

2

首先,請確保修改php.ini(如果可能)以允許延長的執行時間。如果你的腳本花費太長時間,你的腳本可能會終止它。

然後,確保你實際上給腳本足夠的時間去了shell_exec()

第三,確保安全模式被禁用。

第四,確保您的託管服務提供商允許shell_exec()或反引號。

2

接受的答案是正確的,但應該指出,virtualenv帶有一個名爲activate_this.py的腳本,該腳本存在用於設置類似virtualenv的環境以用於Web服務器。請參閱https://pypi.python.org/pypi/virtualenv並在頁面上搜索activate_this.py。然後你就可以做到這一點,而不需要從web服務器啓動一個子shell來修改環境來運行virtualenv的Python解釋器。