Какая оболочка использует вызов Perl system()?

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

system('myframework mycode');

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

Что я делаю неправильно?

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

Ответ 1

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

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

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

Ответ 2

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

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

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

system "/path/to/mysh -c 'mycommand arg1 ...'";

Ответ 3

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

$ 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

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

system(" . myhome/me/.profile && /path/to/mycommand")

Ответ 5

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

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

$ENV{PERL5SHELL} = "sh";

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

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

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

Ответ 6

Я перепутал с переменными окружения, установленными для моего script на этот пост, где мне нужно было установить переменную env $DBUS_SESSION_BUS_ADDRESS, но это было бы не тогда, когда Я назвал script как 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.

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

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

[email protected]:~$ perl -e 'print $ENV{q/MY_ENV_VARIABLE/} . "\n"'

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

Ответ 7

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