简体   繁体   中英

How do you call python command “workon” from PHP exec?

I am running a PHP script from the CLI. In that PHP script I would like to execute a few commands from the command line using system() . Perhaps this isn't the right tool for the job, and I could probably just wrap the PHP script in a shell script, but I want to know if it's possible to do completely within the PHP script.

When I do this in a terminal it works fine:

user@host:~$ workon pootle
(pootle)user@host:~$

However this doesn't work from PHP (being executed as the same user).

#!/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

I notice that the output for the last two is exactly the same as when executing by a terminal, but the first one is different. I thought it might be an alias, however it doesn't appear to be. alias | grep -i workon alias | grep -i workon shows no output.

I also compared all of the environment variables returned from command line env and PHP system('env') , and all but _ are exactly the same, including SHELL=/bin/bash .

The output of which workon executed by the terminal is empty.

Edit

Maybe I'm getting somewhere with this.

user@host:~$ 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
}

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

I found this by installing virtualenvwrapper and then i ran

 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

and saw VIRTUALENVWRAPPER_SCRIPT ... pretty easy to figure out from there

To be able to execute the virtualenvwrapper functions, we need to first source the virtualenvwrapper.sh file. To find the location of that file, in a terminal execute:

which virtualenvwrapper.sh

If that doesn't produce any output, use find to find it.

find /usr/ -name "virtualenvwrapper.sh"

For me, the location was /usr/local/bin/virtualenvwrapper.sh

When PHP does system calls, it uses sh :

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

However the virtualenvwrapper.sh script fails when being executed with sh , so we need to use bash instead.

Another thing to note is that PHP system calls are separate subshells from each other, so if you do:

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

This prints out an empty line. Where as the following prints BAR :

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

Therefore, we need to:

  • Use bash instead of sh
  • Source the virtualenvwrapper.sh
  • Execute workon to change working virtual environments
  • Execute any other commands needed
  • Do all this in one single line

This is what I came up with and appears to be working correctly:

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM