19

On Windows, if I start c:\msys64\mingw64.exe, it opens a shell, where I can build my project, let's say by calling a release bash script (to simplify). Everything works fine.

Now, I would like to execute my release script on mingw64 directly, without interaction.

I tried:

c:\msys64\mingw64.exe /c/the/full/path/release

A window opens and closes, it does not work.

I attempted to use bash directly, but it seems the environment is not correctly set:

> c:\msys64\usr\bin\bash -c ls
/usr/bin/bash: ls: command not found

> c:\msys64\usr\bin\bash -c /bin/ls
... it works ...

So it is obvious that the environment is not the same as when execute c:\msys64\mingw64.exe then call ls.

How to execute my release script as if I were in the shell started by mingw64.exe?

rom1v
  • 2,752
  • 3
  • 21
  • 47
  • Try this: `msys2_shell.cmd -mingw64 -c "help |more"` – KonstantinL Nov 22 '17 at 16:00
  • @KonstantinL this helps, I can execute my script, but 1) the environment is still not the same (e.g. it does not find meson, while it finds it in a mingw64 shell), and 2) it opens a new window. – rom1v Nov 22 '17 at 16:17
  • I already posted my answer, but I'd like some clarification about your "new window" complaint. Do you want any window to show up at all? What happens if your script has an error and you want to see what the error is? – David Grayson Nov 23 '17 at 05:25
  • @DavidGrayson Thank you for your long answer, I will read it carefully. About not having a window, I would like to execute the script from another program (e.g. jenkins) and retrieve its output programmatically (like I would do with any "native" script not using msys2). – rom1v Nov 23 '17 at 07:31
  • 1
    You didn't mention that in your question. The command to run from Jenkins would probably be something like the one in my answer except you remove everything before `/bin/env` and replace `/bin/env` with an absolute Windows-style path to the same program. Running mintty probably prevents you from getting the output. – David Grayson Nov 23 '17 at 08:09
  • You're right, my question was not clear enough. I wanted to give only minimal information to avoid many irrelevant details. Thank you very much! – rom1v Nov 23 '17 at 09:12

4 Answers4

20

To run a Bash shell script in MSYS2 without showing a window, you should right-click on your Desktop or somewhere else in Windows Explorer, select "New", select "Shortcut", and then enter something like this for the shortcut target:

C:\msys64\usr\bin\mintty.exe -w hide /bin/env MSYSTEM=MINGW64 /bin/bash -l /c/Users/rom1v/project/release.sh

Note that there are 4 paths in here. The path to mintty and release.sh are absolute paths that you will need to adjust. The paths to env and bash are relative to your MSYS2 installation directory. Note also that the first path must be a standard Windows path, since Windows expects that when it is running a shortcut.

Explanation

It might seem odd to use MinTTY for a non-interactive script, but we need to use some program that was compiled for the Windows subsystem (-mwindows option to GCC), or else Windows will automatically start a new console when we run the program. We pass the -w hide option to MinTTY to tell it not to actually show a window. Everything after that option is interpreted by MinTTY as a command to run.

So MinTTY will run /bin/env from the MSYS2 distribution and pass the remainder of the arguments on to it. This is a handy utility that is actually a standard part of Linux as well as MSYS2. It sets the MSYSTEM environment variable to MINGW64 (which is important later) and then it runs /bin/bash with the remainder of the command-line arguments.

We pass -l to Bash so that it acts as a login script, and runs certain startup scripts. In particular, the /etc/profile script from MSYS2 is essential because it looks at the MSYSTEM environment variable, sees that it is MINGW64, and then sets a bunch of other environment variables (e.g. PATH) to give you the MinGW 64-bit shell environment.

Finally, we pass the name of your script as the main argument to bash, so it will run that script after running the initialization scripts.

Error handling

Note that if your Bash script has an error, you won't get any notification, because the shortcut above doesn't open any console windows. I personally would find that pretty annoying. I'd probably remove the -w hide option, then make a wrapper bash script that just does something like:

run_my_main_script || sleep 10000

So if the main script is successful, exit right away, otherwise keep the window open for 10000 seconds. You don't have to even put that wrapper script in its own file, you can just put it in the shortcut as the argument to Bash's -c option (don't forget to wrap it in double quotes).

David Grayson
  • 84,103
  • 24
  • 152
  • 189
  • Please take note that `-w hide` still unfocuses the current window, at least in my case it does. I am still searching for a solution to prevent this to let it keep the focus on its current program. – Menno van Leeuwen Apr 27 '20 at 18:08
8

Thanks to the answers from @David Grayson, I managed to call my release script with msys2/mingw from a Windows console (cmd), with additional directories (for Java and Meson) in $PATH:

c:\msys64\usr\bin\env MSYSTEM=MINGW64 c:\msys64\usr\bin\bash -l -c "PATH=\"/c/Program Files/Java/jdk1.8.X_XXX/bin:/c/Program Files/Meson:$PATH\" /c/Users/rom1v/project/release"
rom1v
  • 2,752
  • 3
  • 21
  • 47
3

Another way of doing it is using the msys2_shell.cmd launcher on MSYS2' installation folder. Assuming that it was installed to the default folder, the command goes:

C:\msys64\msys2_shell.cmd -defterm -no-start -mingw64 -here -c "your command here"

The option -defterm sends the output to the current terminal, -no-start makes so a new terminal window is not opened, -here makes the current directory as the working directory, -mingw64 is the environment to use (other possibilities are -mingw32, -ucrt64, -clang64), and -c is your shell command itself.

0

add an supplement to the above: if u want to the output of shell script

  • reference:https://mintty.github.io/mintty.1.html

-l, --log FILE|-

Copy all output into the specified log file, or standard output if a dash is given instead of a file name. (Implies -o Logging=yes.)

If FILE contains %d it will be substituted with the process ID. See description of equivalent option "Log file" (Log=) below for further formatting options and hints.

Note that logging can be toggled from the extended context menu.

Add A complete example:

C:\msys64\usr\bin\mintty.exe -w hide -l - c:\msys64\usr\bin\env MSYSTEM=MINGW64 c:\msys64\usr\bin\bash -l -c "PATH=\"$PATH\" /C/Users/Administrator/Desktop/myProject/Demo_C_C++/shell/textProcess/bookNoteHandler.sh" | find /v "/v:Displays all lines that don't contain the specified"

=========

enter image description here