passenger 5.3.7 → 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +14 -0
- data/build/agent.rb +4 -2
- data/build/support/cxx_dependency_map.rb +134 -0
- data/resources/templates/standalone/server.erb +1 -0
- data/src/agent/AgentMain.cpp +4 -0
- data/src/agent/Core/ApplicationPool/Group/StateInspection.cpp +1 -1
- data/src/agent/Core/ApplicationPool/Options.h +7 -7
- data/src/agent/Core/ApplicationPool/Process.h +3 -0
- data/src/agent/Core/Config.h +9 -2
- data/src/agent/Core/Controller/Config.h +27 -6
- data/src/agent/Core/Controller/InitRequest.cpp +12 -7
- data/src/agent/Core/Controller/InitializationAndShutdown.cpp +2 -0
- data/src/agent/Core/CoreMain.cpp +62 -33
- data/src/agent/Core/OptionParser.h +6 -0
- data/src/agent/Core/SpawningKit/Spawner.h +20 -5
- data/src/agent/Core/SpawningKit/UserSwitchingRules.h +13 -6
- data/src/agent/Core/TelemetryCollector.h +1 -0
- data/src/agent/FileReadHelper/FileReadHelperMain.cpp +198 -0
- data/src/agent/Watchdog/Config.h +1 -0
- data/src/apache2_module/ConfigGeneral/AutoGeneratedDefinitions.cpp +5 -0
- data/src/apache2_module/ConfigGeneral/AutoGeneratedSetterFuncs.cpp +15 -0
- data/src/apache2_module/DirConfig/AutoGeneratedCreateFunction.cpp +5 -0
- data/src/apache2_module/DirConfig/AutoGeneratedManifestGeneration.cpp +13 -0
- data/src/apache2_module/DirConfig/AutoGeneratedMergeFunction.cpp +7 -0
- data/src/apache2_module/DirConfig/AutoGeneratedStruct.h +13 -0
- data/src/apache2_module/DirectoryMapper.h +14 -3
- data/src/apache2_module/Hooks.cpp +15 -4
- data/src/cxx_supportlib/AppLocalConfigFileUtils.h +148 -0
- data/src/cxx_supportlib/AppTypeDetector/CBindings.cpp +12 -1
- data/src/cxx_supportlib/AppTypeDetector/CBindings.h +2 -0
- data/src/cxx_supportlib/AppTypeDetector/Detector.h +38 -4
- data/src/cxx_supportlib/Constants.h +1 -1
- data/src/nginx_module/ConfigGeneral/AutoGeneratedDefinitions.c +16 -0
- data/src/nginx_module/ConfigGeneral/AutoGeneratedManifestDefaultsInitialization.c +6 -0
- data/src/nginx_module/ConfigGeneral/AutoGeneratedSetterFuncs.c +12 -0
- data/src/nginx_module/Configuration.c +20 -0
- data/src/nginx_module/ContentHandler.c +301 -23
- data/src/nginx_module/ContentHandler.h +5 -0
- data/src/nginx_module/LocationConfig/AutoGeneratedCreateFunction.c +10 -0
- data/src/nginx_module/LocationConfig/AutoGeneratedManifestGeneration.c +27 -0
- data/src/nginx_module/LocationConfig/AutoGeneratedMergeFunction.c +3 -0
- data/src/nginx_module/LocationConfig/AutoGeneratedStruct.h +7 -0
- data/src/nginx_module/ngx_http_passenger_module.h +6 -1
- data/src/ruby_supportlib/phusion_passenger.rb +6 -5
- data/src/ruby_supportlib/phusion_passenger/apache2/config_options.rb +6 -0
- data/src/ruby_supportlib/phusion_passenger/nginx/config_options.rb +14 -0
- data/src/ruby_supportlib/phusion_passenger/standalone/app_finder.rb +1 -0
- data/src/ruby_supportlib/phusion_passenger/standalone/config_options_list.rb +11 -1
- data/src/ruby_supportlib/phusion_passenger/standalone/start_command/builtin_engine.rb +1 -0
- metadata +4 -2
@@ -41,6 +41,7 @@ passenger_enabled on;
|
|
41
41
|
<%= nginx_option(app, :spawn_method) %>
|
42
42
|
<%= nginx_option(app, :app_type) %>
|
43
43
|
<%= nginx_option(app, :startup_file) %>
|
44
|
+
<%= nginx_option(app, :app_start_command) %>
|
44
45
|
<%= nginx_option(app, :start_timeout) %>
|
45
46
|
<%= nginx_option(app, :min_instances) %>
|
46
47
|
<%= nginx_option(app, :max_request_queue_size) %>
|
data/src/agent/AgentMain.cpp
CHANGED
@@ -36,6 +36,7 @@ int systemMetricsMain(int argc, char *argv[]);
|
|
36
36
|
int tempDirToucherMain(int argc, char *argv[]);
|
37
37
|
int spawnEnvSetupperMain(int argc, char *argv[]);
|
38
38
|
int execHelperMain(int argc, char *argv[]);
|
39
|
+
int fileReadHelperMain(int argc, char *argv[]);
|
39
40
|
|
40
41
|
static bool
|
41
42
|
isHelp(const char *arg) {
|
@@ -58,6 +59,7 @@ usage(int argc, char *argv[]) {
|
|
58
59
|
printf("Utility subcommands:\n");
|
59
60
|
printf(" system-metrics\n");
|
60
61
|
printf(" exec-helper\n");
|
62
|
+
printf(" file-read-helper\n");
|
61
63
|
}
|
62
64
|
|
63
65
|
static bool
|
@@ -90,6 +92,8 @@ dispatchSubcommand(int argc, char *argv[]) {
|
|
90
92
|
exit(spawnEnvSetupperMain(argc, argv));
|
91
93
|
} else if (strcmp(argv[1], "exec-helper") == 0) {
|
92
94
|
exit(execHelperMain(argc, argv));
|
95
|
+
} else if (strcmp(argv[1], "file-read-helper") == 0) {
|
96
|
+
exit(fileReadHelperMain(argc, argv));
|
93
97
|
} else if (strcmp(argv[1], "test-binary") == 0) {
|
94
98
|
printf("PASS\n");
|
95
99
|
exit(0);
|
@@ -233,7 +233,7 @@ Group::inspectConfigInAdminPanelFormat(Json::Value &result) const {
|
|
233
233
|
|
234
234
|
result["type"] = NON_EMPTY_SVAL(options.appType);
|
235
235
|
result["startup_file"] = NON_EMPTY_SVAL(options.startupFile);
|
236
|
-
result["start_command"] = NON_EMPTY_SVAL(replaceAll(options.
|
236
|
+
result["start_command"] = NON_EMPTY_SVAL(replaceAll(options.appStartCommand,
|
237
237
|
P_STATIC_STRING("\t"), P_STATIC_STRING(" ")));
|
238
238
|
result["ruby"] = SVAL(options.ruby, DEFAULT_RUBY);
|
239
239
|
result["python"] = SVAL(options.python, DEFAULT_PYTHON);
|
@@ -85,7 +85,7 @@ private:
|
|
85
85
|
result.push_back(&options.appGroupName);
|
86
86
|
result.push_back(&options.appLogFile);
|
87
87
|
result.push_back(&options.appType);
|
88
|
-
result.push_back(&options.
|
88
|
+
result.push_back(&options.appStartCommand);
|
89
89
|
result.push_back(&options.startupFile);
|
90
90
|
result.push_back(&options.processTitle);
|
91
91
|
|
@@ -181,15 +181,15 @@ public:
|
|
181
181
|
/** The application's type, used for determining the command to invoke to
|
182
182
|
* spawn an application process as well as determining the startup file's
|
183
183
|
* filename. It can be one of the app type names in AppType.cpp, or the
|
184
|
-
* empty string (default). In case of the latter, '
|
184
|
+
* empty string (default). In case of the latter, 'appStartCommand' and
|
185
185
|
* 'startupFile' (which MUST be set) will dictate the startup command
|
186
186
|
* and the startup file's filename. */
|
187
187
|
StaticString appType;
|
188
188
|
|
189
|
-
/** The command for spawning the application process.
|
190
|
-
*
|
191
|
-
|
192
|
-
StaticString
|
189
|
+
/** The shell command string for spawning the application process.
|
190
|
+
* Only used during spawning and only if appType.empty().
|
191
|
+
*/
|
192
|
+
StaticString appStartCommand;
|
193
193
|
|
194
194
|
/** Filename of the application's startup file. Only actually used for
|
195
195
|
* determining user switching info. Only used during spawning. */
|
@@ -629,7 +629,7 @@ public:
|
|
629
629
|
} else if (entry.language == P_STATIC_STRING("meteor")) {
|
630
630
|
interpreter = escapeShell(ruby);
|
631
631
|
} else {
|
632
|
-
return
|
632
|
+
return appStartCommand;
|
633
633
|
}
|
634
634
|
|
635
635
|
return interpreter + " " + escapeShell(resourceLocator.getHelperScriptsDir()
|
data/src/agent/Core/Config.h
CHANGED
@@ -160,6 +160,7 @@ using namespace std;
|
|
160
160
|
* server_software string - default("Phusion_Passenger/5.3.7")
|
161
161
|
* show_version_in_header boolean - default(true)
|
162
162
|
* single_app_mode_app_root string - default,read_only
|
163
|
+
* single_app_mode_app_start_command string - read_only
|
163
164
|
* single_app_mode_app_type string - read_only
|
164
165
|
* single_app_mode_startup_file string - read_only
|
165
166
|
* standalone_engine string - default
|
@@ -253,6 +254,10 @@ private:
|
|
253
254
|
errors.push_back(Error("If '{{multi_app_mode}}' is set,"
|
254
255
|
" then '{{single_app_mode_startup_file}}' may not be set"));
|
255
256
|
}
|
257
|
+
if (!config["single_app_mode_app_start_command"].isNull()) {
|
258
|
+
errors.push_back(Error("If '{{multi_app_mode}}' is set,"
|
259
|
+
" then '{{single_app_mode_app_start_command}}' may not be set"));
|
260
|
+
}
|
256
261
|
}
|
257
262
|
|
258
263
|
static void validateSingleAppMode(const ConfigKit::Store &config,
|
@@ -264,8 +269,9 @@ private:
|
|
264
269
|
return;
|
265
270
|
}
|
266
271
|
|
267
|
-
// single_app_mode_app_type
|
268
|
-
// autodetected in
|
272
|
+
// single_app_mode_app_type, single_app_mode_startup_file and
|
273
|
+
// single_app_mode_app_start_command are autodetected in
|
274
|
+
// initializeSingleAppMode() so no need to validate them.
|
269
275
|
|
270
276
|
ControllerSingleAppModeSchema::validateAppType("single_app_mode_app_type",
|
271
277
|
wrapperRegistry, config, errors);
|
@@ -425,6 +431,7 @@ public:
|
|
425
431
|
ControllerSingleAppModeSchema::getDefaultAppRoot);
|
426
432
|
add("single_app_mode_app_type", STRING_TYPE, OPTIONAL | READ_ONLY);
|
427
433
|
add("single_app_mode_startup_file", STRING_TYPE, OPTIONAL | READ_ONLY);
|
434
|
+
add("single_app_mode_app_start_command", STRING_TYPE, OPTIONAL | READ_ONLY);
|
428
435
|
|
429
436
|
// Add subschema: controllerServerKit
|
430
437
|
controllerServerKit.translator.setPrefixAndFinalize("controller_");
|
@@ -223,9 +223,10 @@ public:
|
|
223
223
|
* (do not edit: following text is automatically generated
|
224
224
|
* by 'rake configkit_schemas_inline_comments')
|
225
225
|
*
|
226
|
-
* app_root
|
227
|
-
*
|
228
|
-
*
|
226
|
+
* app_root string - default,read_only
|
227
|
+
* app_start_command string - read_only
|
228
|
+
* app_type string - read_only
|
229
|
+
* startup_file string - read_only
|
229
230
|
*
|
230
231
|
* END
|
231
232
|
*/
|
@@ -235,9 +236,11 @@ struct ControllerSingleAppModeSchema: public ConfigKit::Schema {
|
|
235
236
|
|
236
237
|
addWithDynamicDefault("app_root", STRING_TYPE, OPTIONAL | READ_ONLY | CACHE_DEFAULT_VALUE,
|
237
238
|
getDefaultAppRoot);
|
238
|
-
add("app_type", STRING_TYPE,
|
239
|
-
add("startup_file", STRING_TYPE,
|
239
|
+
add("app_type", STRING_TYPE, OPTIONAL | READ_ONLY);
|
240
|
+
add("startup_file", STRING_TYPE, OPTIONAL | READ_ONLY);
|
241
|
+
add("app_start_command", STRING_TYPE, OPTIONAL | READ_ONLY);
|
240
242
|
|
243
|
+
addValidator(validateAppTypeOrAppStartCommandSet);
|
241
244
|
addValidator(boost::bind(validateAppType, "app_type", wrapperRegistry,
|
242
245
|
boost::placeholders::_1, boost::placeholders::_2));
|
243
246
|
addNormalizer(normalizeAppRoot);
|
@@ -257,6 +260,21 @@ struct ControllerSingleAppModeSchema: public ConfigKit::Schema {
|
|
257
260
|
return result;
|
258
261
|
}
|
259
262
|
|
263
|
+
static void validateAppTypeOrAppStartCommandSet(const ConfigKit::Store &config,
|
264
|
+
vector<ConfigKit::Error> &errors)
|
265
|
+
{
|
266
|
+
typedef ConfigKit::Error Error;
|
267
|
+
|
268
|
+
if (config["app_type"].isNull() && config["app_start_command"].isNull()) {
|
269
|
+
errors.push_back(Error(
|
270
|
+
"Either '{{app_type}}' or '{{app_start_command}}' must be set"));
|
271
|
+
}
|
272
|
+
if (!config["app_type"].isNull() && config["startup_file"].isNull()) {
|
273
|
+
errors.push_back(Error(
|
274
|
+
"If '{{app_type}}' is set, then '{{startup_file}}' must also be set"));
|
275
|
+
}
|
276
|
+
}
|
277
|
+
|
260
278
|
static void validateAppType(const string &appTypeKey,
|
261
279
|
const WrapperRegistry::Registry *wrapperRegistry,
|
262
280
|
const ConfigKit::Store &config, vector<ConfigKit::Error> &errors)
|
@@ -290,7 +308,10 @@ struct ControllerSingleAppModeSchema: public ConfigKit::Schema {
|
|
290
308
|
|
291
309
|
static Json::Value normalizeStartupFile(const Json::Value &effectiveValues) {
|
292
310
|
Json::Value updates;
|
293
|
-
|
311
|
+
if (effectiveValues.isMember("startup_file")) {
|
312
|
+
updates["startup_file"] = absolutizePath(
|
313
|
+
effectiveValues["startup_file"].asString());
|
314
|
+
}
|
294
315
|
return updates;
|
295
316
|
}
|
296
317
|
};
|
@@ -337,13 +337,18 @@ Controller::createNewPoolOptions(Client *client, Request *req,
|
|
337
337
|
|
338
338
|
const LString *appType = secureHeaders.lookup("!~PASSENGER_APP_TYPE");
|
339
339
|
if (appType == NULL || appType->size == 0) {
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
340
|
+
const LString *appStartCommand = secureHeaders.lookup("!~PASSENGER_APP_START_COMMAND");
|
341
|
+
if (appStartCommand == NULL || appStartCommand->size == 0) {
|
342
|
+
AppTypeDetector::Detector detector(*wrapperRegistry);
|
343
|
+
AppTypeDetector::Detector::Result result = detector.checkAppRoot(options.appRoot);
|
344
|
+
if (result.isNull()) {
|
345
|
+
disconnectWithError(&client, "client did not send a recognized !~PASSENGER_APP_TYPE header");
|
346
|
+
return;
|
347
|
+
}
|
348
|
+
options.appType = result.wrapperRegistryEntry->language;
|
349
|
+
} else {
|
350
|
+
fillPoolOption(req, options.appStartCommand, "!~PASSENGER_APP_START_COMMAND");
|
345
351
|
}
|
346
|
-
options.appType = result.wrapperRegistryEntry->language;
|
347
352
|
} else {
|
348
353
|
fillPoolOption(req, options.appType, "!~PASSENGER_APP_TYPE");
|
349
354
|
}
|
@@ -360,7 +365,7 @@ Controller::createNewPoolOptions(Client *client, Request *req,
|
|
360
365
|
fillPoolOption(req, options.group, "!~PASSENGER_GROUP");
|
361
366
|
fillPoolOption(req, options.minProcesses, "!~PASSENGER_MIN_PROCESSES");
|
362
367
|
fillPoolOption(req, options.spawnMethod, "!~PASSENGER_SPAWN_METHOD");
|
363
|
-
fillPoolOption(req, options.
|
368
|
+
fillPoolOption(req, options.appStartCommand, "!~PASSENGER_APP_START_COMMAND");
|
364
369
|
fillPoolOptionSecToMsec(req, options.startTimeout, "!~PASSENGER_START_TIMEOUT");
|
365
370
|
fillPoolOption(req, options.maxPreloaderIdleTime, "!~PASSENGER_MAX_PRELOADER_IDLE_TIME");
|
366
371
|
fillPoolOption(req, options.maxRequestQueueSize, "!~PASSENGER_MAX_REQUEST_QUEUE_SIZE");
|
@@ -112,11 +112,13 @@ Controller::initialize() {
|
|
112
112
|
string environment = config["default_environment"].asString();
|
113
113
|
string appType = singleAppModeConfig->get("app_type").asString();
|
114
114
|
string startupFile = singleAppModeConfig->get("startup_file").asString();
|
115
|
+
string appStartCommand = singleAppModeConfig->get("app_start_command").asString();
|
115
116
|
|
116
117
|
options->appRoot = appRoot;
|
117
118
|
options->environment = environment;
|
118
119
|
options->appType = appType;
|
119
120
|
options->startupFile = startupFile;
|
121
|
+
options->appStartCommand = appStartCommand;
|
120
122
|
*options = options->copyAndPersist();
|
121
123
|
poolOptionsCache.insert(options->getAppGroupName(), options);
|
122
124
|
}
|
data/src/agent/Core/CoreMain.cpp
CHANGED
@@ -258,53 +258,83 @@ initializeSingleAppMode() {
|
|
258
258
|
}
|
259
259
|
|
260
260
|
WorkingObjects *wo = workingObjects;
|
261
|
-
string appType, startupFile;
|
261
|
+
string appType, startupFile, appStartCommand;
|
262
262
|
string appRoot = coreConfig->get("single_app_mode_app_root").asString();
|
263
263
|
|
264
|
-
if (coreConfig->get("single_app_mode_app_type").isNull()
|
264
|
+
if (!coreConfig->get("single_app_mode_app_type").isNull()
|
265
|
+
&& !coreConfig->get("single_app_mode_app_start_command").isNull())
|
266
|
+
{
|
267
|
+
fprintf(stderr, "ERROR: it is not allowed for both --app-type and"
|
268
|
+
" --app-start-command to be set.\n");
|
269
|
+
exit(1);
|
270
|
+
}
|
271
|
+
|
272
|
+
if (!coreConfig->get("single_app_mode_app_start_command").isNull()) {
|
273
|
+
// The config specified that this is a generic app or a Kuria app.
|
274
|
+
appStartCommand = coreConfig->get("single_app_mode_app_start_command").asString();
|
275
|
+
} else if (coreConfig->get("single_app_mode_app_type").isNull()) {
|
276
|
+
// Autodetect whether this is generic app, Kuria app or auto-supported app.
|
265
277
|
P_DEBUG("Autodetecting application type...");
|
266
|
-
AppTypeDetector::Detector detector(*coreWrapperRegistry
|
267
|
-
AppTypeDetector::Detector::Result
|
268
|
-
if (result.isNull()) {
|
269
|
-
fprintf(stderr, "ERROR: unable to autodetect what kind of application "
|
270
|
-
"lives in %s. Please specify information about the app using "
|
271
|
-
"--app-type and --startup-file, or specify a correct location to "
|
272
|
-
"the application you want to serve.\n"
|
273
|
-
"Type '" SHORT_PROGRAM_NAME " core --help' for more information.\n",
|
274
|
-
appRoot.c_str());
|
275
|
-
exit(1);
|
276
|
-
}
|
278
|
+
AppTypeDetector::Detector detector(*coreWrapperRegistry);
|
279
|
+
AppTypeDetector::Detector::Result detectorResult = detector.checkAppRoot(appRoot);
|
277
280
|
|
278
|
-
|
281
|
+
if (!detectorResult.appStartCommand.empty()) {
|
282
|
+
// This is a generic or Kuria app.
|
283
|
+
appStartCommand = detectorResult.appStartCommand;
|
284
|
+
} else {
|
285
|
+
// This is an auto-supported app.
|
286
|
+
if (coreConfig->get("single_app_mode_app_type").isNull()) {
|
287
|
+
if (detectorResult.isNull()) {
|
288
|
+
fprintf(stderr, "ERROR: unable to autodetect what kind of application "
|
289
|
+
"lives in %s. Please specify information about the app using "
|
290
|
+
"--app-type, --startup-file and --app-start-command, or specify a "
|
291
|
+
"correct location to the application you want to serve.\n"
|
292
|
+
"Type '" SHORT_PROGRAM_NAME " core --help' for more information.\n",
|
293
|
+
appRoot.c_str());
|
294
|
+
exit(1);
|
295
|
+
}
|
296
|
+
appType = detectorResult.wrapperRegistryEntry->language;
|
297
|
+
} else {
|
298
|
+
appType = coreConfig->get("single_app_mode_app_type").asString();
|
299
|
+
}
|
300
|
+
}
|
279
301
|
} else {
|
302
|
+
// This is an auto-supported app.
|
280
303
|
appType = coreConfig->get("single_app_mode_app_type").asString();
|
281
304
|
}
|
282
305
|
|
283
|
-
if (
|
284
|
-
|
285
|
-
|
286
|
-
|
306
|
+
if (!appType.empty()) {
|
307
|
+
if (coreConfig->get("single_app_mode_startup_file").isNull()) {
|
308
|
+
const WrapperRegistry::Entry &entry = coreWrapperRegistry->lookup(appType);
|
309
|
+
if (entry.defaultStartupFiles.empty()) {
|
310
|
+
startupFile = appRoot + "/";
|
311
|
+
} else {
|
312
|
+
startupFile = appRoot + "/" + entry.defaultStartupFiles[0];
|
313
|
+
}
|
287
314
|
} else {
|
288
|
-
startupFile =
|
315
|
+
startupFile = coreConfig->get("single_app_mode_startup_file").asString();
|
316
|
+
}
|
317
|
+
if (!fileExists(startupFile)) {
|
318
|
+
fprintf(stderr, "ERROR: unable to find expected startup file %s."
|
319
|
+
" Please specify its correct path with --startup-file.\n",
|
320
|
+
startupFile.c_str());
|
321
|
+
exit(1);
|
289
322
|
}
|
290
|
-
} else {
|
291
|
-
startupFile = coreConfig->get("single_app_mode_startup_file").asString();
|
292
|
-
}
|
293
|
-
if (!fileExists(startupFile)) {
|
294
|
-
fprintf(stderr, "ERROR: unable to find expected startup file %s."
|
295
|
-
" Please specify its correct path with --startup-file.\n",
|
296
|
-
startupFile.c_str());
|
297
|
-
exit(1);
|
298
323
|
}
|
299
324
|
|
300
325
|
wo->singleAppModeConfig["app_root"] = appRoot;
|
301
|
-
wo->singleAppModeConfig["app_type"] = appType;
|
302
|
-
wo->singleAppModeConfig["startup_file"] = startupFile;
|
303
326
|
|
304
327
|
P_NOTICE(SHORT_PROGRAM_NAME " core running in single-application mode.");
|
305
|
-
P_NOTICE("Serving app
|
306
|
-
|
307
|
-
|
328
|
+
P_NOTICE("Serving app : " << appRoot);
|
329
|
+
if (!appType.empty()) {
|
330
|
+
P_NOTICE("App type : " << appType);
|
331
|
+
P_NOTICE("App startup file : " << startupFile);
|
332
|
+
wo->singleAppModeConfig["app_type"] = appType;
|
333
|
+
wo->singleAppModeConfig["startup_file"] = startupFile;
|
334
|
+
} else {
|
335
|
+
P_NOTICE("App start command: " << appStartCommand);
|
336
|
+
wo->singleAppModeConfig["app_start_command"] = appStartCommand;
|
337
|
+
}
|
308
338
|
}
|
309
339
|
|
310
340
|
static void
|
@@ -852,7 +882,6 @@ initializeSecurityUpdateChecker() {
|
|
852
882
|
|
853
883
|
static void
|
854
884
|
initializeTelemetryCollector() {
|
855
|
-
return; // disable for now
|
856
885
|
TRACE_POINT();
|
857
886
|
WorkingObjects &wo = *workingObjects;
|
858
887
|
|
@@ -109,6 +109,9 @@ coreUsage() {
|
|
109
109
|
printf(" (single-app mode only)\n");
|
110
110
|
printf(" --startup-file PATH The path of the app's startup file, relative to\n");
|
111
111
|
printf(" the app root directory (single-app mode only)\n");
|
112
|
+
printf(" --app-start-command COMMAND\n");
|
113
|
+
printf(" The command string with which to start the app\n");
|
114
|
+
printf(" (single-app mode only)\n");
|
112
115
|
printf(" --spawn-method NAME Spawn method to use. Can either be 'smart' or\n");
|
113
116
|
printf(" 'direct'. Default: %s\n", DEFAULT_SPAWN_METHOD);
|
114
117
|
printf(" --load-shell-envvars Load shell startup files before loading application\n");
|
@@ -317,6 +320,9 @@ parseCoreOption(int argc, const char *argv[], int &i, Json::Value &updates) {
|
|
317
320
|
} else if (p.isValueFlag(argc, i, argv[i], '\0', "--startup-file")) {
|
318
321
|
updates["single_app_mode_startup_file"] = argv[i + 1];
|
319
322
|
i += 2;
|
323
|
+
} else if (p.isValueFlag(argc, i, argv[i], '\0', "--app-start-command")) {
|
324
|
+
updates["single_app_mode_app_start_command"] = argv[i + 1];
|
325
|
+
i += 2;
|
320
326
|
} else if (p.isValueFlag(argc, i, argv[i], '\0', "--spawn-method")) {
|
321
327
|
updates["default_spawn_method"] = argv[i + 1];
|
322
328
|
i += 2;
|
@@ -31,6 +31,7 @@
|
|
31
31
|
|
32
32
|
#include <modp_b64.h>
|
33
33
|
|
34
|
+
#include <AppLocalConfigFileUtils.h>
|
34
35
|
#include <LoggingKit/Logging.h>
|
35
36
|
#include <SystemTools/SystemTime.h>
|
36
37
|
#include <Core/SpawningKit/Context.h>
|
@@ -79,8 +80,7 @@ protected:
|
|
79
80
|
void setConfigFromAppPoolOptions(Config *config, Json::Value &extraArgs,
|
80
81
|
const AppPoolOptions &options)
|
81
82
|
{
|
82
|
-
|
83
|
-
*context->wrapperRegistry);
|
83
|
+
TRACE_POINT();
|
84
84
|
string envvarsData;
|
85
85
|
try {
|
86
86
|
envvarsData = modp::b64_decode(options.environmentVariables.data(),
|
@@ -91,15 +91,30 @@ protected:
|
|
91
91
|
envvarsData.clear();
|
92
92
|
}
|
93
93
|
|
94
|
+
AppLocalConfig appLocalConfig = parseAppLocalConfigFile(options.appRoot);
|
95
|
+
string startCommand;
|
96
|
+
|
97
|
+
if (appLocalConfig.appSupportsKuriaProtocol) {
|
98
|
+
config->genericApp = false;
|
99
|
+
config->startsUsingWrapper = false;
|
100
|
+
config->startCommand = options.appStartCommand;
|
101
|
+
} else if (options.appType.empty()) {
|
102
|
+
config->genericApp = true;
|
103
|
+
config->startCommand = options.appStartCommand;
|
104
|
+
} else {
|
105
|
+
startCommand = options.getStartCommand(*context->resourceLocator,
|
106
|
+
*context->wrapperRegistry);
|
107
|
+
config->genericApp = false;
|
108
|
+
config->startsUsingWrapper = true;
|
109
|
+
config->startCommand = startCommand;
|
110
|
+
}
|
111
|
+
|
94
112
|
config->appGroupName = options.getAppGroupName();
|
95
113
|
config->appRoot = options.appRoot;
|
96
114
|
config->logLevel = options.logLevel;
|
97
|
-
config->genericApp = false;
|
98
|
-
config->startsUsingWrapper = true;
|
99
115
|
config->wrapperSuppliedByThirdParty = false;
|
100
116
|
config->findFreePort = false;
|
101
117
|
config->loadShellEnvvars = options.loadShellEnvvars;
|
102
|
-
config->startCommand = startCommand;
|
103
118
|
config->startupFile = options.getStartupFile(*context->wrapperRegistry);
|
104
119
|
config->appType = options.appType;
|
105
120
|
config->appEnv = options.environment;
|
@@ -98,8 +98,8 @@ prepareUserSwitching(const AppPoolOptions &options,
|
|
98
98
|
|
99
99
|
UPDATE_TRACE_POINT();
|
100
100
|
string defaultGroup;
|
101
|
-
|
102
|
-
|
101
|
+
// This is the file that determines what user we lower privilege to.
|
102
|
+
string referenceFile;
|
103
103
|
struct passwd &pwd = info.lveUserPwd;
|
104
104
|
boost::shared_array<char> &pwdBuf = info.lveUserPwdStrBuf;
|
105
105
|
struct passwd *userInfo;
|
@@ -109,6 +109,13 @@ prepareUserSwitching(const AppPoolOptions &options,
|
|
109
109
|
boost::shared_array<char> grpBuf;
|
110
110
|
int ret;
|
111
111
|
|
112
|
+
if (options.appType.empty()) {
|
113
|
+
referenceFile = absolutizePath(options.appRoot);
|
114
|
+
} else {
|
115
|
+
referenceFile = absolutizePath(options.getStartupFile(wrapperRegistry),
|
116
|
+
absolutizePath(options.appRoot));
|
117
|
+
}
|
118
|
+
|
112
119
|
// _SC_GETPW_R_SIZE_MAX/_SC_GETGR_R_SIZE_MAX are not maximums:
|
113
120
|
// http://tomlee.co/2012/10/problems-with-large-linux-unix-groups-and-getgrgid_r-getgrnam_r/
|
114
121
|
pwdBufSize = std::max<long>(1024 * 128, sysconf(_SC_GETPW_R_SIZE_MAX));
|
@@ -158,9 +165,9 @@ prepareUserSwitching(const AppPoolOptions &options,
|
|
158
165
|
}
|
159
166
|
} else {
|
160
167
|
struct stat buf;
|
161
|
-
if (syscalls::lstat(
|
168
|
+
if (syscalls::lstat(referenceFile.c_str(), &buf) == -1) {
|
162
169
|
int e = errno;
|
163
|
-
throw SystemException("Cannot lstat(\"" +
|
170
|
+
throw SystemException("Cannot lstat(\"" + referenceFile +
|
164
171
|
"\")", e);
|
165
172
|
}
|
166
173
|
ret = getpwuid_r(buf.st_uid, &pwd, pwdBuf.get(),
|
@@ -187,10 +194,10 @@ prepareUserSwitching(const AppPoolOptions &options,
|
|
187
194
|
if (options.group == "!STARTUP_FILE!") {
|
188
195
|
struct stat buf;
|
189
196
|
|
190
|
-
if (syscalls::lstat(
|
197
|
+
if (syscalls::lstat(referenceFile.c_str(), &buf) == -1) {
|
191
198
|
int e = errno;
|
192
199
|
throw SystemException("Cannot lstat(\"" +
|
193
|
-
|
200
|
+
referenceFile + "\")", e);
|
194
201
|
}
|
195
202
|
|
196
203
|
ret = getgrgid_r(buf.st_gid, &grp, grpBuf.get(), grpBufSize,
|