/// <summary> /// Deploy fast-cgi settings /// </summary> protected void DeployFasctCgi() { var limits = this.Deployment.GetApplicationLimits(); using (ServerManager serverManager = new ServerManager()) { this.Logger.LogWarning(false, "Deploying fastCgi based applications causes IIS to internally reset to pick the new configuration because fastCgi is configured at the server level."); var phpRuntime = this.GetFastCgiExe(); var iniFilePath = this.GetIniFilePath(); var phpIniFile = this.GetIniFilePath(); string siteAlias = this.Deployment.getShortId(); // fastCgi settings in IIS can only be set at the HOSTS level // we found no way to set this at a web.config level. Microsoft.Web.Administration.Configuration config = serverManager.GetApplicationHostConfiguration(); ConfigurationSection section = config.GetSection("system.webServer/fastCgi"); ConfigurationElement cfs = null; // Each fastCgi in IIS is a unique combination of RUNTIME_PATH|ARGUMENTS, try to find // the current application. foreach (ConfigurationElement sec in section.GetCollection()) { // Cada aplicación se identifica de manera única por la combincación de atributo y path de ejecución. if (sec.HasValue("arguments", siteAlias) && sec.HasValue("fullPath", phpRuntime)) { cfs = sec; break; } } // We need to keep track if the element already existed // in the configuration, or it is new. bool addApplication = false; ConfigurationElementCollection elems = section.GetCollection(); if (cfs == null) { cfs = elems.CreateElement("application"); addApplication = true; } // In this deployment we are not really passing // any argments to PHP, simply use the site Alias to // isolate each PHP site. // OJO: PONER EL SITE ALIAS AQUÍ NO ES ALGO // GRATUITO. LUEGO EN EL WEB.CONFIG DE LA PROPIA // APLICACIÓN DEBE ESTAR EXACTAMENTE IGUAL. cfs.SetAttributeValue("arguments", siteAlias); // Set reasonable defaults, even if the user configuration says differently var instanceMaxRequests = this.PhpSettings.instanceMaxRequests > 200 ? this.PhpSettings.instanceMaxRequests : 10000; var maxInstances = this.PhpSettings.maxInstances > 3 ? this.PhpSettings.maxInstances : 10; var activityTimeout = this.PhpSettings.activityTimeout > 100 ? this.PhpSettings.activityTimeout : 600; var requestTimeout = this.PhpSettings.requestTimeout > 60 ? this.PhpSettings.requestTimeout : 300; // Ensure that all values are within the limits if (maxInstances > limits.FastCgiMaxInstances && limits.FastCgiMaxInstances > 0) { maxInstances = limits.FastCgiMaxInstances.Value; } // Runtime Path. cfs.SetAttributeValue("fullPath", phpRuntime); cfs.SetAttributeValue("maxInstances", maxInstances); cfs.SetAttributeValue("activityTimeout", activityTimeout); cfs.SetAttributeValue("requestTimeout", requestTimeout); cfs.SetAttributeValue("instanceMaxRequests", instanceMaxRequests); // Make sure that changes to PHP.ini are refreshed properly if (File.Exists(iniFilePath)) { cfs.SetAttributeValue("monitorChangesTo", iniFilePath); } // Este setting no sirve para nada según -E- de MS porque // la implementación de FastCGI está mal hecha en IIS. // Los eventos internos de señal no se llegan a ejecutar nunca, // lo único que consigues es demorar el cierre de instancias. cfs.SetAttributeValue("signalBeforeTerminateSeconds", 0); if (!File.Exists(phpIniFile)) { throw new Exception("PHP.ini file not found. This will break the IIS FastCgiModule when using monitorChangesTo feature."); } // Retrieve the environment variables. ConfigurationElement cfgEnvironment = cfs.GetChildElement("environmentVariables"); ConfigurationElementCollection a = cfgEnvironment.GetCollection(); // This is fastcgi specific. a.AddOrUpdateConfigurationElementInCollection("PHP_FCGI_MAX_REQUESTS", instanceMaxRequests.ToString()); // Add all the environment variables. var environmentVariables = this.GetEnvironmentVariables(); foreach (var p in environmentVariables) { a.AddOrUpdateConfigurationElementInCollection(p.Key, p.Value); } if (addApplication) { elems.Add(cfs); } // Cleanup any fastCgi applications that point to non-existent handlers // see the comments in FastCgiRemove() as to why this is here. var fastCgiHandlers = section.GetCollection(); foreach (ConfigurationElement sec in fastCgiHandlers.ToList()) { if (sec.RawAttributes.Keys.Contains("fullPath")) { string fullPath = sec.GetAttributeValue("fullPath").ToString(); if (!File.Exists(fullPath)) { this.Logger.LogInfo(true, "Removed stale fastCgi handler {0}", fullPath); fastCgiHandlers.Remove(sec); } } } UtilsIis.CommitChanges(serverManager); } }