<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: mJehanno</title>
    <description>The latest articles on Forem by mJehanno (@mjehanno).</description>
    <link>https://forem.com/mjehanno</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F265963%2F50a52211-2a79-4402-bd42-a5e8565b06de.png</url>
      <title>Forem: mJehanno</title>
      <link>https://forem.com/mjehanno</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/mjehanno"/>
    <language>en</language>
    <item>
      <title>Launch a node script at boot on MacOs</title>
      <dc:creator>mJehanno</dc:creator>
      <pubDate>Mon, 07 Mar 2022 07:14:51 +0000</pubDate>
      <link>https://forem.com/mjehanno/launch-a-node-script-at-boot-on-macos-1dnd</link>
      <guid>https://forem.com/mjehanno/launch-a-node-script-at-boot-on-macos-1dnd</guid>
      <description>&lt;p&gt;Sometimes, we need to get things started when our os is booting. In windows, we just create a service and set him to start when the session is open, or we can also move a file in a specific folder. With linux you create a daemon. How can we do the same on macOs ?&lt;br&gt;
That's what we're going to explore here !&lt;/p&gt;
&lt;h2&gt;
  
  
  LaunchD
&lt;/h2&gt;

&lt;p&gt;LaunchD is a tool installed by default on macOs. It is made to handle daemons and agents. LaunchD rely on config files placed in specific folders.&lt;br&gt;
Also, it can manage cron-like task management.&lt;/p&gt;
&lt;h3&gt;
  
  
  Daemon or Agent ?
&lt;/h3&gt;

&lt;p&gt;Before going anywhere we need to get the difference between Agents and Daemons, at least the difference made by Launchd.&lt;br&gt;
It's pretty straight-forward : it depends which user is running the process.&lt;/p&gt;

&lt;p&gt;If the process is running as the &lt;em&gt;current logged user&lt;/em&gt;,  then you will use an &lt;strong&gt;Agent&lt;/strong&gt;, if it's running as &lt;em&gt;root&lt;/em&gt;, then you will use a &lt;strong&gt;Daemon&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;LaunchD gives you the possibility to create three types of Agents and two types of Daemon. The creation of any of these types depends on where you create your config file like shown in the table below :&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Location&lt;/th&gt;
&lt;th&gt;Run on behalf of&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;User Agents&lt;/td&gt;
&lt;td&gt;~/Library/LaunchAgents&lt;/td&gt;
&lt;td&gt;Currently logged in user&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Global Agents&lt;/td&gt;
&lt;td&gt;/Library/LaunchAgents&lt;/td&gt;
&lt;td&gt;Currently logged in user&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Global Daemons&lt;/td&gt;
&lt;td&gt;/Library/LaunchDaemons&lt;/td&gt;
&lt;td&gt;root or the user specified with the key UserName&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;System Agents&lt;/td&gt;
&lt;td&gt;/System/Library/LaunchAgents&lt;/td&gt;
&lt;td&gt;Currently logged in user&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;System Daemons&lt;/td&gt;
&lt;td&gt;/System/Library/LaunchDaemons&lt;/td&gt;
&lt;td&gt;root or the user specified with the key UserName&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Disclaimer : this crystal-clear array is the work of &lt;a href="https://launchd.info/"&gt;LaunchD info&lt;/a&gt; (mentionned in the source part)&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Plist file
&lt;/h3&gt;

&lt;p&gt;In order to run your process, LaunchD need a plist config file placed in a specified folder as we saw previously.&lt;br&gt;
A plist file is basically a simple xml file.&lt;/p&gt;

&lt;p&gt;The minimal template of a plist file looks like this :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;/span&gt; 
    &lt;span class="cp"&gt;&amp;lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&amp;gt;&lt;/span&gt; 
    &lt;span class="nt"&gt;&amp;lt;plist&lt;/span&gt; &lt;span class="na"&gt;version=&lt;/span&gt;&lt;span class="s"&gt;"1.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 
        &lt;span class="nt"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt; 
        &lt;span class="nt"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt; 
    &lt;span class="nt"&gt;&amp;lt;/plist&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, here we just have the xml Schema, a plist tag with used version of plist and a dict.&lt;/p&gt;

&lt;p&gt;Dict here is a &lt;code&gt;Dictionary&lt;/code&gt; type, so it works witk Key and Values.&lt;/p&gt;

&lt;p&gt;First thing first, we need to give a name to our process, it's required by launchd and it needs to be unique as it will be used to identify our job :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;/span&gt; 
    &lt;span class="cp"&gt;&amp;lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&amp;gt;&lt;/span&gt; 
    &lt;span class="nt"&gt;&amp;lt;plist&lt;/span&gt; &lt;span class="na"&gt;version=&lt;/span&gt;&lt;span class="s"&gt;"1.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 
        &lt;span class="nt"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt; 
            &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Label&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;com.mjehanno.myScript&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt; 
    &lt;span class="nt"&gt;&amp;lt;/plist&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can then define the program we want to run. There is two way of doing this :&lt;/p&gt;

&lt;p&gt;You can either have a script defined in a file :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;/span&gt; 
    &lt;span class="cp"&gt;&amp;lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&amp;gt;&lt;/span&gt; 
    &lt;span class="nt"&gt;&amp;lt;plist&lt;/span&gt; &lt;span class="na"&gt;version=&lt;/span&gt;&lt;span class="s"&gt;"1.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 
        &lt;span class="nt"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt; 
            &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Label&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;com.mjehanno.myScript&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Program&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;~/Scripts/myScript.sh&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt; 
    &lt;span class="nt"&gt;&amp;lt;/plist&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or you can pass a array of argument which seems to be the prefered way when dealing with a node script (at least if you don't want to have to handle shebangs and many environnement variable).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;/span&gt; 
    &lt;span class="cp"&gt;&amp;lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&amp;gt;&lt;/span&gt; 
    &lt;span class="nt"&gt;&amp;lt;plist&lt;/span&gt; &lt;span class="na"&gt;version=&lt;/span&gt;&lt;span class="s"&gt;"1.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 
        &lt;span class="nt"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt; 
            &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Label&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;com.mjehanno.myScript&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;ProgramArguments&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;array&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;~/.nvm/versions/node/v14.18.2/bin/node&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;~/Documents/Projects/Javascript/myApp/bin/myApp.js&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;arg1&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;arg2&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/array&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt; 
    &lt;span class="nt"&gt;&amp;lt;/plist&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Speaking about environnement variables, you can pass some to your job.&lt;br&gt;
Let's imagine we need something in our PATH. &lt;br&gt;
We just need to add a dictionary with the right Key :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;/span&gt; 
    &lt;span class="cp"&gt;&amp;lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&amp;gt;&lt;/span&gt; 
    &lt;span class="nt"&gt;&amp;lt;plist&lt;/span&gt; &lt;span class="na"&gt;version=&lt;/span&gt;&lt;span class="s"&gt;"1.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 
        &lt;span class="nt"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt; 
            &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Label&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;com.mjehanno.myScript&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;ProgramArguments&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;array&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;~/.nvm/versions/node/v14.18.2/bin/node&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;~/Documents/Projects/Javascript/myApp/bin/myApp.js&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;arg1&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;arg2&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/array&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;EnvironmentVariables&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;PATH&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;    /Users/mjehanno/.nvm/versions/node/v14.18.2/bin:/Users/mjehnno/.nvm/versions/node/v14.18.2/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin:/Users/mjehanno/Documents/Tools&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt; 
    &lt;span class="nt"&gt;&amp;lt;/plist&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it ! We have a plist file, defining our Job with a unique label, the script we need to run and we even gave him some context with our environnement variable.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Nb : plist files don't really like wildcard like * so you should avoid them in path&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Enable the agent
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Load and Run
&lt;/h4&gt;

&lt;p&gt;Before launching our Agent, we need to load our job definition file in LaunchD.&lt;/p&gt;

&lt;p&gt;LaunchD come with an handy cli called &lt;strong&gt;launchctl&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So now if we want to load our job we can run the following : &lt;/p&gt;

&lt;p&gt;&lt;code&gt;launchtl bootstrap gui/502 ./com.mjehanno.myScript.plist&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;launchctl bootstrap&lt;/code&gt; takes a domain target ( &lt;code&gt;gui/502&lt;/code&gt; where 502 is my UserId) and a path to our plist file.&lt;/p&gt;

&lt;p&gt;Now we can start it  with :&lt;/p&gt;

&lt;p&gt;&lt;code&gt;launchctl kickstart gui/502/com.mjehanno.myScript&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If you want your job to run directly when loaded there is also an option you can pass in the plist file :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;/span&gt; 
    &lt;span class="cp"&gt;&amp;lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&amp;gt;&lt;/span&gt; 
    &lt;span class="nt"&gt;&amp;lt;plist&lt;/span&gt; &lt;span class="na"&gt;version=&lt;/span&gt;&lt;span class="s"&gt;"1.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 
        &lt;span class="nt"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt; 
            &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Label&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;com.mjehanno.myScript&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;ProgramArguments&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;array&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;~/.nvm/versions/node/v14.18.2/bin/node&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;~/Documents/Projects/Javascript/myApp/bin/myApp.js&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;arg1&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;arg2&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/array&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;EnvironmentVariables&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;PATH&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;    /Users/mjehanno/.nvm/versions/node/v14.18.2/bin:/Users/mjehnno/.nvm/versions/node/v14.18.2/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin:/Users/mjehanno/Documents/Tools&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;RunAtLoad&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;true/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt; 
    &lt;span class="nt"&gt;&amp;lt;/plist&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Error Handling
&lt;/h4&gt;

&lt;p&gt;We just launched our agent but we have nothing, no return, no error, we don't know if it's running correctly or not.&lt;/p&gt;

&lt;p&gt;Launchctl gives us the possibility to list our jobs :&lt;/p&gt;

&lt;p&gt;&lt;code&gt;launchctl list&lt;/code&gt;  &lt;em&gt;(you might want to grep on the label you defined in your plist file)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This command will just display a list of all jobs loaded with their PID (if they are running), their label and a code representing their current status. Yet we don't know what does status code means.&lt;/p&gt;

&lt;p&gt;No problem here, launchctl at the rescue again :&lt;/p&gt;

&lt;p&gt;&lt;code&gt;launchctl error [errorCode]&lt;/code&gt; will give you a human readable description of the problem.&lt;/p&gt;

&lt;p&gt;Also, you can unload your job at any time :&lt;/p&gt;

&lt;p&gt;&lt;code&gt;launchctl bootout /gui/502/com.mjehanno.myScript&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;Or stop it with :&lt;/p&gt;

&lt;p&gt;&lt;code&gt;launchctl kill [sigTerm] /gui/502/com.mjehanno.myScript&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Finally, in your plist file you can also redirect stdout and stderr of your job to files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;/span&gt; 
    &lt;span class="cp"&gt;&amp;lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&amp;gt;&lt;/span&gt; 
    &lt;span class="nt"&gt;&amp;lt;plist&lt;/span&gt; &lt;span class="na"&gt;version=&lt;/span&gt;&lt;span class="s"&gt;"1.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 
        &lt;span class="nt"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt; 
            &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Label&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;com.mjehanno.myScript&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;ProgramArguments&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;array&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;~/.nvm/versions/node/v14.18.2/bin/node&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;~/Documents/Projects/Javascript/myApp/bin/myApp.js&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;arg1&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;arg2&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/array&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;EnvironmentVariables&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;PATH&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;    /Users/mjehanno/.nvm/versions/node/v14.18.2/bin:/Users/mjehnno/.nvm/versions/node/v14.18.2/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin:/Users/mjehanno/Documents/Tools&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;RunAtLoad&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;true/&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;StandardOutPath&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;/tmp/com.mjehanno.myScript.out&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;StandardErrorPath&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;/tmp/com.mjehanno.myScript.err&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt; 
        &lt;span class="nt"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt; 
    &lt;span class="nt"&gt;&amp;lt;/plist&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Warning : In case of an Agent, your user needs to have write access to the path you provided for &lt;code&gt;StandardOutPath&lt;/code&gt; or &lt;code&gt;StandardErrorPath&lt;/code&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Tips
&lt;/h4&gt;

&lt;p&gt;I bumped into a command supposed to verify the integrity of your plist file :&lt;/p&gt;

&lt;p&gt;&lt;code&gt;plutil [pathToPlistFile]&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  GUI
&lt;/h2&gt;

&lt;p&gt;If you don't want to deal with this stuff yourself, you can use a GUI app to manage your LaunchD configuration.  At the moment I'm writing this I found two available options.&lt;br&gt;
Both are paid-app but you can still use some part freely (only saving configuration will not work on the free-tier).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LaunchControl&lt;/li&gt;
&lt;li&gt;Lingon&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;[EDIT]&lt;/p&gt;

&lt;h2&gt;
  
  
  TUI
&lt;/h2&gt;

&lt;p&gt;If you're not afraid of using a terminal, you can use &lt;a href="https://github.com/wecraftforfun/launch-tui"&gt;launch-tui&lt;/a&gt; to manage your agents and this one is completly free.&lt;/p&gt;

&lt;p&gt;[EDIT]&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://launchd.info/"&gt;LaunchD info&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://babodee.wordpress.com/2016/04/09/launchctl-2-0-syntax/"&gt;Launchctl 2.0 Syntax&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/masklinn/a532dfe55bdeab3d60ab8e46ccc38a68"&gt;Launchctl cheatsheet&lt;/a&gt;&lt;/p&gt;

</description>
      <category>macos</category>
      <category>automation</category>
      <category>node</category>
    </item>
  </channel>
</rss>
