passenger 5.3.7 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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,
|