2017-03-02 58 views
1

我正在從CLI運行一個PHP腳本。在該PHP腳本中,我想使用system()從命令行執行一些命令。也許這不是適合工作的工具,我可能只是將PHP腳本包裝在shell腳本中,但我想知道是否可以在PHP腳本中完全完成。如何從PHP exec調用python命令「workon」?

當我做這在終端正常工作:

[email protected]:~$ workon pootle 
(pootle)[email protected]:~$ 

但是這並不PHP(相同的用戶正在執行)工作。

#!/usr/bin/env php 
<?php 
system('workon pootle'); // sh: 1: workon: not found 
system('/bin/bash workon pootle'); // /bin/bash: workon: No such file or directory 
system('/bin/sh workon pootle'); // /bin/sh: 0: Can't open workon 

我注意到輸出最後兩個是完全一樣的由終端執行時一樣,但第一個是不同的。我認爲這可能是一個別名,但它似乎並不是。 alias | grep -i workon顯示沒有輸出。

我還比較所有命令行env和PHP system('env')返回的環境變量,以及所有,但_是完全一樣的,包括SHELL=/bin/bash

由終端執行的輸出which workon爲空。

編輯

也許我與此有所進展。

[email protected]:~$ type workon 
workon is a function 
workon() 
{ 
    typeset env_name="$1"; 
    if [ "$env_name" = "" ]; then 
     lsvirtualenv -b; 
     return 1; 
    fi; 
    virtualenvwrapper_verify_workon_home || return 1; 
    virtualenvwrapper_verify_workon_environment $env_name || return 1; 
    activate="$WORKON_HOME/$env_name/$VIRTUALENVWRAPPER_ENV_BIN_DIR/activate"; 
    if [ ! -f "$activate" ]; then 
     echo "ERROR: Environment '$WORKON_HOME/$env_name' does not contain an activate script." 1>&2; 
     return 1; 
    fi; 
    type deactivate > /dev/null 2>&1; 
    if [ $? -eq 0 ]; then 
     deactivate; 
     unset -f deactivate > /dev/null 2>&1; 
    fi; 
    virtualenvwrapper_run_hook "pre_activate" "$env_name"; 
    source "$activate"; 
    virtualenvwrapper_original_deactivate=`typeset -f deactivate | sed 's/deactivate/virtualenv_deactivate/g'`; 
    eval "$virtualenvwrapper_original_deactivate"; 
    unset -f deactivate > /dev/null 2>&1; 
    eval 'deactivate() { 

     # Call the local hook before the global so we can undo 
     # any settings made by the local postactivate first. 
     virtualenvwrapper_run_hook "pre_deactivate" 

     env_postdeactivate_hook="$VIRTUAL_ENV/$VIRTUALENVWRAPPER_ENV_BIN_DIR/postdeactivate" 
     old_env=$(basename "$VIRTUAL_ENV") 

     # Call the original function. 
     virtualenv_deactivate $1 

     virtualenvwrapper_run_hook "post_deactivate" "$old_env" 

     if [ ! "$1" = "nondestructive" ] 
     then 
      # Remove this function 
      unset -f virtualenv_deactivate >/dev/null 2>&1 
      unset -f deactivate >/dev/null 2>&1 
     fi 

    }'; 
    virtualenvwrapper_run_hook "post_activate"; 
    return 0 
} 
+0

'回聲$(其中workon)'(運行在shell終端,並參考路徑) –

+0

@JoranBeasley輸出爲空。 – Mike

+1

在這種情況下,我不認爲workon可以從終端訪問...'workon --help && echo $(which workon)' –

回答

0

爲了能夠執行virtualenvwrapper函數,我們首先需要source這個virtualenvwrapper.sh文件。要查找文件的位置,在終端執行:

which virtualenvwrapper.sh 

如果不產生任何輸出,使用find找到它。

find /usr/ -name "virtualenvwrapper.sh" 

對我來說,地點是/usr/local/bin/virtualenvwrapper.sh

當PHP做系統調用,它使用sh

<?php 
system('echo $0'); // echoes 'sh' 

然而virtualenvwrapper.sh腳本失敗時,正在與sh執行的,所以我們需要改爲使用bash

另一個要注意的是,PHP系統調用是相互獨立的子shell,所以如果你這樣做:

<?php 
system('FOO=BAR'); 
system('echo $FOO'); 

這打印出一個空行。凡爲下面的打印BAR

<?php 
system('FOO=BAR && echo $FOO'); 

因此,我們需要:

  • 使用bash,而不是SH
  • 來源virtualenvwrapper.sh
  • 執行workon改變工作虛擬環境
  • 執行所需的任何其他命令
  • 做到這一切在一個單行

這是我想出了,似乎一切正常:

<?php 
$commands = [ 
    'source /usr/local/bin/virtualenvwrapper.sh', 
    'workon pootle', 
    'pootle update_stores --project=AIWeb', 
]; 

system('/bin/bash -c "'.implode(' && ', $commands) .'"'); 
0

bash /usr/share/virtualenvwrapper/virtualenvwrapper.sh workon

我發現這個通過安裝virtualenvwrapper然後我跑

env | grep VIRTU 
VIRTUALENVWRAPPER_PROJECT_FILENAME=.project 
VIRTUALENVWRAPPER_SCRIPT=/usr/share/virtualenvwrapper/virtualenvwrapper.sh 
VIRTUALENVWRAPPER_HOOK_DIR=/root/.virtualenvs 
_VIRTUALENVWRAPPER_API= mkvirtualenv rmvirtualenv lsvirtualenv showvirtualenv workon add2virtualenv cdsitepackages cdvirtualenv lssitepackages toggleglobalsitepackages cpvirtualenv setvirtualenvproject mkproject cdproject mktmpenv 

,看到VIRTUALENVWRAPPER_SCRIPT ...很容易從那裏找出

+0

我沒有'VIRTUALENVWRAPPER_SCRIPT'環境變量,但是我找到了'/ usr/local/bin/virtualenvwrapper.sh'。執行'/ bin/bash /usr/local/bin/virtualenvwrapper.sh workon pootle'沒有任何輸出。 – Mike