{"id":1640,"date":"2015-08-23T20:14:56","date_gmt":"2015-08-24T02:14:56","guid":{"rendered":"http:\/\/dev.iachieved.it\/iachievedit\/?p=1640"},"modified":"2015-08-23T20:14:56","modified_gmt":"2015-08-24T02:14:56","slug":"using-monit-with-node-js-and-pm2","status":"publish","type":"post","link":"https:\/\/dev.iachieved.it\/iachievedit\/using-monit-with-node-js-and-pm2\/","title":{"rendered":"Using Monit with Node.js and PM2"},"content":{"rendered":"<p>As I&#8217;ve said <a href=\"http:\/\/dev.iachieved.it\/iachievedit\/a-look-at-apples-swift\/\">before<\/a>, I&#8217;m a bit of a whore when it comes to learning new languages and development frameworks.  So it comes as no surprise to myself that at some point I&#8217;d start looking at <a href=\"https:\/\/nodejs.org\/\">Node.js<\/a> and <a href=\"https:\/\/www.javascript.com\/\">JavaScript<\/a>.<\/p>\n<p>I have another confession to make.  I hate JavaScript, even more so than PHP.  Nothing about the language is appealing to me, whether its the rules about scoping and the use of <code>var<\/code> or the bizarre mechanism by which classes are declared (not to mention there are several ways).  Semicolons are optional, <i>kind of<\/i>, but not really.  I know plenty of developers who enjoy programming in Objective-C, Python, Ruby, etc.; I have never met <i>anyone<\/i> who says &#8220;Me? I love JavaScript!&#8221;  Well, perhaps a web UI developer whose only other &#8220;language&#8221; is CSS or HTML.  In fact, a lot of people go out of their way to articulate why <a href=\"http:\/\/whydoesitsuck.com\/why-does-javascript-suck\/\">JavaScript sucks<\/a>.<\/p>\n<p>So along comes Node.js, which we can all agree is the new hotness.  I&#8217;m not sure <i>why<\/i> it is so appealing.  JavaScript on the server!  Event-driven programming!  Everything is asynchronous and nothing blocks!  Okay, great.  I didn&#8217;t really <i>ask<\/i> for JavaScript on the server, and event-driven programming is not new.  When you develop iOS applications you&#8217;re developing in an <a href=\"https:\/\/developer.apple.com\/library\/ios\/documentation\/General\/Conceptual\/Devpedia-CocoaApp\/MainEventLoop.html\">event-driven environment<\/a>.  Python developers have had the <a href=\"https:\/\/twistedmatrix.com\/trac\/\">Twisted<\/a> framework for <i>years<\/i>.  The venerable <a href=\"https:\/\/en.wikipedia.org\/wiki\/X_Window_System\">X<\/a> system is built upon an event loop.  Reading the Node.js hype online one would think event-driven callback execution was invented in the 21st century.<\/p>\n<p>Of course, the Node.js community is also reinventing the wheel in other areas as well.  What do the following have in common:  <code>brew<\/code>, <code>apt-get<\/code>, <code>rpm<\/code>, <code>gem<\/code>, <code>easy_install<\/code>, <code>pip<\/code>.  Every last one is a &#8220;package manager&#8221; of some sort, aimed at making your life easy, automagically downloading and installing software along with all of its various dependencies onto your system.  A new framework is nothing without a package manager that it can call its own, thus the Node.js world gives us the <a href=\"https:\/\/www.npmjs.com\/\">Node Package Manager<\/a>, or <code>npm<\/code>.  That&#8217;s fine.  I like to think of myself as a &#8220;full-stack developer&#8221;, so if I need to learn a new package manager and all of its quirks, so be it.  <\/p>\n<p>Unfortunately it didn&#8217;t stop there.  Node.js has its own collection of application &#8220;management&#8221; utilities; you know, those helper utilities that aim to provide an &#8220;environment&#8221; in which to run your application.  Apparently <a href=\"https:\/\/github.com\/foreverjs\/forever\">Forever<\/a> was popular for some time until it was displaced by <a href=\"https:\/\/github.com\/Unitech\/pm2\">PM2<\/a>, a &#8220;Production process manager for Node.js \/ io.js applications&#8221;<\/p>\n<p>I&#8217;m not quite sure when it became en vogue to release version 0 software for production environments, but I suppose it&#8217;s all arbitrary (hell, Node.js is what, 0.12?) But true to a version 0 software release, PM2 has given me nothing but fits in creating a system that <i>consistently<\/i> brings up a Node.js application upon reboot.  Particularly in machine-to-machine (<a href=\"https:\/\/en.wikipedia.org\/wiki\/Machine_to_machine\">M2M<\/a>) applications this is important; there is frequently no opportunity to ssh into a device that&#8217;s on the cellular network and installed out in an oil field tank site.  The system must be rock-solid and touch free once it&#8217;s installed in the field.<\/p>\n<p>To date the most pernicious bug I&#8217;ve come across with PM2 is it completely eating the <code>dump.pm2<\/code> file that it ostensibly uses to &#8220;resurrect&#8221; the environment that was operating.  A number of people have reported <a href=\"https:\/\/github.com\/Unitech\/PM2\/issues\/1035\">this issue<\/a> as well.  If I can&#8217;t rely on PM2 to consistently restart my Node.js application, I need something to watch the watchers.  So who watches the watchers?  <a href=\"https:\/\/mmonit.com\/monit\/\">Monit<\/a> of course.<\/p>\n<p>Because PM2 refused to cooperate I decided to utilize monit to ensure my Node.js application process was up and running, even after a reboot.  In this configuration file example I am checking my process pid (located in the <code>\/root\/.pm2\/pids<\/code> directory) and then using <code>pm2 start<\/code> and <code>pm2 stop<\/code> as the start and stop actions.<\/p>\n<p><b>NB<\/b>:  Monit executes its scripts with a bare bones environment. If you are ever stumped by why your actions &#8220;work on the command line but not with monit&#8221;, see this <a href=\"http:\/\/stackoverflow.com\/questions\/3356476\/debugging-monit\">this<\/a> Stack Overflow post.  In the case of PM2, it is critical that the <code>PM2_HOME<\/code> environment variable be set prior to calling <code>pm2<\/code>.<\/p>\n<p>The first iteration of my monit configuration looked like this:<\/p>\n<pre>\r\ncheck process node_app with pidfile \/root\/.pm2\/pids\/node_app-0.pid\r\n  start program = \"\/bin\/bash -lc 'cd \/root\/node_app && PM2_HOME=\/root\/.pm2 \/usr\/bin\/pm2 startOrRestart processes.json'\"\r\n  stop program = \"\/bin\/bash -lc 'cd \/root\/node_app && PM2_HOME=\/root\/.pm2 \/usr\/bin\/pm2 stop processes.json'\"\r\n<\/pre>\n<p>Only if this were sufficient, but it isn&#8217;t.<\/p>\n<p>For some reason PM2 insists on appending a process ID to the pidfile filename (perhaps for clustering where you need a bunch of processes of the same name), so a simple pidfile check won&#8217;t suffice.  Other folks even went to the Monit lists looking for <a href=\"https:\/\/lists.nongnu.org\/archive\/html\/monit-general\/2015-03\/msg00063.html\">wildcard pidfile support<\/a> and quoted PM2 as the reason why they felt they needed it.<\/p>\n<p>So, now our monit configuration takes advantage of the <code>matching<\/code> directive and looks like this:<\/p>\n<pre>\r\ncheck process node_app matching \/root\/node_app\/app.js\r\n   start program = \"\/bin\/bash -lc 'cd \/root\/node_app && PM2_HOME=\/root\/.pm2 \/usr\/bin\/pm2 startOrRestart processes.json'\"\r\n   stop program  = \"\/bin\/bash -lc 'cd \/root\/node_app && PM2_HOME=\/root\/.pm2 \/usr\/bin\/pm2 stop processes.json'\"\r\n<\/pre>\n<p>Granted, we <i>should not<\/i> be running as <code>root<\/code> here.  Future iterations will move the applications to a non-privileged user, but for now this gives us a system that successfully restarts our Node.js applications after a reboot.  PM2 is a promising tool and definitely takes care of a lot of mundane tasks we need to accomplish to daemonize an application; unfortunately it is a little rough around the edges when it comes to consistent actions surrounding the ability to survive system restarts.  Don&#8217;t take my word for it:  read the Github <a href=\"https:\/\/github.com\/Unitech\/PM2\/issues?&#038;q=is%3Aissue+is%3Aopen+reboot\">issues<\/a>.<\/p>\n<h3>Conclusion<\/h3>\n<p>A rolling stone gathers no moss.  The more things stay the same, the more things change (or is it the other way around?).  I have nothing against new frameworks, but there are times when being an early adopter requires one to pull out a tried-and-true applications to get the job done.  In this case our old friend Monit helps up fill in the gaps while Node.js and PM2 mature.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>As I&#8217;ve said before, I&#8217;m a bit of a whore when it comes to learning new languages and development frameworks. So it comes as no surprise to myself that at some point I&#8217;d start looking at Node.js and JavaScript. I have another confession to make. I hate JavaScript, even more so than PHP. Nothing about [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[21,19,14],"tags":[],"class_list":["post-1640","post","type-post","status-publish","format-standard","hentry","category-devops","category-linux","category-node-js"],"_links":{"self":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/1640"}],"collection":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/comments?post=1640"}],"version-history":[{"count":36,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/1640\/revisions"}],"predecessor-version":[{"id":1676,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/1640\/revisions\/1676"}],"wp:attachment":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/media?parent=1640"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/categories?post=1640"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/tags?post=1640"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}