-
Notifications
You must be signed in to change notification settings - Fork 7.3k
child_process.spawn ignores PATHEXT on Windows #2318
Comments
@OrangeDog as a workaround, you could use
(this option is internal and not guarateed to stick btw) |
Not very helpful for writing portable code though. |
@OrangeDog Well you can't really write a portable batch file anyway. @DrPizza suggested today that we could add a |
It'd be superfluous on Unices - the two things a shell script needs is a valid shebang and the executable bit set. |
@bnoordhuis not completely because people may want to do |
If I can interject into this conversation; the shebang indicates which executable will actually run the file and the executable bit flags that the user (or a user) has granted permission to run the file (probably why auto-executing of shell scripts in the Windows %PATH% was objected to before, since there's no executable bit there). Perhaps a Basically, the shebang line is invalid syntax in Javascript, but Node.js tolerates it because Unix shells will automatically interpret that line and pass the file to the specified program -- but then that means you can't use that JS file in a browser without modification. A developer using browser-require might instead prefer to spawn the script with EDIT: Of course, in Unix, a shebanged shell script could still be run the normal way. |
@piscisaureus but you can write batch/perl/etc. scripts to allow I thought the whole point of adding libuv was to give portable cross-platform support. |
@piscisaureus Is this still an issue? |
@bnoordhuis It is. |
I think @piscisaureus's suggestion is on to something. It's kind of annoying right now that there's a "run in a shell" function that buffers the output (exec), and a "run as-is" option that doesn't (spawn), and a "run as-is" that buffers the output (execFile), but no "run in a shell" that doesn't buffer the output. However, it can't be What about this? child = child_process.spawnShell('util.bat glerp gorp', {options...}) Which would be sugar for: child = child_process.spawn(isWin ? 'cmd' : 'sh', [isWin?'/c':'-c', arg], options) |
So, I don't understand anything about shells on Unix, so take this with a grain of salt. In particular I don't understand how But for me the problem is that there is lots of published code out there that is not cross-platform because of this. (npm with git and npm-www with couchdb recently, but much more I've seen) A fix that retroactively makes all that code work would be ideal, instead of throwing a new method in the already-confusing medley of So I'd say
is the most useful thing I've seen so far. Alternately, if there's an alternative to the |
@domenic If we start wrapping every command in a shell, then that's not so great. |
@isaacs I see. Then that seems like a fairly orthogonal concern to the fact that Windows executables come in many flavors (exe, bat, cmd, etc.). People using It sounds like
case, but regardless I think |
libuv used to use PATHEXT, but this was reverted in joyent/libuv@8ed2ffb because it didn't work for non-exe files. I would be ok with putting this back in and running all non-exe files with "cmd /c". I take patches. (Note that the escaping rules are quite complicated when running stuff with |
@piscisaureus Would using Otherwise, if I were to work on a patch for this, would you suggest it as a libuv patch or Node patch? Probably libuv, right? |
@domenic Afaik ShellExecuteEx doesn't allow redirection of stdio handles. |
The problem seems to be that child_process got a bit muddied up trying to handle some of these cases for shell commands, but we've reached a point where it's getting uncomfortable to continue to add shims in there to support more shell-friendly options. I don't think this is a cross-platform problem. It's a problem of executables vs. shell scripts. This isn't a problem for most Unix devs, because they already know the difference between the two. I'm primarily a Windows guy myself, but it doesn't seem fair that Windows should get special treatment at the child_process level just because cmd and bat files are treated as shell commands by the OS. Windows devs will just need to learn the difference between an executable and a shell command for their platform. (This isn't just a problem with Node, BTW. I've seen this play out in other platforms, too.) We need to respect Windows's idea of what is executable, and what is not, and be careful not to break that. I initially liked the idea of adding a {shell:true} sort of option to spawn(), but after looking at the code, I'd expect it to be supported in exec() and execFile(), too, and that would break things. (We could have different defaults for spawn() and exec(), but that's still pretty confusing.) Rather than try to make the mess of spawn(), exec(), and execFile() do even more black magic, and risk making things even more unclear, I'd prefer that we keep things honest and add @isaacs's suggestion of adding a spawnShell() method. If we clean up the docs a bit, and make it more clear what each of these methods does, we've got a shot at having a fairly complete set of use cases. In the long term, it might be worth considering the deprecation of exec() and execFile(), in favor of a set of functions with a more deliberate separation between executables and shell commands. The code would get a lot cleaner, and with just slightly better documentation and error messages, it would also be an easier API for new developers to understand. |
bump |
I'd like to add my 2 cents with regard to using
on windows. This is giving me a real headache as doing this with long running processes results in those processes being orphaned when I call See this gist for an example: https://gist.github.com/4117163 I'm still trying to figure out if this is a bug that should be raised separately (child.kill seems to deliberately not kill grandchildren (which is annoying also) and this might be considered a grandchild) |
For example
require('child.process').spawn('mycmd')
won't findC:\util\mycmd.bat
when PATH containsC:\util
and PATHEXT contains.BAT
.Ye olde code (https://github.com/joyent/node/blob/v0.4/src/node_child_process_win32.cc) looks like it would have worked, but I have no idea where the v0.6 equivalent is.
The text was updated successfully, but these errors were encountered: