Я запускаю скрипт PHP из CLI. В этом сценарии PHP я хотел бы выполнить несколько команд из командной строки, используя system()
, Возможно, это не правильный инструмент для работы, и я мог бы просто обернуть сценарий PHP в сценарий оболочки, но я хочу знать, возможно ли это сделать полностью в сценарии PHP.
Когда я делаю это в терминале, он работает нормально:
user@host:~$ workon pootle
(pootle)user@host:~$
Однако это не работает с 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
выполненный терминалом пуст.
редактировать
Может быть, я где-то с этим.
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
Я нашел это установкой 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
… довольно легко выяснить оттуда
Чтобы иметь возможность выполнять функции 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 являются отдельными подоболочками друг от друга, поэтому если вы это сделаете:
<?php
system('FOO=BAR');
system('echo $FOO');
Это печатает пустую строку. Где как следующие отпечатки BAR
:
<?php
system('FOO=BAR && echo $FOO');
Поэтому нам необходимо:
workon
изменить рабочие виртуальные средыЭто то, что я придумал и, кажется, работает правильно:
<?php
$commands = [
'source /usr/local/bin/virtualenvwrapper.sh',
'workon pootle',
'pootle update_stores --project=AIWeb',
];
system('/bin/bash -c "'.implode(' && ', $commands) .'"');