-1

Recently put Strawberry Perl on a Windows 8.1 machine and discovered that exec behaves differently with v5.8.8 in git-bash at /bin/perl than with Strawberry at /c/strawberry/perl/bin/perl. Here is the very simply script I found this with (purely by accident when playing with $PATH):

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

This works fine with git-bash (/bin/perl), but when /c/strawberry/perl/bin/perl is found ahead in the $PATH the following error happens:

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

Did you mean this?
    status

The code is identical in both cases. My hunch is that perl 5.18 in strawberry has changed the behavior of the exec command itself, which has always been rather convoluted as it interprets arguments to it contextually (like perl loves to do).

My main concern is that somehow the two versions of perl render this rather simple bit of code incompatible between the perl versions and not some other simple system configuration issue, perhaps even an issue with the strawberry distro itself and not perl.

If this is a perl compatibility issue I am inclined to stick with v5.8.8, which does everything I'd ever want Perl to do for me (before going to another language).

Did the exec perl statement change between these versions? I can find no evidence on the Internet that it has.

To recreate this behavior:

install git-scm.org on a windows machine:

  • Download and install http://git-scm.org
  • Fire up the git-bash shell
  • Create a shell script and put the above code into it
  • Set execute permission with chmod 755
  • Ensure you are using /bin/perl with which perl
  • Execute the script

Then ...

  • Install Strawberry Perl
  • Set the $PATH to include /c/strawberry/perl/bin before everything else
  • Check it with which perl
  • Execute the same script

This is the best way to understand what is happening and why the difference matters. The implications are that standard perl script written for git-bash (v5.8.8) will not work with 5.18 in strawberry. My next step is to install perl 5.18 on a Linux machine and make sure it behaves the same as a 5.8.8 there. If anyone has done this already please let me know.

Note: Using another operating system, while I would prefer it, is not an option in this case since we do other game development on these same machines that requires Windows.

Note: I use Perl instead of Bash because my little hacks tend to grow. I use Perl instead of Python or Node or because Perl comes standard with git-bash and I therefore don't need another install on every student machine. I only put strawberry on there because I was looking to add back perlpod functionality that git-bash stripped.

To those who voted the question down. You simply prove why stackexchange is a poor excuse for accurate information and real help. Thank you for validating my decision to go back to IRC, where the real experts are, not those parading for a popularity contest.

robmuh
  • 3
  • 1
  • 2
  • 4

1 Answers1

6

It's not about your version of Perl, it's about bash versus the Windows command shell. Any version of Strawberry Perl is built to invoke the Windows command shell with calls like exec, system, and qx, and the perl that ships with git-bash is apparently configured to invoke a Unix-emulation environment. Perl built for Cygwin is another example of an interpreter that runs on Windows but sends external commands to a Unix-emulation environment.

The Windows command shell does not recognize the ; character to terminate/separate commands, like sh does, so you can't run a series of commands with exec on Strawberry Perl the same way you can on the git-bash perl.

Workarounds:

  1. Windows does treat (AFAICT) the && characters like bash does -- you can use it is a command separator that will keep executing commands as long as the commands are successful

    exec "git status && git add -A . && git status && git commit -m '$comment' && git push"
    
  2. Put the list of commands into a batch file, and call exec on the batch file name.

  3. Separate the commands into multiple calls, using system (which returns) for all of the calls except the last.

    system("git status");
    system("git add -A .");
    system("git status");
    system("git commit -m '$comment'");
    exec("git push");
    
mob
  • 110,546
  • 17
  • 138
  • 265
  • I believe this is very much about the version of Perl. Can you provide information supporting the statement that it is not? Yours is one possible solution (of many I was already aware of). But perhaps I have not communicated the point clear enough. The exact same code in a script works without a problem in the /bin/perl variant and fails when calling /c/strawberry/perl/bin/perl the same way. I appreciate what you are saying, but it does not address my primary concern, which is the difference between strawberry 5.18 and git-bash perl 5.8. – robmuh Jan 17 '14 at 20:28
  • You also refer to 'batch' files. The whole point of git-bash, for me, is to avoid the 'b' word entirely, which is in fact very possible. – robmuh Jan 17 '14 at 20:35
  • The difference is that `exec` (and `system`, `qx`, etc.) in Strawberry Perl send commands to the Windows command shell, and in the `git-bash` version it sends commands to a `bash` shell. The shells are different and use different syntax. – mob Jan 17 '14 at 20:35
  • 1
    @robmuh, mob is correct. `exec($shell_command)` necessarily requires a shell to execute the command. In unixy systems, `exec($shell_command)` is short for `exec('/bin/sh', '-c', $shell_command)`. On Windows systems, `exec($shell_command)` is short for `exec('cmd', '/x', '/c', $shell_command)`. (See output of `perl -V:sh`) As you might expect, `sh` and `cmd` commands have major syntax differences. – ikegami Jan 17 '14 at 20:36
  • 1
    It is complaining that the command `git status;` is not a valid git command. As @mob says this is a difference between `cmd` used by Strawberry and bash used by git-bash. What part of your questions is not addressed. – justintime Jan 17 '14 at 20:38
  • Have you tried it with both? If this is true this is reason alone not to use Strawberry for me. What you say about `exec($shell_command) being 'short for `exec('cmd', '/x', '/c', $shell_command)` is simply not true when running the `/bin/perl` that is included as a part of `git-bash`. This means either the perl bundled with `git-bash` has been modified to invoke `sh` instead of `cmd` or that strawberry is not observing the same things that `/bin/perl` does. – robmuh Jan 17 '14 at 20:46
  • 2
    @robmuh nothing **ever** uses the "parent shell". – hobbs Jan 17 '14 at 20:49
  • I do think we have identified the fundamental difference being that strawberry perl, even when invoked from a git-bash shell, still forces `cmd` as the shell, while the `/bin/perl` that ships with git-bash does not. This is the fundamental issue. – robmuh Jan 17 '14 at 20:52
  • @hobbs by 'parent shell' I was referring to the shell that contains the running perl script when the subshell is created with `exec`, which is often the case depending on the context detected by the `exec` function, which is why I asked in the first place because one possible reason is that this context detection has changed. – robmuh Jan 17 '14 at 20:58
  • 1
    @robmuh, Re "What you say about ... is simply not true when running the /bin/perl", that's because /bin/perl runs in a unix-emulation environement (msys? cygwin?). As such, it not actually running on Windows. – ikegami Jan 17 '14 at 21:00
  • Strawberry uses MinGW. – friedo Jan 17 '14 at 21:01
  • @friedo, The compiler doesn't matter. – ikegami Jan 17 '14 at 21:03
  • @ikegami have you actually installed git-bash and tried this? What you are suggesting is that calling /c/strawberry/perl/bin/perl is different than calling /bin/perl *from the exact same 'emulation environment' shell*. This would confirm that the Stawberry build is simply not observing the same things, which at this point I am confident is the case, but need to confirm by executing the same code on a linux machine with both versions of Perl. By the way, this isn't my first rodeo. :) I've been coding and writing about Perl since '94 (and cited in some books). – robmuh Jan 17 '14 at 21:03
  • @friedo I think you are onto something. Stawberry perl is somehow overriding the execution environment with it's own, MinGW probably instead of using the one it is called from. – robmuh Jan 17 '14 at 21:05
  • 1
    Yes,I use cygwin daily. If you launch a Windows application (e.g. Strawberry Perl) from inside the unix emulation, it will still be a Windows application. It will not know anything about any unix emulation. – ikegami Jan 17 '14 at 21:06
  • @robmuh, Strawberry Perl doesn't override anything. It's a build of Perl for Windows, not for cywgin/msys. If anything overrides anything, it's `/bin/perl` by creating a unixy OS environemnt for itself. – ikegami Jan 17 '14 at 21:07
  • I want to thank everyone for your contributions. I'll go ahead and add the best answer we've come up with as being strawberry forces it's own execution environment, which means exec() shells out to `cmd` instead of `sh` like the git-bash `/bin/perl` does. That is reason enough for me to never use Strawberry for scripts on windows that are called from git-bash. Thanks. – robmuh Jan 17 '14 at 21:08
  • @ikegami As you probably know, Cygwin is NOT msysgit at all. Cygwin uses POSIX compliant copies. MsysGIT uses Windows versions of the the same GNU command set. http://stackoverflow.com/questions/3144082/difference-between-msysgit-and-cygwin-git – robmuh Jan 17 '14 at 21:09
  • 1
    But your conclusion is correct: Running scripts designed for unix on a Perl built for Windows is a bad idea and should be avoided. – ikegami Jan 17 '14 at 21:09
  • No, MSYS and cygwin both provide Windows version of the GNU command set by compiling systems calls to a library that emulates a unixy system. – ikegami Jan 17 '14 at 21:10
  • @ikegmai I would agree with your 'bad idea' conclusion if I had not read elsewhere that one of the reasons git-scm.org uses msysgit the way it does is to include perl to fulfill some of the secondary dependencies to the whole git installation thing. In other words, they built perl into a windows version of msys with bash to make it work as a core dependency. It is very fair to say, then, that creating perl scripts for 5.8.8 in /bin/perl on git-bash is not only not a 'bad idea' it's expected by the very creators of git. Things get ugly because of Strawberry's Window-ish-ness, not git-bash. – robmuh Jan 18 '14 at 00:10
  • Msys and Cygwin are similar in which tool sets they provide, but the are fundamentally different at the core. See this thread for more on why: http://stackoverflow.com/questions/771756/what-is-the-difference-between-cygwin-and-mingw [Aside from my personal aversion for the bloated crap that cygwin has become. I don't have an hour to install it on every student work station. I can have students themselves (as young as 12) install git-bash in under 5 minutes and have.] – robmuh Jan 18 '14 at 00:13
  • @mob please accept my edits so I can approve of that answer with a little clarification. I don't care about the rep stuff. – robmuh Jan 18 '14 at 00:23
  • Please add the following as well perl -V:sh sh='/bin/sh'; /c/strawberry/perl/bin/perl -V:sh sh='cmd /x /c'; – robmuh Jan 18 '14 at 00:36
  • On Twitter @merlyn confirms the configvars cannot be changed. They are compiled in. This proves that the strawberry Perl interpreter has been compiled with 'cmd' as the shell, while the Windows git-bash that comes with git-scm.org has had 'sh' compiled in although they both run on Windows. The statements about 'cmd' always being the shell on windows are patently false as /bin/perl -V:sh clearly shows. You can have a unix perl on windows, just not Strawberry. Must stick with git-scm.org (msysgit) or the bloated cygwin that noobs still use. – robmuh Jan 19 '14 at 00:27