-
Notifications
You must be signed in to change notification settings - Fork 29.6k
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
src: command line option to preload modules #881
Conversation
Isn't that the purpose of _third_party_main? EDIT: Although that appears to be for compile time. |
I've wanted a feature like this, too. Some node core features (such as cluster) basically do this, but they do it by using fixed env variables and check for them and trigger specific code. So in some sense its a "feature" available to core, but no way has been found to expose it to user-land. In order to factor cluster out of core, something like this would be needed. I don't think this implementation is great, particularly the hard-coded path. What would make more sense to me is an env variable like |
@sam-github: @cjihrig: _third_party_main lets you build stand-alone executables of your javascript program, provided as _third_party_main at node compile time. The output isn't node but rather an executable for your javascript program. |
The
translates to require('foo');
require('/bar/baz.js');
require('quux'); |
@piscisaureus Updated as per your suggestion. |
As a vendor, if you have enough control to change the command line then why not just node invoke to a proxy script that invokes the original script? |
@meandmycode asks a good question. As to the implementation, loading arbitrary code based on an environment variable is insecure when the iojs binary is setuid root. On the C++ side, |
@meandmycode I want the preload modules to be loaded uniformly across all uses of node, including Also, I think the See also the use-case @sam-github describes above. @bnoordhuis Yes, you're right that setuid is a concrete problem. I had vague feelings of security issues which is why I had originally proposed a hard-coded path within the installation directory. I can look into |
Right, but how will |
|
Ah sorry, I was confused on that aspect and the preload parameter. I feel like environmental variables are a bad story. How do you target a specific io.js/node? How would it affect things like atom etc? looking adjacent to the exec path seems like a safer option but I'm obviously not as informed in this space. |
Environment variables are the easiest starting point for this feature, but a well rounded implementation would probably offer both environment variables and a |
I think there are some legitimate concerns, I'm not totally sold on this, but I do think its worth considering hard. A couple comments:
/cc @rmg |
@sam-github thanks for the mention! I have generally been in favour of the proxy command route, but it definitely doesn't mix well with some really useful use-cases, like I also question the Another option, which could be more broadly useful, is to make For the sake of examples, I'll say
After typing up those examples, it definitely feels clunky if pre-loading modules is the problem being solved.. that clunkiness might discourage over-use, which is good or bad depending on your preferences. Maybe a Something like a |
+1 for EDIT: Conceptual +1. Of course have to work through the practical issues, like security. |
-1 to using an environment variable to inject functionality into the trusted core, think through for a moment where those variables could come from and how unlikely you are to ever check that |
You control your environment... you better, if not, someone can just set your PATH to their version of Again, this is something ruby and perl have, so its hard to call an all-caps security flaw. |
I think those scenarios seem fine, although it feels super hacky, almost asking for a backdoor in because it's convenient for you as a host of what is someone else's app most likely. My only concern is third parties using (embedding) iojs- I don't think this behavior should exist for those instances of iojs. |
@rmg I like the ideas about @rvagg I can already inject functionality into the trusted core using @meandmycode If the embedding scenario is an important concern, it can be dealt with a --disable-preload configure flag. As a user, though, maybe I do want to debug an embedded node.. it would be nice if I could do it without having direct access to the command line being passed to the embedded node. Environment variables are a different kind of a tool than a command line option. Both have their valid use-cases. |
@ofrobots I believe the difference between |
@trevnorris on systems that use That said, |
As a compromise can I suggest just sticking with a commandline flag instead of env var for now, perhaps extend it later? Otherwise we might get bogged down arguing about this. I like the feature, I just don't like magic environment variables. |
+1 for an explicit command line argument. |
I'm cool with a command line argument. |
Sounds good to me. I will summarize the discussion and adjust the PR in a little bit (need to be away from the 'net for a couple of days). |
I'm fine with a command line argument, as well, though it doesn't address the use-case of effecting node child invocations transparently. Still, we can try it out a bit and get feedback. |
@sam-github Indeed. However, we don't necessarily have to conflate the need to effect node child invocations with the need to preload modules. I think an independent separate argument can be made for a more general |
I have updated the pull request to implement preloading modules via a The general consensus in the discussion above seems to be that the ability to preload modules is a useful feature. There was however debate on the topic of whether this should be done via command-line options or via environment variables. Upon reflection, it seems environment variables are an orthogonal concern. It make sense to decouple these discussions. Since some valid use-cases for environment variables came up, an independent issue can be be opened on the topic of a more generic We also discussed a non-exclusive variant of the |
@@ -2935,6 +2942,12 @@ static void PrintHelp() { | |||
" -p, --print evaluate script and print result\n" | |||
" -i, --interactive always enter the REPL even if stdin\n" | |||
" does not appear to be a terminal\n" | |||
#ifdef _WIN32 | |||
" -r, --require ';'-separated list of modules to" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need this... you can use :
in unix or win32 package names (unadvised, though, and if it fails to work your bug reports will be laughed at). Stick with :
. Thoughts, @piscisaureus, or @orangemocha, am I too unix-centric? :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was following what we do for NODE_PATH
. The other alternative would be to use a comma, but I think that's even more likely to be in a package name. I'm open to suggestions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using a colon for this doesn't work on windows.
+1 to what the PR makes of it.
Looks OK to me as a feature, I didn't read the code. |
Here's a proposal, along with a PR, I would like to get feedback from the community on.
It would be nice if there was a standard mechanism to allow vendors, such as a cloud host, to customize startup of node applications.
Basically, I want to be able to inject functionality into a node application without requiring an explicit require. This could be useful to automatically enable, e.g., vendor specific tracing and application performance monitoring APIs when applications are deployed.
There are a few ways this could be done:
0. (Status quo) Ask the developers to modify their applications and add an explicit require of a vendor provided npm module. This adds friction to the deployment experience and possibly prevents people from being able to easily try different cloud vendors.
Here's a proposal on how to do option 2 (EDIT: updated as per suggestions by @piscisaureus):
On startup, node checks ifprocess.env.NODE_VENDOR_STARTUP
is set. If so, the filenode_prefix + '/lib/vendor/index.js'
is loaded (if it exists).Vendors could package up their distributions of node/io by adding lib/vendor.Another alternative would be forNODE_VENDOR_STARTUP
to be a path. It gives more flexibility, but is probably not as secure.EDIT: 20150313: change to command line option.
translates to:
Thoughts?