Here's a UDF I came up with to restart ColdFusion MX from your code. Say you needed a way to restart, but you're not on the server or can't get a remote desktop on the server, or perhaps you're monitoring getMetricData and you have a criterion for which you might wish to restart CFMX.

In this example, which only works on Windows, I'm using the Windows "AT" scheduler to stop and start the ColdFusion MX server at a specified time in the future. The function takes 2 optional imput parameters:

  • [delay] How many minutes to wait until stopping CF
  • [offset] How many minutes to wait after that before restarting CF

Both of the arguments are expressed as minutes. I've written requirements into the UDF to compensate for
a) letting the script complete and successfully run the "at" scheduler service, and
b) to allow for a sufficient time for CF to shutdown before attempting to start again.
Seems reasonable to me that you'd ought not want CF to start at the same time it was shutting down.

In the example below, the test.cfm script tests to see if the average cfm request execution time is greater than some arbritrary value, say 15 seconds, and if so, it calls the restart UDF to stop ColdFusion MX in 2 minutes, and start CFMX 1 minute after that.

I've found that the "at" scheduler on Windows does not respect time in seconds. I've tried running at manually with times such as 18:05:30 to run at 6:05 and 30 seconds, but the job would always run at 6:05 while ignoring the 30 second difference. For this reason the UDF only handles minutes, with a minimum of 1 minute from time of execution until stop and a minimum of 1 minute after that before restarting. In total, from the time the code runs it could be as much as 2-3 minutes before the restart process is complete.

I'm currently working on a *nix version, where the at command is also available, and although on Linux at handles robust time expressions, including strangely enough teatime such as "at teatime -f /tmp/somejob", I can't find a way to pass a secondary command as the job to execute from the commandline. It seems that at will either accept a file (-f) as the script to execute or it enters an interactive shell at the commandline where you can type the job to run. If I figure this out I'll rewrite.

[cffunction name="restart" output="No" returntype="boolean">
[cfargument name="delay" default="1" type="numeric" required="No" />
[cfargument name="offset" default="1" type="numeric" required="No" />
var stopTime = ';
var startTime = ';
var stop = ';
var start = ';
var cronSvc = ';
var cronStopStmt = ';
var cronStartStmt = ';
var bSuccess = ';
[cfif arguments.delay lt 1 or arguments.offset lt 1>
stopTime = timeformat(dateadd("n",arguments.delay,now()),"HH:mm:ss");
startTime = timeformat(dateadd("n",arguments.offset,stopTime),"HH:mm:ss");
stop = 'net stop "ColdFusion MX Application Server"';
start = 'net start "ColdFusion MX Application Server"';
cronSvc = "at";
cronStopStmt = cronSvc &" "& stopTime &" "& stop;
cronStartStmt = cronSvc &" "& startTime &" "& start;
bSuccess = 1;
[cfexecute name="#cronStopStmt#" timeout="0" />
[cfexecute name="#cronStartStmt#" timeout="0" />
[cfcatch>[cfset bSuccess = 0>[/cfcatch>
[cfreturn bSuccess>

[cfinclude template="functions.cfm">

[cfif getMetricData("avg_req_time") gt 15000>
[cfset restart(2,1)>