{"id":13455060,"url":"https://github.com/coreybutler/node-mac","last_synced_at":"2025-05-16T08:03:28.314Z","repository":{"id":7385050,"uuid":"8713206","full_name":"coreybutler/node-mac","owner":"coreybutler","description":"Node utilities for Mac","archived":false,"fork":false,"pushed_at":"2024-05-16T22:30:45.000Z","size":1788,"stargazers_count":539,"open_issues_count":11,"forks_count":51,"subscribers_count":16,"default_branch":"master","last_synced_at":"2025-05-09T12:51:20.441Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/coreybutler.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["coreybutler"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2013-03-11T21:00:43.000Z","updated_at":"2025-05-02T19:05:24.000Z","dependencies_parsed_at":"2024-10-30T14:13:21.021Z","dependency_job_id":null,"html_url":"https://github.com/coreybutler/node-mac","commit_stats":{"total_commits":65,"total_committers":8,"mean_commits":8.125,"dds":"0.19999999999999996","last_synced_commit":"2bf9e64f637f3ab1f036bf69c1205d0f6c227e7b"},"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coreybutler%2Fnode-mac","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coreybutler%2Fnode-mac/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coreybutler%2Fnode-mac/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coreybutler%2Fnode-mac/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/coreybutler","download_url":"https://codeload.github.com/coreybutler/node-mac/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254493381,"owners_count":22080126,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T08:01:00.820Z","updated_at":"2025-05-16T08:03:28.286Z","avatar_url":"https://github.com/coreybutler.png","language":"JavaScript","readme":"# node-mac\r\n\r\n[![NPM version](https://badge.fury.io/js/node-mac.png)](http://badge.fury.io/js/node-mac)\r\n[![NGN Dependencies](https://david-dm.org/coreybutler/node-mac.png)](https://david-dm.org/coreybutler/node-mac)\r\n[![Build](https://api.travis-ci.org/coreybutler/node-mac.png)](https://travis-ci.org/coreybutler/node-mac)\r\n\r\n**Sponsors (as of 2020)**\r\n\r\n\u003ctable cellpadding=\"10\" cellspacing=\"0\" border=\"0\"\u003e\r\n  \u003ctr\u003e\r\n    \u003ctd\u003e\u003ca href=\"https://metadoc.io\"\u003e\u003cimg src=\"https://github.com/coreybutler/staticassets/raw/master/sponsors/metadoclogobig.png\" width=\"200px\"/\u003e\u003c/a\u003e\u003c/td\u003e\r\n    \u003ctd\u003e\u003ca href=\"https://butlerlogic.com\"\u003e\u003cimg src=\"https://github.com/coreybutler/staticassets/raw/master/sponsors/butlerlogic_logo.png\" width=\"200px\"/\u003e\u003c/a\u003e\u003c/td\u003e\r\n  \u003c/tr\u003e\r\n\u003c/table\u003e\r\n\r\nFollow the author on [Twitter (@goldglovecb)](http://twitter.com/goldglovecb).\r\n\r\nThis README provides a pretty good overview of what node-mac has to offer, but better\r\ndocumentation is now available at the [node-mac documentation portal](http://coreybutler.github.io/node-mac).\r\n\r\n# node-mac\r\n\r\nThis is a standalone module, originally designed for internal use in [NGN](http://github.com/ngnjs/NGN).\r\nHowever; it is capable of providing the same features for Node.js scripts independently of NGN.\r\n\r\nFor alternative versions, see [node-windows](http://github.com/coreybutler/node-windows) and [node-linux](http://github.com/coreybutler/node-linux)\r\n\r\n## Overview\r\n\r\nThis module helps create/manage native processes and event logs for Node.js applications on Mac OSX.\r\n\r\n![Mac](https://user-images.githubusercontent.com/770982/86995965-fa1da980-c16f-11ea-89d6-9204fb172df6.png)\r\n\r\n\u003e **Notice** Some vesions of Node will not display the pretty title (Hello World) of the process. See the [underlying issue](https://github.com/nodejs/node/issues/28945) in Node core. Instead, it just displays \"node\", but still functions normally.\r\n\r\nTo start, install node-mac via:\r\n\r\n    npm install node-mac\r\n\r\nnode-mac is a utility for creating/managing Node.js scripts as OSX daemons. Please note that like\r\nall OSX daemons, creating one requires sudo/root privileges. To create a service with\r\nnode-mac, prepare a script like:\r\n\r\n``` js\r\n    var Service = require('node-mac').Service;\r\n\r\n    // Create a new service object\r\n    var svc = new Service({\r\n      name:'Hello World',\r\n      description: 'The nodejs.org example web server.',\r\n      script: '/path/to/helloworld.js'\r\n    });\r\n\r\n    // Listen for the \"install\" event, which indicates the\r\n    // process is available as a service.\r\n    svc.on('install',function(){\r\n      svc.start();\r\n    });\r\n\r\n    svc.install();\r\n```\r\n\r\nThe code above creates a new `Service` object, providing a pretty name and description.\r\nThe `script` attribute identifies the Node.js script that should run as a service. Upon running\r\nthis, the script will be visible from the Activity Monitor.\r\n\r\nThe `Service` object emits the following events:\r\n\r\n- _install_ - Fired when the script is installed as a service.\r\n- _alreadyinstalled_ - Fired if the script is already known to be a service.\r\n- _invalidinstallation_ - Fired if an installation is detected but missing required files.\r\n- _uninstall_ - Fired when an uninstallation is complete.\r\n- _start_ - Fired when the new service is started.\r\n- _stop_ - Fired when the service is stopped.\r\n- _error_ - Fired in some instances when an error occurs.\r\n\r\nIn the example above, the script listens for the `install` event. Since this event\r\nis fired when a service installation is complete, it is safe to start the service.\r\n\r\nServices created by node-mac are similar to most other services running on OSX.\r\nThey can be stopped from the Activity Monitor and make logs available in the Console app.\r\n\r\n## Environment Variables\r\n\r\nSometimes you may want to provide a service with static data, passed in on creation of the service. You can do this by setting environment variables in the service config, as shown below:\r\n\r\n``` js\r\n    var svc = new Service({\r\n      name:'Hello World',\r\n      description: 'The nodejs.org example web server.',\r\n      script: '/path/to/helloworld.js',\r\n      env: {\r\n        name: \"HOME\",\r\n        value: process.env[\"USERPROFILE\"] // service is now able to access the user who created its home directory\r\n      }\r\n    });\r\n```\r\n\r\nYou can also supply an array to set multiple environment variables:\r\n\r\n``` js\r\n    var svc = new Service({\r\n      name:'Hello World',\r\n      description: 'The nodejs.org example web server.',\r\n      script: '/path/to/helloworld.js',\r\n      env: [{\r\n        name: \"HOME\",\r\n        value: process.env[\"USERPROFILE\"] // service is now able to access the user who created its home directory\r\n      },\r\n      {\r\n        name: \"TEMP\",\r\n        value: path.join(process.env[\"USERPROFILE\"],\"/temp\") // use a temp directory in user's home directory\r\n      }]\r\n    });\r\n```\r\n\r\n## Cleaning Up: Uninstall a Service\r\n\r\nUninstalling a previously created service is syntactically similar to installation.\r\n\r\n``` js\r\n    var Service = require('node-mac').Service;\r\n\r\n    // Create a new service object\r\n    var svc = new Service({\r\n      name:'Hello World',\r\n      script: require('path').join(__dirname,'helloworld.js')\r\n    });\r\n\r\n    // Listen for the \"uninstall\" event so we know when it's done.\r\n    svc.on('uninstall',function(){\r\n      console.log('Uninstall complete.');\r\n      console.log('The service exists: ',svc.exists);\r\n    });\r\n\r\n    // Uninstall the service.\r\n    svc.uninstall();\r\n```\r\n\r\nThe uninstall process only removes process-specific files. **It does NOT delete your Node.js script, but it will remove the logs!**\r\nThis process also removes the plist file for the service.\r\n\r\n## What Makes node-mac Services Unique?\r\n\r\nLots of things!\r\n\r\n**Long Running Processes \u0026 Monitoring:**\r\n\r\nThe built-in service recovery for OSX services is fairly limited and cannot easily be configured\r\nfrom code. Therefore, node-mac creates a wrapper around the Node.js script. This wrapper\r\nis responsible for restarting a failed service in an intelligent and configurable manner. For example,\r\nif your script crashes due to an unknown error, node-mac will attempt to restart it. By default,\r\nthis occurs every second. However; if the script has a fatal flaw that makes it crash repeatedly,\r\nit adds unnecessary overhead to the system. node-mac handles this by increasing the time interval\r\nbetween restarts and capping the maximum number of restarts.\r\n\r\n**Smarter Restarts That Won't Pummel Your Server:**\r\n\r\nUsing the default settings, node-mac adds 25% to the wait interval each time it needs to restart\r\nthe script. With the default setting (1 second), the first restart attempt occurs after one second.\r\nThe second occurs after 1.25 seconds. The third after 1.56 seconds (1.25 increased by 25%) and so on.\r\nBoth the initial wait time and the growth rate are configuration options that can be passed to a new\r\n`Service`. For example:\r\n\r\n``` js\r\n    var svc = new Service({\r\n      name:'Hello World',\r\n      description: 'The nodejs.org example web server.',\r\n      script: '/path/to/helloworld.js',\r\n      wait: 2,\r\n      grow: .5\r\n    });\r\n```\r\n\r\nIn this example, the wait period will start at 2 seconds and increase by 50%. So, the second attempt\r\nwould be 3 seconds later while the fourth would be 4.5 seconds later.\r\n\r\n**Don't DOS Yourself!**\r\n\r\nRepetitive recycling could potentially go on forever with a bad script. To handle these situations, node-mac\r\nsupports two kinds of caps. Using `maxRetries` will cap the maximum total number of times the service\r\nrestarts itself before it kills the process. By default, this is unlimited. Setting it to 3 would tell the\r\nprocess to stop restarting itself (i.e. leave the dead process alone) after it tries to restart it 3 times.\r\n\r\nAnother option is `maxRestarts`, which caps the number of restarts attempted within a 60 second period.\r\nFor example, if this is set to 3 (the default) and the process crashes/restarts repeatedly,\r\nnode-mac will stop restarting the process after the 3rd crash within a 60 second timeframe.\r\n\r\nBoth of these configuration options can be set, just like `wait` or `grow`.\r\n\r\nFinally, an attribute called `abortOnError` can be set to `true` if you want your script to **not** restart\r\nat all when it exits with an error.\r\n\r\n## How Services Are Made\r\n\r\nnode-mac uses the `launchd` utility to create a unique process\r\nfor each Node.js script deployed as a service. A plist file is created in `/Library/LaunchDaemons`\r\nby default. Additionally, two log files are generated in `/Library/Logs/\u003cname\u003e` for general output\r\nand error logging.\r\n\r\n## Event Logging\r\n\r\n![Mac log](https://user-images.githubusercontent.com/770982/86995948-f0944180-c16f-11ea-81c9-0561435092aa.png)\r\n\r\nServices created with node-mac have two event logs that can be viewed through the Console app.\r\nA log source named `myappname.log` provides basic logging for the service. It can be used to see\r\nwhen the entire service starts/stops. A second log, named `myappname_error.log` stores error output.\r\n\r\nBy default, any `console.log`, `console.warn`, `console.error` or other output will be made available\r\nin one of these two files.\r\n\r\n# License (MIT)\r\n\r\nCopyright (c) 2013 Corey Butler\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining\r\na copy of this software and associated documentation files (the\r\n'Software'), to deal in the Software without restriction, including\r\nwithout limitation the rights to use, copy, modify, merge, publish,\r\ndistribute, sublicense, and/or sell copies of the Software, and to\r\npermit persons to whom the Software is furnished to do so, subject to\r\nthe following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be\r\nincluded in all copies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\r\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\r\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\r\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\r\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\r\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r\n","funding_links":["https://github.com/sponsors/coreybutler"],"categories":["Packages","Repository","包","Process management","目录","JavaScript","Number"],"sub_categories":["Process management","进程管理","流程管理"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoreybutler%2Fnode-mac","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcoreybutler%2Fnode-mac","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoreybutler%2Fnode-mac/lists"}