Почему 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.
обходные:
Windows лечит (AFAICT)
&&
такие символы, как bash - вы можете использовать его как разделитель команд, который будет выполнять команды до тех пор, пока команды будут успешнымиexec "git status && git add -A . && git status && git commit -m '$comment' && git push"
Поместите список команд в командный файл и вызовите
exec
на имя пакетного файла.Разделите команды на несколько вызовов, используя
system
(который возвращает) для всех вызовов, кроме последнего.system("git status"); system("git add -A ."); system("git status"); system("git commit -m '$comment'"); exec("git push");