Какую оболочку использует системный вызов Perl ()? - PullRequest
10 голосов
/ 19 ноября 2010

Я использую системный вызов для выполнения некоторых задач

system('myframework mycode');

но он жалуется на отсутствие переменных окружения. Эти переменные окружения установлены в моей оболочке bash (откуда я запускаю код Perl).

Что я делаю не так?

Создает ли вызов system совершенно новую оболочку (без настроек переменных среды)? Как я могу избежать этого?

Ответы [ 7 ]

18 голосов
/ 19 ноября 2010

Это сложно.Perl не обязательно вызывает оболочку. Perldoc говорит:

Если есть только один скалярный аргумент, аргумент проверяется на наличие метасимволов оболочки, и, если они есть, весь аргумент передается командной оболочке системыдля разбора (это / bin / sh -c на платформах Unix, но отличается на других платформах).Если в аргументе нет метасимволов оболочки, он разбивается на слова и передается непосредственно в execvp, что более эффективно.

Таким образом, похоже, что аргументы передаются прямо в execvp.Кроме того, будет ли оболочка загружать ваши .bashrc, .profile или .bash_profile, зависит от того, является ли оболочка интерактивной.Вероятно, это не так, но вы можете проверить, как это .

4 голосов
/ 19 ноября 2010

Я думаю, что это не вопрос выбора оболочки, поскольку переменные окружения всегда наследуются подпроцессами, если они не очищены явно. Вы уверены, что экспортировали свои переменные? Это будет работать:

$ A=5 perl -e 'system(q{echo $A});'
5
$

Это тоже будет работать:

$ export A=5
$ perl -e 'system(q{echo $A});'
5
$

Это не будет:

$ A=5
$ perl -e 'system(q{echo $A});'

$
4 голосов
/ 19 ноября 2010

Если вы не хотите вызывать оболочку, вызовите system со списком:

system 'mycommand', 'arg1', '...';
system qw{mycommand arg1 ...};

Если вы хотите определенную оболочку, вызовите ее явно:

system "/path/to/mysh -c 'mycommand arg1 ...'";
3 голосов
/ 18 апреля 2012

Я боролся за 2 дня, работая над этим. В моем случае переменные среды были правильно установлены в Linux, но не в Cygwin.

От ответа mkb Я подумал проверить man perlrun, и в нем упоминается переменная с именем PERL5SHELL (, специфичная для порта Win32 ). Следующее затем решило проблему:

$ENV{PERL5SHELL} = "sh";

Как это часто бывает - все, что я могу на самом деле сказать, это «это работает для меня», хотя документация подразумевает, что это может быть разумным решением:

Может быть установлена ​​альтернативная оболочка, которую perl должен использовать внутри для выполнения команд "backtick" или system ().

Если оболочка, используемая perl, неявно наследует переменные окружения, тогда они не будут установлены для вас.

3 голосов
/ 19 ноября 2010

system () вызывает / bin / sh как оболочку.Если вы находитесь в несколько ином окне, например, ARM, было бы хорошо прочитать справочную страницу для семейства вызовов exec - поведение по умолчанию.Вы можете вызвать ваш .profile, если вам нужно, так как system () принимает команду

system(" . myhome/me/.profile && /path/to/mycommand")
1 голос
/ 20 ноября 2010

Я перепутал переменные окружения, установленные для моего скрипта на в этом посте , где мне нужно было установить переменную env $ DBUS_SESSION_BUS_ADDRESS, но этого не произошло, когда я назвал скрипт как root.Вы можете прочитать это, но в конце вы можете проверить, содержит ли% ENV необходимые переменные и, если нет, добавить их.

От perlvar

   %ENV
   $ENV{expr}
           The hash %ENV contains your current environment.  Setting a value in "ENV" changes
           the environment for any child processes you subsequently fork() off.

Моя проблема заключалась в том, что я запускал скрипт под sudo, и он не сохранял все переменные env моего пользователя. Вы запускаете скрипт под sudo или как другой пользователь, скажем, www-data (apache)?

Простой тест:

user@host:~$ perl -e 'print $ENV{q/MY_ENV_VARIABLE/} . "\n"'

, и если это не сработает, вам нужно будет добавить его в% ENV в верхней части вашего скрипта.

0 голосов
/ 19 ноября 2010

попробуйте system("echo \$SHELL"); в вашей системе.

...