Почему perl exec() работает по-другому в v5.18.2 (клубника) и perl v5.8.8 (git-bash)?

Недавно поставил Strawberry Perl на компьютер с Windows 8.1 и обнаружил, что exec ведет себя иначе с v5.8.8 в git-bash на /bin/perl чем с клубникой на /c/strawberry/perl/bin/perl, Вот очень простой скрипт, с которым я нашел это (чисто случайно, когда играл с $PATH):

#!/usr/bin/env perl
my $comment = "@ARGV" || 'update';
exec "git status; git add -A . ; git status; git commit -m '$comment'; git push";

Это прекрасно работает с git-bash (/bin/perl), но когда /c/strawberry/perl/bin/perl находится впереди в $PATH происходит следующая ошибка:

git: 'status;' is not a git command. See 'git --help'.

Did you mean this?
    status

Код идентичен в обоих случаях. Я догадываюсь, что Perl 5.18 в клубнике изменил поведение exec сама команда, которая всегда была довольно запутанной, поскольку она интерпретирует аргументы ей в контексте (как это делает perl).

Моя главная проблема заключается в том, что две версии perl делают этот довольно простой фрагмент кода несовместимым между версиями perl, а не какую-то другую проблему простой конфигурации системы, возможно, даже проблему с самим клубничным дистрибутивом, а не perl.

Если это проблема совместимости с Perl, я склонен придерживаться версии 5.8.8, которая делает все, что я хочу, чтобы Perl сделал для меня (перед переходом на другой язык).

Сделал exec Perl оператор изменения между этими версиями? Я не могу найти никаких доказательств в Интернете, что у него есть.

Чтобы воссоздать это поведение:

установите git-scm.org на машине с Windows:

  • Загрузите и установите http://git-scm.org/
  • Запустите оболочку git-bash
  • Создайте скрипт оболочки и поместите в него приведенный выше код
  • Установите разрешение на выполнение с помощью chmod 755
  • Убедитесь, что вы используете /bin/perl с which perl
  • Выполнить скрипт

Затем...

  • Установите Strawberry Perl
  • Установите $PATH для включения /c/strawberry/perl/bin перед всем остальным
  • Проверьте это с which perl
  • Выполнить тот же скрипт

Это лучший способ понять, что происходит и почему разница имеет значение. Это означает, что стандартный Perl-скрипт, написанный для git-bash (v5.8.8), не будет работать с 5.18 в клубнике. Мой следующий шаг - установить Perl 5.18 на Linux-машину и убедиться, что он ведет себя так же, как и 5.8.8. Если кто-то уже сделал это, пожалуйста, дайте мне знать.

Примечание. Использование другой операционной системы, хотя я бы предпочел ее, в этом случае не подходит, поскольку мы занимаемся разработкой других игр на тех же компьютерах, для которых требуется Windows.

Примечание: я использую Perl вместо Bash, потому что мои маленькие хаки имеют тенденцию расти. Я использую Perl вместо Python или Node или потому что Perl стандартно поставляется с git-bash и поэтому я не нуждаюсь в другой установке на каждой машине ученика. Я положил туда только клубнику, потому что я хотел добавить обратно perlpod функциональность, которая git-bash раздел.

Для тех, кто проголосовал за вопрос. Вы просто доказываете, почему stackexchange - плохое оправдание для точной информации и реальной помощи. Спасибо за подтверждение моего решения вернуться в IRC, где настоящие эксперты, а не те, кто выставляет напоказ конкурс на популярность.

1 ответ

Речь идет не о вашей версии Perl, а о bash и командной оболочке Windows. Любая версия Strawberry Perl создана для вызова командной оболочки Windows с такими вызовами exec, system, а также qxи perl который поставляется с git-bash очевидно настроен для вызова среды эмуляции Unix. Perl, созданный для Cygwin, является еще одним примером интерпретатора, который работает в Windows, но отправляет внешние команды в среду эмуляции Unix.

Командная оболочка Windows не распознает ; символ для завершения / разделения команд, например sh делает, поэтому вы не можете запустить серию команд с exec на клубничном Perl так же, как на git-bash perl.

обходные:

  1. Windows лечит (AFAICT) && такие символы, как bash - вы можете использовать его как разделитель команд, который будет выполнять команды до тех пор, пока команды будут успешными

    exec "git status && git add -A . && git status && git commit -m '$comment' && git push"
    
  2. Поместите список команд в командный файл и вызовите exec на имя пакетного файла.

  3. Разделите команды на несколько вызовов, используя system (который возвращает) для всех вызовов, кроме последнего.

    system("git status");
    system("git add -A .");
    system("git status");
    system("git commit -m '$comment'");
    exec("git push");
    
Другие вопросы по тегам