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

Already on GitHub? Sign in to your account

please remove `node` symlink from iojs installer #796

Closed
sintaxi opened this Issue Feb 11, 2015 · 60 comments

Comments

Projects
None yet

sintaxi commented Feb 11, 2015

Is there a good reason the iojs installer creates a node symlink? Its seems quite invasive to me and not in the spirit of being a good open source citizen so I'm hoping there is a good reason for it to be there. If not, please remove it.

Apart from it being inappropriate its also inconvenient as I'm sure many people want to dabble with iojs while maintaining their production NodeJS systems. This makes it more challenging and will create unexpected behaviour for those who do not read the installer process.

banners_and_alerts_and_install_io_js_and_downloads

#389 #631 #776 and probably a shitload of others.

Owner

targos commented Feb 11, 2015

If you need Node.js and io.js to coexist on your system, you can use nvm

sintaxi commented Feb 11, 2015

Is it really to much to ask for an explanation for this? What purpose does this symlink serve?

I would like to switch https://github.com/sintaxi/harp to iojs but this is preventing me from doing that as I'm not comfortable forcing the harp community to abandon NodeJS. This behaviour hostile and unprofessional and the lack of explanation leads me to believe this "feature" is self-serving and not operating in good faith. Please don't dismiss this without an explanation as to why iojs feels compelled to override competing binaries on my machine.

This does seem like a good case for a simple confirmation in the installer as to whether or not you want the symlink

@sintaxi I think the explanation is here: iojs#249 (comment) (and there's an even longer discussion at iojs#631)

Owner

targos commented Feb 11, 2015

It is like MariaDB vs MySQL : io.js is a replacement for Node. Too many modules/scripts rely on the node executable.

Member

vkurchatkin commented Feb 11, 2015

This was closed primarily because it is a duplicate. You can find extensive explanation in linked issues

Member

vkurchatkin commented Feb 11, 2015

@sintaxi your harp project relies on this as well as many other packages: https://github.com/sintaxi/harp/blob/master/bin/harp#L1

sintaxi commented Feb 11, 2015

Harp is asking for NodeJS because that is what it depends on.

I would like Harp to depend on iojs instead but I'm not going to force the entire Harp community to abandon NodeJS just because Harp wants to use iojs. I can't in good conscience force this decision on them because its not my place to make that decision for them.

Owner

Fishrock123 commented Feb 11, 2015

@sintaxi io.js symlinks to node so that it is usable as node, and so that your files with #!/usr/bin/env node will not break.

sintaxi commented Feb 11, 2015

@vkurchatkin btw - thanks for the explanation. If you prefer to close this ticket I can move discussion to issue #249

sintaxi commented Feb 11, 2015

@Fishrock123 I understand the explanation it just isn't based on facts. If the user has NodeJS installed which is what the script is asking for, it will run just fine. In reality the scripts are much more likely to break if some systems run node as nodejs and others run iojs.

Member

indexzero commented Feb 11, 2015

@Fishrock123 what about a bin shim that would run iojs or node depending on external config? Or maybe at least making this an option in the installer?

Owner

Fishrock123 commented Feb 11, 2015

@sintaxi considering the aim is to keep backwards compatibility, how is this more of an issue than upgrading to 0.12?

@indexzero not sure, I'm probably not the best person to cc for that. :)

Member

kenperkins commented Feb 11, 2015

There's also a significant amount of commentary in #43

Member

Qard commented Feb 11, 2015

If you want to know why the symlink is required, try removing it and seeing just how broken everything in the ecosystem gets. So many things assume the binary name is "node" that, if we want to maintain compatibility, we have to use the same name or the vast majority of tools are just plain broken.

There may be some clever way to make a wrapper script that can figure out what to run from some environment variable hack, but I don't think it'd be much less intrusive than just using a version manager, like nvm.

Really, I think the solution is just to merge back with node.js at some point and forget all this symlink nonsense. The new foundation is a good step in that direction, but it needs further evaluation to see if merging aligns with the goals of io.js.

sintaxi commented Feb 12, 2015

@Fishrock123 its in issue because the script is asking to use the node runtime not iojs. But users cant even have both installed along side each other. This is makes scripts far more likely to break and much more difficult to debug when users run into issues. Q: "Which version of node are you running? can you run node --version for me?" A: "it says I'm running node version 1.0.0", Q: "cool, is that node node or iojs node? ?" A: "Wut?".

Member

indexzero commented Feb 12, 2015

@Qard as the author of one of the most globally installed modules (forever) I can say with certainty that the symlink is necessary. I (and authors like me) do not want to change how our main executables are structured

sintaxi commented Feb 12, 2015

If you want to know why the symlink is required, try removing it and seeing just how broken everything in the ecosystem gets. So many things assume the binary name is "node" that, if we want to maintain compatibility, we have to use the same name or the vast majority of tools are just plain broken.

Removing the symlink only breaks my node scripts because iojs chose to clobber my node binary on install. Currently the best way to avoid these problems is to not install iojs in the first place.

If this is a package ecosystem issue than lets raise awareness and get people to update their modules to something that is sustainable. People will update because those that don't will get left behind.

Member

vkurchatkin commented Feb 12, 2015

io.js is a version of node. saying that it clobbers node binary is the same as saying that node 0.12 clobbers node 0.10 binary. If you need multiple versions on the same machine you can use nvm

sintaxi commented Feb 12, 2015

@vkurchatkin This has nothing to do with MY needs.

If I tell users to install iojs because my modules depend on it than I am forcing NodeJS OFF other peoples machines which does not sit well with me. If you are saying you understand and that is something iojs is cool with than I suppose this discussion has come to an end but in my view that makes iojs a virus and not a suitable dependency for my project.

I would be profoundly disappointed if this is the case as I feel this project shows a lot of promise.

Member

vkurchatkin commented Feb 12, 2015

@sintaxi I'm not sure what your needs are. I've tried running harp on io.js 1.2.0 and everything seems to work fine. FWIW I'm for adding option not to create symlink to installer. But it obviously makes io.js not compatible with existing ecosystem

sintaxi commented Feb 12, 2015

I'm not sure what your needs are. I've tried running harp on io.js 1.2.0 and everything seems to work fine.

The problem I see is you may now have other projects on your system that don't work because you clobbered node by installing iojs. That is the concern I have. If I instruct users to install iojs they are (in most cases unknowingly) clobbering their NodeJS binary and I have doubts this behaviour would be expected.

If iojs wants to install to its own namespace and leave the rest of the system alone like every other program then Im a happy camper and iojs becomes an appealing dependency.

Owner

Fishrock123 commented Feb 12, 2015

Removing the symlink only breaks my node scripts because iojs chose to clobber my node binary on install. Currently the best way to avoid these problems is to not install iojs in the first place.

0.12 will do the same.

If I tell users to install iojs because my modules depend on it than I am forcing NodeJS OFF other peoples machines which does not sit well with me.

0.11 and 0.12 modules also do this. Tell people to use a node version manager.

If you are saying you understand and that is something iojs is cool with than I suppose this discussion has come to an end but in my view that makes iojs a virus and not a suitable dependency for my project.

By definition, io.js is neither malware, nor a computer virus.

io.js is a version of node. Period.

Owner

Fishrock123 commented Feb 12, 2015

If iojs wants to install to its own namespace and leave the rest of the system alone like every other program then Im a happy camper and iojs becomes an appealing dependency.

See the above. io.js is a version of node.

sintaxi commented Feb 12, 2015

io.js is a version of node. Period.

This is disingenuous to say the least. Why then do we create an iojs binary if iojs is a version of node?

I think this project deserves more credit than you are giving it and this is putting far too much stock into the "node" name. I believe io.js can stand on its own and win the community over it doesn't need to stoop to these hostile tactics.

Yes modules will need to be updated but that is not as big of deal as its being made out to be. Most people already have node installed and will likely for quite sometime. Forcing people to pick a side is not putting the community first. There is no need for a standoff.

Contributor

jmar777 commented Feb 12, 2015

io.js is a version of node. Period.

Not really in any meaningful sense. This may be more true-ish if there was a stated compatibility goal (which seems to have been abandoned, from what I can tell?). As it stands, there are already breaking differences between iojs and node. And barring any progress on the reconciliation front that also results in API reconciliation (or whatever a better term for that is), it seems a bit reckless to just assume that they're interchangeable. That may have been 99% "ok" for the initial release (and making NPM work out-of-the-gate), but it ultimately seems short-sighted as API decisions continue to diverge over time.

Member

vkurchatkin commented Feb 12, 2015

As it stands, there are already breaking differences between iojs and node

Can you name some? io.js 1.x.x is supposed to be fully backwards compatible

Contributor

jmar777 commented Feb 12, 2015

Can you name some?

The differences in V8 (and hence supported language features and native bindings) alone constitute a breaking change.

io.js 1.x.x is supposed to be fully backwards compatible

Where do you see that? The closest I can find is that it is "compatible with the npm ecosystem", which I don't even know what to make of, considering people host everything from node modules to strictly client-side libraries in there.

Regardless, backwards compatible isn't the same thing as "interchangeable", but it may be a strong enough claim to at least shut me up over this particular concern. Would you mind referring me to where that claim is made?

Contributor

jmar777 commented Feb 12, 2015

FWIW, I am having trouble finding a more compelling example of breaking changes between the two. I thought I had seen a few come up, but I can't locate them at the moment. Either way, whether it's true today or not, the backwards-compatibility claim for the future would be reassuring.

sintaxi commented Feb 12, 2015

iojs supposedly being backward compatible is not the primary issue for me. Regardless how great Firefox might be if its installer removed IE from my system I would be very put off. In my opinion this does fit the definition of malware.

The problem is we are fudging the users system and removing control from library authors by not allowing them to choose the runtime that suits the program they write which means authors will have to write to the lowest common denominator. Why needlessly impose this problem on the server when it doesn't have to be the case?

Contributor

naholyr commented Feb 12, 2015

If node is already installed, is the symlink created anyway?
If iojs is installed, does the node installer overwrite the binary?

If no and yes, there is no issue here.

@naholyr The answers are YES and YES and Node.js does the same thing.

@sintaxi If you have both installed that would also break it without an NVM. Furthermore, to not "clobber" the Node instillation would make people think you can use both without a NVM which is not possible. This is not a hostile tactic this is just the fact that they can't be used together without a NVM.

Also, you do not need to change you reference due to the symlink. That way users can make a choice of which they will use. If you want you can include a recommendation for io.js but if that bothers you don't or include a warning.

Contributor

naholyr commented Feb 12, 2015

Then wouldn't a good solution be the installer not to overwrite existing node binary?
If there is already a node binary, chances are you just want to test iojs, and especially not screw your existing configuration.
If there is none, obviously creating one looks like the only good idea.

How about that? default = do not overwrite + maybe a checkbox to change that.

Anyway I join the "use nvm" voices: I think it's already mandatory when working with node itself only.

@naholyr The problem is if you don't overwrite the node binary neither will work.

schme16 commented Feb 12, 2015

As echoed several times throughout this discussion, if you need them side-by-side, then you really have to use a NVM. That being said, the aim of iojs wasn't ever to be a new product with the intention of competing, it was to be a test ground that could be used to accelerate progress and introduce new features faster, safely (as most people would be using it in production already) and in a more iterative and predictable release schedule than how Joyent had been with NodeJS. I'd really suggest listening to NodeUp Podcast #81 as the had on Mikeal Rogers and Isaac Schlueter (iojs founders) and Chris Dickinson (of Wallmartlabs) where they basically only see the project continuing in its current for or a year or two, and that they wanted to get to a position that all the great things learned and contributed to iojs would be accepted and merged back into NodeJS core (Joyent permitting, which now that they have set up a foundation to oversee Node I cannot image them being opposed to).

On the question of hostility: iojs is not trying to steal consumers away from node, its first few releases (nightlies) didn't include the symlink, and so much was borked, as soooo many (too many to expect people to change overnight) modules require the node bin. I ABSOLUTELY agree that a checkbox should be added to the installer to allow you to not have the symlink (stubbed exe on windows) installed with the rest of iojs, but node (and therefore iojs) is supposed to be easy and just work, and therefore its good practice to default the symlink on.

tldr; you aren't meant to have both installed and expect them to work together, and if you find a situation where you do need to, you should be using nvm. iojs isn't being hostile it's being practical.

Owner

Fishrock123 commented Feb 12, 2015

Not really in any meaningful sense. This may be more true-ish if there was a stated compatibility goal (which seems to have been abandoned, from what I can tell?). As it stands, there are already breaking differences between iojs and node. And barring any progress on the reconciliation front that also results in API reconciliation (or whatever a better term for that is), it seems a bit reckless to just assume that they're interchangeable. That may have been 99% "ok" for the initial release (and making NPM work out-of-the-gate), but it ultimately seems short-sighted as API decisions continue to diverge over time.

The exact same problems occur from any major node version bump. (or minor, in Node.js land)

Member

therebelrobot commented Feb 12, 2015

Forcing people to pick a side is not putting the community first. There is no need for a standoff.

Like the standoff between 0.10 and 0.12. Or 0.8 and 0.10. If a user doesn't understand the nature of versioning and how different versions could override another, maybe they shouldn't be working in the industry. Yes, maybe there should be more documentation on how to have concurrent installs properly, that is something we as the website working group can take a look at (We're already talking about implementing a guide section). Yes, maybe there should be a checkbox to not override the node if already installed. But to call the entire project hostile, disingenuous and creating a standoff is hyperbolic at best.

Member

kenperkins commented Feb 12, 2015

There are probably 2 issues here really:

  1. Supporting multiple versions of node & iojs on the developer environment. I assert this is the domain of version managers like nvm. I would never use a .dmg to install node or iojs on my dev machine.
  2. Supporting multiple versions of node & iojs in production environments. This is a bit more complex:
    • Use containers to sandbox specific applications to a matching version of the runtime
    • Use individual computers or VMs to the same end
    • Install different binaries to different paths on a single machine and leverage them explicitly at application invocation. this is probably not worth the trouble considering how easy containerizing an app is
    • other?

Either way, the same problems exist whether you're using node v0.10 and v0.12 or node and iojs. This is not exclusive to iojs.

ljharb commented Feb 12, 2015

When you use npm or a global module name on the command line, which one wins? You'd have to manually set up your PATH to decide that (or else both node and iojs' installers would have to work around each other to provide the option, so I don't think that's tenable). What happens when you have two (conflicting) versions installed of a global module, one on node and one on iojs? What happens when you npm install -g something, and it installs to iojs, and the one in node's npm root -g gets shadowed?

I can't understand why anyone would expect to be able to use iojs and node at the same time on the same shell, nor how it would work in an intuitive, unsurprising, and robust fashion.

Contributor

jmar777 commented Feb 12, 2015

The exact same problems occur from any major node version bump. (or minor, in Node.js land)

Having thought on this some more and reading over the comments, I think this makes more sense that I was initially giving it credit for. I do think this needs better communication and stronger guarantees, though (even/especially in the installer). It's not really fair to shrug this off as an analog for node clobbering another version of node:

  • It's almost universally expected for new versions of an app to clobber old versions of the same app (whereas it's almost never expected where the apps differ).
  • When upgrading node, the backwards compatibility situation is both documented and implicit in the version system.
  • I still haven't found any form of documentation stating in which cases iojs is drop-in replacement for node (where drop-in implies backwards-compatibility). Maybe that's a safe and/or implicit guarantee in all versions of iojs right now? If so, that needs to be more clearly documented. Regardless of the current state, though, I'll reiterate my request for if/where that guarantee (or at least stated intention) is being made for future versions. As it stands, I can't point to anything anywhere that says "the current version of iojs will always attempt to be a safe drop-in replacement for any version of node" (or perhaps a more qualified version of that, if necessary). Without something to that effect, it's necessarily scary for it to clobber node. I realize that without doing so, it breaks iojs. I'm just asserting that's not a valid enough reason to break node instead, without providing a clear reason why and providing a guarantee about whether or not that's a safe thing to do.

TLDR:

  • I agree with iojs clobbering node by default now (yay)...
  • ...but only with much better communication about why...
  • ...and some explicit, clear documentation about what the backwards-compatibility goals/guarantees are.

I realize this isn't the tone or spirit of the message, but I feel like what's currently being communicated is "we don't want to break our binary, so we'll replace (break) the other one instead, but don't worry because it will maybe/possibly/probably be a good drop-in replacement". I'm just looking for something more clear than the maybe/possibly/probably part. And for all I know, that's already very clearly documented somewhere - I just can't find it if it is.

Thanks :)

I really don't like symlink for node either. Not only does this break node installs, but It requires that iojs mirror all expected behaviour for node. Correct me If I'm wrong here, but If someone writes a module that contains a call to node, shouldn't we expect node to be used? I'm talking about modules that are either globally installed, or have package scripts. If these modules we're built with node, then maybe they should be run on node. The same can be said for new modules that are authored against iojs. As far as I know this doesn't affect modules that are required by a script, am I correct? If someone wants to use modules that were written for node on iojs, or vice-versa then let them symlink manually. It may suck that you have to install node for older global modules, but for the sake of sanity, we shouldn't be touching other binaries.

I would add it's probably better to allow module authors to add iojs support rather than try to shoe horn the support for them in this way.

Member

mikeal commented Feb 13, 2015

but It requires that iojs mirror all expected behaviour for node

This is a given no matter what. In order to remain compatible with all the modules in npm we can't break backwards compatiblity with old versions of node.

Correct me If I'm wrong here, but If someone writes a module that contains a call to node, shouldn't we expect node to be used?

This is actually very similar to what happens with different implementations of the jvm, all of which clobber the java binary.

Member

kenperkins commented Feb 13, 2015

Edit: Considering @mikeal's comment below this speculation on my part is not particularly accurate

I think we could more explicitly declare a philosophy that's close to MariaDBs:

MariaDB is a community-developed fork of the MySQL relational database management system intended to remain free under the GNU GPL. Being a fork of a leading open source software system, it is notable for being led by the original developers of MySQL, who forked it due to concerns over its acquisition by Oracle. Contributors are required to share their copyright with the MariaDB Foundation.

The intent is also to maintain high compatibility with MySQL, ensuring a "drop-in" replacement capability with library binary equivalency and exact matching with MySQL APIs and commands. It includes the XtraDB storage engine for replacing InnoDB as well as a new storage engine, Aria, that intends to be both a transactional and non-transactional engine perhaps even included in future versions of MySQL.

Minor edits with s/MySQL/node and s/MariaDB/io.js:

io.js is a community-developed fork of the node.js javascript runtime intended to remain free under the MIT license. Being a fork of a leading open source software system, it is notable for being led by many of the original developers of node.js, who forked it due to concerns over its direction by Joyent. Contributors are required to share their copyright with the MariaDB Foundation.

The intent is also to maintain high compatibility with node.js, ensuring a "drop-in" replacement capability with library binary equivalency and exact matching with node.js APIs and commands.

I do wonder if that statement is actually part of the official plan of record, however.

Member

mikeal commented Feb 13, 2015

@kenperkins I have some similar language about ensuring compatibility in the roadmap and in the stability policy. The problem we have is that while we are compatible with node 0.12.0 JS API (not C++ because of the difference in v8) and not entirely with 0.10.x because of some differences (improvements) in streams, we still can't say we will ensure compatibility with 0.12.x because Joyent could add modified versions of our API additions or change behavior in a point release (there is no official policy they are committed to on this). All we can really say is what we've already stated in the stability policy which is that we won't break compatibility with prior releases on the JS side.

Member

kenperkins commented Feb 13, 2015

I'll have to make sure I don't re-use the MariaDB analogy then, considering that. Thanks for the clarification.

iamale commented Mar 5, 2015

@targos Thanks for the nvm advice!

Sorry to ressurect this thread, but can't io.js replace the node executable by an executable that will first check if another version of Node is installed and use that, otherwise it uses iojs?

That way, programs that strictly depend on iojs can use #!/usr/bin/env iojs, and iojs will try to run Node scripts if NodeJS itself is not present.

I honestly do not understand why no one is discussing this possibility. It seems like the most obvious one to me. I'm not saying it's perfect; it just seems the best to me. A version manager would be great, if only version managers didn't tend to suck so bad. They're my main grudge against Python and Ruby. I really didn't want to see Node going that way.

@indexzero, what do you think of that?

Edit:

Are packages compiled for iojs via npm installed on a special iojs directory or are they stored on the same directory Node uses? If the latter, than more would need to be done to get both to work side-by-side.

Owner

rvagg commented Apr 28, 2015

replace the node executable by an executable that will first check if another version of Node is installed and use that

So, if we overwrite an existing node installation with an executable, what is there to detect, since the previous one has been removed?

schme16 commented Apr 28, 2015

@rvagg: I think what @n2liquid means, is to replace the node binary inside the iojs directory with a binary that first checks if there is an existing node installation, and only links to the iojs binary when there isn't an existing node installation (feel free to correct me @n2liquid).

(@rvagg: totally off topic, but I loved the the latest NodeUp - Never enough of us ANZAC's around, haha)

Owner

rvagg commented Apr 28, 2015

"iojs directory" only makes sense on Windows, everywhere else it's a shared PATH space like /usr/bin or /usr/local/bin where you have only one of a thing with a particular name.

schme16 commented Apr 28, 2015

@rvagg: ahh, that's true, my Windows past is showing; feel free to ignore me.

@rvagg: So I trust it you've considered deeply the possibility of replacing the node executable with a delegator script and to the best of your knowledge it's not viable, correct?

This is tough. I know it is. But it's insane to think there isn't a simple solution to it. GNU has come a long way, and there's still no easy way to handle this? This doesn't look like an uncommon scenario: Two or more packages offer the same executable. User can select which one he wants at anytime and if the one in use is removed, it falls back to another one, until there is no more options left; then the executable is gone.

I think I've seen some package managers offering such a feature (Portage?), but not all.

Owner

rvagg commented Apr 28, 2015

Debian-based systems do it with alternatives but that needs to happen at a package-level, we're considering this over at https://github.com/nodesource/distributions but we have enough on our plate right now that it's not a high priority.

OS X installers are pretty rudimentary and I really don't know what the state-of-the-art is there (or if there is such a thing - they don't even do "uninstallers" on OS X).

Windows is ironically best placed to do this easily given the mechanism you're proposing.

However, what you've suggested involves a lot of magic on the user's behalf, you're making an assumption about what they are wanting to actually invoke and you don't have enough information to even make an informed assumption! The most straight-forward way to make an assumption about what the user is wanting to invoke is to just use the version they last installed, which is the current situation now across all of our installers. Running both io.js and Node.js on the same computer is something that only concerns some developers, most devs and I'd suggest almost all production deploys will only be using one version of one project. Given that version managers like nave, n, nvm, nvm.sh have adapted to the new reality of letting you install multiple versions and do it quite well, this issue is a very low priority for the project.

If you want to run Node.js, install that, if you want to run io.js, install that, if you want to run both for some reason, use a version manager, they are perfect for developers and give you an easy way to always grab the latest version as a bonus.

schme16 commented May 1, 2015

@rvagg 👍

afshinm commented May 14, 2015

+1

Owner

Fishrock123 commented May 14, 2015

Now that we've agreed to merge into the Node Foundation there's not really a point. Maybe if someone can put in the work for a patch to make it optional.

https://www.binarysludge.com/2015/01/14/how-to-uninstall-io-js-or-io-js-and-node-js-together/

sudo rm /usr/local/bin/node && ln -s /usr/local/Cellar/node/0.10.32/bin/node /usr/local/bin/node
node --version 
iojs --version

👍 rambo-panda
Just came here from the binarysludge article, now I ask, why the symlink to node?

Owner

Fishrock123 commented Jun 30, 2015

Why: in short, so that node executable files work properly. (See above for more context.)

No such symlinks will exist in the converged node because it will only be node.

@Fishrock123 Fishrock123 locked and limited conversation to collaborators Jun 30, 2015

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.