When I’m rolling out an update to a Web2 app, I have an administrator UI button that I can click which finds active sessions and sends them to a “Sorry, website is being rebooted” page. It works great. The only problem is I have to remember to log in and click the button.
My question is - is there a way to communicate with the WebApp via the command line? That way I could write a shell script to deploy the update, something like:
tell the WebApp to notify users it’s going down
kill the WebApp
copy the new WebApp to the server
launch the new WebApp
I’m thinking maybe I could use the kill command with a different signal? kill -signal_name INT /path/to/my/webApp
is it possible to catch these signals in a WebApp?
(this is on macOS)
You could catch the incoming commandline in the app.opening event, and if there’s an existing mutex, pass the command line over to the already running version of the webapp (and a 2nd instance doesn’t open). You could then take the incoming command line, use it as a trigger against user Sessions to prompt the app will be going down, and begin the back-side script to terminate, download, replace, and restart your application?
Alternatively - you could add an admin interface to the webapp or an admin-only url that causes the same events to happen? I use this method with one of our web 1.0 apps. The app knows of all remote instances and begins requesting the admin-only url to trigger each instance to begin updating at the remote-end. It then pings each application after X amount of time to ensure the app updated and restarted, otherwise, sending a notice to the instance account holder to look into the issue or manually restart their system (have only had it happen only once honestly, - due to a user caused breaking event in a linux upgrade by the user using experimental APT sources)
SIGKILL is too Killy. I need a few seconds to notify the sessions before the App actually quits. I might try using SIGHUP Or another signal first and then follow it later was SIGKILL
The idea of using a Mutex is interesting, but wouldn’t the second app launched be unable to bind the server port? Not sure how that would work
**I would give it a test - in that case, it would cause an unhandledexception - where you could then handle the exception appropriately without a hard-crash to the mutex, do what’s needed, and end gracefully
Alternatively - you could make the webapp port dependent on it’s opening commandline setting the port in the “restarting command line commands” that get sent - which would also prevent any port conflicts? There’s a few options available to avoid port conflicts to achieve the same.
The app just terminates with the message it couldn’t bind to the port. I have an app that runs a cleanup cron job using the same webapp but receiving params via command line. Once Open(ing) completes it quits because of the port in use, but I personally feel safer adding a Quit to the end of the cleanup routine.
I think this is my favorite solution, as it would be cross-platform (assuming the ‘curl’ utility exists on your platform - does Windows have this?) I’m using macOS which definitely does.
You would need to include a redistributable OpenSSL installation (contains the needed curl items for Windows machines). Current version viewable at: curl for Windows
Just confirmed with a fellow Microsoft employee that CURL as well as TAR became native to Windows 10 starting in 2018 - you should be ok! Any systems/os’s prior to that, that are windows-based will require OpenSSL to be installed.
echo "############################################################"
echo "# Sending go_offline to WebApp"
echo "############################################################"
# note: this sends a special URL to HandleURL so we can alert all sessions that the server is going down
curl https:/example.com/go_offline?token=EAFCDEDA
sleep 1
In App.HandleURL:
select case request.Path
case "go_offline"
dim c as string = request.Parameter("token")
c = c.DefineEncoding(Encodings.UTF8)
if c = "EAFCDEDA" then
response.MIMEType = "text/html"
response.Write "<html><body>Going offline</body></html>"
response.Status = 200
call ForceUsersOffline(true) // A method which iterates through all sessions and sends them to the "offline" webpage
return true