Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Executing scripts with ./ results in an error in Windows 11 #1660

Closed
SpacewaIker opened this issue Feb 20, 2023 · 12 comments
Closed

Executing scripts with ./ results in an error in Windows 11 #1660

SpacewaIker opened this issue Feb 20, 2023 · 12 comments

Comments

@SpacewaIker
Copy link

I'm trying to execute a gradlew file in a java project like so

❯ ./gradlew --version

The command/file part is highlighted in green, seemingly indicating that elvish knows what I'm talking about. However, when I execute this, I get:

'.' is not recognized as an internal or external command,
operable program or batch file.
Exception: ./gradlew exited with 1

I'm fairly sure that when I first installed elvish, executing scripts like this worked, but now it doesn't anymore. I honestly don't know what could cause this issue, which is why my description is so vague. Has anyone else had this issue? Should I just try to reinstall elvish? Thanks!

@krader1961
Copy link
Contributor

krader1961 commented Feb 20, 2023

Works for me. That is, I have no difficulty running external commands (programs) from an Elvish shell on Windows 11; even using a relative path:

elvish> cd c:\msys64\opt\bin
elvish> ./authtest
2023/02/20 14:47:11 authtest.go:39: usage: [GOAUTH=CMD...] authtest.exe URL
Exception: ./authtest exited with 1
[tty 195]:1:1: ./authtest

What version of Elvish are you running (put $buildinfo or elvish --version)? You say "executing scripts like this used to work". What does the first line of that script look like? Does the interpreter it presumably references exist? Also, the error message is weird since it should say './gradlew' is not recognized. Are you really at an Elvish prompt when you type that command?

@krader1961
Copy link
Contributor

@SpacewaIker, ping? Is this still an issue for you? If it is can you answer my questions from my previous comment? If this is no longer an issue for you it would be appreciated if you explained what the problem was and close this issue.

@SpacewaIker
Copy link
Author

I have elvish version 0.19.0-dev.0.20230119103625-1a5873eea523+official. The first line of the script is a sha-bang:

#!/bin/sh

Which I now realize probably doesn't work on Windows. After further testing, here's what I found:

With Powershell, running the ./gradlew script works, as does the ./gradlew.bat. I'm not sure if the sha-bang actually works or if it works only because Powershell has some aliases that makes it somewhat compatible with shell scripts.

With cmd, running ./gradlew or ./gradlew.bat does not work. And more interestingly, gives the error '.' is not recognized as an internal or external command, operable program or batch file., which is exactly the error given by elvish when I try to run the script. However, with cmd, I can run both scripts by removing the ./ (i.e., running gradlew or gradlew.bat works). I don't understand why running gradlew works though, because cmd is definitely not compatible with shell scripts, and I don't think the sha-bang should work.

With elvish, running either ./gradlew or ./gradlew.bat also does not work. And it gives the same error as cmd did, with the added Exception: ./gradlew exited with 1 \ [tty xx]:1:1: ./gradlew --version. But running the scripts without the ./ does not work either, as elvish is trying to run an executable with this name, and gives the error Exception: exec: "gradlew": cannot run executable found relative to current directory \ [tty xx]:1:1: gradlew --version.

I also tried writing a simple shell script for testing:

#!/bin/sh

echo "hello world"

But this one gives weird results: Powershell and cmd want to open the file in a new program (with a windows dialog) when executing the script, while elvish gives the error Exception fork/exec .test/sh: %1 is not a valid Win32 application. \ [tty xx]:1:1: ./test.sh.

So honestly, I'm not sure what's going on. It seems like elvish is trying to run scripts through windows cmd, which is failing because of the leading ./, which is required to elvish to execute the file as a script. But as I said, I didn't have this problem before, and scripts were executing as expected. Not sure what changed on my computer since then...

@krader1961
Copy link
Contributor

With Powershell, running the ./gradlew script works, as does the ./gradlew.bat

I'm pretty sure that when you type ./gradlew Powershell is actually running your "bat" file, not the UNIX script. Did you actually modify the UNIX script to do something distinct from the bat file that would enable you to verify it was actually executed?

And more interestingly, gives the error '.' is not recognized as an internal or external command, operable program or batch file., which is exactly the error given by elvish when I try to run the script.

No, it is not. This is what I see when I attempt to run a shell script with a shebang line on Windows 11:

elvish> cat x
#!/bin/bash
echo done
elvish> ./x
Exception: exec: "./x": file does not exist

So honestly, I'm not sure what's going on.

I understand what is happening on my system but do not understand what is happening on your system. Scripts with shebang lines do not work on Windows 11. At least not with Elvish. That's because on UNIX systems the shebang line is interpreted by the OS kernel. Elvish simply tells the OS kernel to execute the script and the kernel reads the first line, recognizes the shebang, and turns the execution request into /bin/sh ./gradlew. The Windows kernel does not recognize shebang lines. Shells like Bash provided by the MSYS2 project have special support for shebang lines (not to mention mapping paths like /bin/sh to c:\msys64\usr\bin\sh.exe).

I have a framework that I use for automating the building and unit testing of projects like Elvish on various virtual machines I run locally. Including a Windows 11 VM. For the Windows 11 system I explicitly execute statements like bash sync-home rather than just sync-home precisely because scripts with shebang lines do not work on Windows 11 when run from Elvish.

@krader1961
Copy link
Contributor

Also, Google for "windows script shebang" and you will find a lot of discussion about this topic. If your script has an explicit extension (e.g., .py or .sh) then you can configure Windows to recognize a "file association" between the extension and the interpreter to run when the file is executed. But that, obviously, doesn't work for a script without an explicit type extension.

@SpacewaIker
Copy link
Author

Yes, it does seem like running ./gradlew actually runs the batch file. I tried deleting the content of the UNIX script, and the command still worked. However, deleting the contents of the batch file makes the ./gradlew command not do anything.

As for the rest, firstly I appreciate the explanations, I'm not very knowledgeable about this kind of stuff and I like to learn more. Secondly, I tried downloading elvish v0.18.0, and the behaviour was different. With this version, running ./gradlew --version does not work either, and gives the same error message (which seems to come from cmd). However, I can run the script successfully by treating it like a command: gradlew --version. And this does not work if I'm in another directory, so it really is using the script, and not a command called gradlew that's on the PATH. And here too, it seems that it's the batch file that's being used, even if it's the UNIX script that's being called.

I do see something about executables on windows in the release notes for version 0.19.0, but it's listed as a bug fix and is related to command completion, so I'm not sure why the above works on version 0.18.0 but not 0.19.0.

Is it possible that this is a bug that was introduced in version 0.19.0? Maybe the way that the scripts are run by elvish is different and broke things on windows? Probably not, since you said you didn't have any issues running scripts from windows, but maybe I misunderstood. In any case, I can switch to version 0.18.0 for the time being and I'll see if the issue persists when version 0.20.0 comes out. I'd be happy to look into this issue further but as I said, I don't know much about shells and all of this stuff, and I don't know Go either...

@xiaq
Copy link
Member

xiaq commented Feb 26, 2023

@SpacewaIker Presumably .\gradlew still works?

The behavior you observed between 0.18.0 and 0.19.0 is likely caused by a Go standard library change (https://tip.golang.org/doc/go1.19#os-exec-path). When Elvish was compiled with an older version of Go compiler, it respected . in PATH, and thus supported gradlew. The Go standard library change causes . to be ignored.

That .\gradelew but ./gradlew doesn't seems to be a Go bug. I'll file one.

@xiaq
Copy link
Member

xiaq commented Feb 26, 2023

Filed golang/go#58743

@krader1961
Copy link
Contributor

you said you didn't have any issues running scripts from windows

My apologies, I did not mean to leave that impression. I was showing how I don't have any issues running programs (i.e., binary executables) using a relative path like ./ls. I then went on to explain that scripts do not work, using an implicit PATH lookup, relative path, or absolute path, because Windows does not support shebang lines. Elvish does, however, implicitly search for executables with a .bat or .exe extension. So when you type gradlew it is finding, and running gradlew.bat. And that works because of the association between the bat extension and the cmd shell.

@SpacewaIker
Copy link
Author

@xiaq Yes actually! I hadn't thought of using .\... And thank you for the explanation on the Go standard library change.

@krader1961 I see, thanks for the clarification.

So since .\ works, and the fact that ./ doesn't is because of Windows and/or Go, and not Elvish, then I suppose this issue can be closed! However, I do wonder: would it be possible to add something in my config file to make is so that when I type ./script, .\script is executed instead? And would this impact performance (for instance if it needs to check every command with regex before executing it)?

@xiaq
Copy link
Member

xiaq commented Feb 27, 2023

I can't think of a good reason why ./ shouldn't be supported, so it makes sense for Elvish to "fix" this quirk by rewriting / to \ in relative command paths.

@xiaq
Copy link
Member

xiaq commented Feb 27, 2023

This is something that PowerShell seems to do anyway, ./foo works there when you have a foo.bat in the working directory.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants