{"id":31330932,"url":"https://github.com/therootcompany/serviceman","last_synced_at":"2025-09-26T00:41:13.231Z","repository":{"id":45068811,"uuid":"317996178","full_name":"therootcompany/serviceman","owner":"therootcompany","description":"Cross-platform service management for Mac, Linux, and Windows.","archived":false,"fork":false,"pushed_at":"2024-12-12T17:12:44.000Z","size":4679,"stargazers_count":43,"open_issues_count":3,"forks_count":6,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-12-12T17:43:22.821Z","etag":null,"topics":["launchd","linux","mac","systemd","windows","windows-service-wrapper"],"latest_commit_sha":null,"homepage":"https://webinstall.dev/serviceman","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/therootcompany.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"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}},"created_at":"2020-12-02T21:28:07.000Z","updated_at":"2024-12-12T16:50:25.000Z","dependencies_parsed_at":"2024-06-20T15:32:53.456Z","dependency_job_id":"ffb882d7-0f2a-4575-a16f-851245ad7c0a","html_url":"https://github.com/therootcompany/serviceman","commit_stats":null,"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/therootcompany/serviceman","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/therootcompany%2Fserviceman","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/therootcompany%2Fserviceman/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/therootcompany%2Fserviceman/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/therootcompany%2Fserviceman/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/therootcompany","download_url":"https://codeload.github.com/therootcompany/serviceman/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/therootcompany%2Fserviceman/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":277004900,"owners_count":25743691,"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","status":"online","status_checked_at":"2025-09-25T02:00:09.612Z","response_time":80,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["launchd","linux","mac","systemd","windows","windows-service-wrapper"],"created_at":"2025-09-26T00:41:11.059Z","updated_at":"2025-09-26T00:41:13.219Z","avatar_url":"https://github.com/therootcompany.png","language":"Go","funding_links":[],"categories":["linux"],"sub_categories":[],"readme":"# New, Rewritten Version at New Repo\n\nSee \u003chttps://github.com/bnnanet/serviceman\u003e.\n\n## [serviceman-sh](https://github.com/bnnanet/serviceman)\n\nThe new version is rewritten in POSIX script.\n\nThe **transitional version 0.9.x** will print several **warnings for options that have changed**, except `--user`, which is now `--agent` (as it was rarely used, and most often caused confusion).\n\nSee [Changes in v1.0](https://github.com/bnnanet/serviceman?tab=readme-ov-file#changes-in-v10) for details.\n\n# [go-serviceman](https://git.rootprojects.org/root/serviceman) (DEPRECATED)\n\nCross-platform service management made easy.\n\n\u003e sudo serviceman add --name foo ./serve.js --port 3000\n\n\u003e Success: \"foo\" started as a \"launchd\" SYSTEM service, running as \"root\"\n\n## Why?\n\nBecause it sucks to debug launchctl, systemd, etc.\n\nAlso, I wanted a reasonable way to install [Telebit](https://telebit.io) on Windows.\n(see more in the **More Why** section below)\n\n## Features\n\n-   Unprivileged (User Mode) Services with `--user` (_Default_)\n    -   [x] Linux (`sytemctl --user`)\n    -   [x] MacOS (`launchctl`)\n    -   [x] Windows (`HKEY_CURRENT_USER/.../Run`)\n-   Privileged (System) Services with `--system` (_Default_ for `root`)\n    -   [x] Linux (`sudo sytemctl`)\n    -   [x] MacOS (`sudo launchctl`)\n    -   [ ] Windows (_not yet implemented_)\n\n# Table of Contents\n\n-   Usage\n-   Install\n-   Examples\n    -   compiled programs\n    -   scripts\n    -   bash\n    -   node\n    -   python\n    -   ruby\n    -   PATH\n-   Logging\n-   Debugging\n-   Windows\n-   Building\n-   More Why\n-   Legal\n\n# Usage (DEPRECATED)\n\nThe basic pattern of usage:\n\n```bash\nsudo serviceman add --name \"foobar\" [options] [interpreter] \u003cservice\u003e [--] [service options]\nsudo serviceman start \u003cservice\u003e\nsudo serviceman stop \u003cservice\u003e\nsudo serviceman list --all\nserviceman version\n```\n\nAnd what that might look like:\n\n```bash\nsudo serviceman add --name \"foo\" foo.exe -c ./config.json\n```\n\nYou can also view the help:\n\n```\nserviceman add --help\n```\n\n# System Services VS User Mode Services\n\nUser services start **on login**.\n\nSystem services start **on boot**.\n\nThe **default** is to register a _user_ services. To register a _system_ service, use `sudo` or run as `root`.\n\n# Install\n\n**Note**: v0.9.x+ install from \u003chttps://github.com/bnnanet/serviceman\u003e.\n\nYou can install `serviceman` directly from the official git releases with [`webi`](https://webinstall.dev/serviceman):\n\n**Mac**, **Linux**:\n\n```bash\ncurl -sL https://webinstall.dev/serviceman | bash\n```\n\n**Windows 10**:\n\n```pwsh\ncurl.exe -sLA \"MS\" https://webinstall.dev/serviceman | powershell\n```\n\nYou can run this from cmd.exe or PowerShell (curl.exe is a native part of Windows 10).\n\n## Manual Install\n\nThere are a number of pre-built binaries.\n\nIf none of them work for you, or you prefer to build from source,\nsee the instructions for building far down below.\n\n## Downloads\n\n```\ncurl -fsSL \"https://rootprojects.org/serviceman/dist/$(uname -s)/$(uname -m)/serviceman\" -o serviceman\nchmod +x ./serviceman\n```\n\n### MacOS\n\n\u003cdetails\u003e\n\u003csummary\u003eSee download options\u003c/summary\u003e\n\nMacOS (darwin): [64-bit Download ](https://rootprojects.org/serviceman/dist/darwin/amd64/serviceman)\n\n```\ncurl https://rootprojects.org/serviceman/dist/darwin/amd64/serviceman -o serviceman\nchmod +x ./serviceman\n```\n\n\u003c/details\u003e\n\n### Windows\n\n\u003cdetails\u003e\n\u003csummary\u003eSee download options\u003c/summary\u003e\nWindows 10: [64-bit Download](https://rootprojects.org/serviceman/dist/windows/amd64/serviceman.exe)\n\n```\npowershell.exe $ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest https://rootprojects.org/serviceman/dist/windows/amd64/serviceman.exe -OutFile serviceman.exe\n```\n\n**Debug version**:\n\n```\npowershell.exe $ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest https://rootprojects.org/serviceman/dist/windows/amd64/serviceman.debug.exe -OutFile serviceman.debug.exe\n```\n\nWindows 7: [32-bit Download](https://rootprojects.org/serviceman/dist/windows/386/serviceman.exe)\n\n```\npowershell.exe \"(New-Object Net.WebClient).DownloadFile('https://rootprojects.org/serviceman/dist/windows/386/serviceman.exe', 'serviceman.exe')\"\n```\n\n**Debug version**:\n\n```\npowershell.exe \"(New-Object Net.WebClient).DownloadFile('https://rootprojects.org/serviceman/dist/windows/386/serviceman.debug.exe', 'serviceman.debug.exe')\"\n```\n\n\u003c/details\u003e\n\n### Linux\n\n\n\u003cdetails\u003e\n\u003csummary\u003eSee download options\u003c/summary\u003e\n\nLinux (64-bit): [Download](https://rootprojects.org/serviceman/dist/linux/amd64/serviceman)\n\n```\ncurl https://rootprojects.org/serviceman/dist/linux/amd64/serviceman -o serviceman\nchmod +x ./serviceman\n```\n\nLinux (32-bit): [Download](https://rootprojects.org/serviceman/dist/linux/386/serviceman)\n\n```\ncurl https://rootprojects.org/serviceman/dist/linux/386/serviceman -o serviceman\nchmod +x ./serviceman\n```\n\n\u003c/details\u003e\n\n### Raspberry Pi (Linux ARM)\n\n\u003cdetails\u003e\n\u003csummary\u003eSee download options\u003c/summary\u003e\n\nRPi 4 (64-bit armv8): [Download](https://rootprojects.org/serviceman/dist/linux/armv8/serviceman)\n\n```\ncurl https://rootprojects.org/serviceman/dist/linux/armv8/serviceman -o serviceman`\nchmod +x ./serviceman\n```\n\nRPi 3 (armv7): [Download](https://rootprojects.org/serviceman/dist/linux/armv7/serviceman)\n\n```\ncurl https://rootprojects.org/serviceman/dist/linux/armv7/serviceman -o serviceman\nchmod +x ./serviceman\n```\n\nARMv6: [Download](https://rootprojects.org/serviceman/dist/linux/armv6/serviceman)\n\n```\ncurl https://rootprojects.org/serviceman/dist/linux/armv6/serviceman -o serviceman\nchmod +x ./serviceman\n```\n\nRPi Zero (armv5): [Download](https://rootprojects.org/serviceman/dist/linux/armv5/serviceman)\n\n```\ncurl https://rootprojects.org/serviceman/dist/linux/armv5/serviceman -o serviceman\nchmod +x ./serviceman\n```\n\n\u003c/details\u003e\n\n### Add to PATH\n\n**Windows**\n\n```\nmkdir %userprofile%\\bin\nmove serviceman.exe %userprofile%\\bin\\serviceman.exe\nreg add HKEY_CURRENT_USER\\Environment /v PATH /d \"%PATH%;%userprofile%\\bin\"\n```\n\n**All Others**\n\n```\nsudo mv ./serviceman /usr/local/bin/\n```\n\n# Examples\n\n```bash\nsudo serviceman add --name \u003cname\u003e \u003cprogram\u003e [options] [--] [raw options]\n\n# Example\nsudo serviceman add --name \"gizmo\" gizmo --foo bar/baz\n```\n\nAnything that looks like file or directory will be **resolved to its absolute path**:\n\n```bash\n# Example of path resolution\ngizmo --foo /User/me/gizmo/bar/baz\n```\n\nUse `--` to prevent this behavior:\n\n```bash\n# Complex Example\nsudo serviceman add --name \"gizmo\" gizmo -c ./config.ini -- --separator .\n```\n\nFor native **Windows** programs that use `/` for flags, you'll need to resolve some paths yourself:\n\n```bash\n# Windows Example\nserviceman add --name \"gizmo\" gizmo.exe .\\input.txt -- /c \\User\\me\\gizmo\\config.ini /q /s .\n```\n\nIn this case `./config.ini` would still be resolved (before `--`), but `.` would not (after `--`)\n\n\u003cdetails\u003e\n\u003csummary\u003eCompiled Programs\u003c/summary\u003e\n\nNormally you might your program somewhat like this:\n\n```bash\ngizmo run --port 8421 --config envs/prod.ini\n```\n\nAdding a service for that program with `serviceman` would look like this:\n\n```bash\nsudo serviceman add --name \"gizmo\" gizmo run --port 8421 --config envs/prod.ini\n```\n\nserviceman will find `gizmo` in your PATH and resolve `envs/prod.ini` to its absolute path.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eUsing with scripts\u003c/summary\u003e\n\n```bash\n./snarfblat.sh --port 8421\n```\n\nAlthough your text script may be executable, you'll need to specify the interpreter\nin order for `serviceman` to configure the service correctly.\n\nThis can be done in two ways:\n\n1. Put a **hashbang** in your script, such as `#!/bin/bash`.\n2. Prepend the **interpreter** explicitly to your command, such as `bash ./dinglehopper.sh`.\n\nFor example, suppose you had a script like this:\n\n`iamok.sh`:\n\n```bash\nwhile true; do\n  sleep 1; echo \"Still Alive, Still Alive!\"\ndone\n```\n\nNormally you would run the script like this:\n\n```bash\n./imok.sh\n```\n\nSo you'd either need to modify the script to include a hashbang:\n\n```bash\n#!/usr/bin/env bash\nwhile true; do\n  sleep 1; echo \"I'm Ok!\"\ndone\n```\n\nOr you'd need to prepend it with `bash` when creating a service for it:\n\n```bash\nsudo serviceman add --name \"imok\" bash ./imok.sh\n```\n\n**Background Information**\n\nAn operating system can't \"run\" text files (even if the executable bit is set).\n\nScripts require an _interpreter_. Often this is denoted at the top of\n\"executable\" scripts with something like one of these:\n\n```\n#!/usr/bin/env ruby\n```\n\n```bash\n#!/usr/bin/python\n```\n\nHowever, sometimes people get fancy and pass arguments to the interpreter,\nlike this:\n\n```bash\n#!/usr/local/bin/node --harmony --inspect\n```\n\nServiceman understands all 3 of those approaches.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eUsing with node.js\u003c/summary\u003e\n\nIf normally you run your node script something like this:\n\n```bash\npushd ~/my-node-project/\nnpm start\n```\n\nThen you would add it as a system service like this:\n\n```bash\nsudo serviceman add npm start\n```\n\nIf normally you run your node script something like this:\n\n```bash\npushd ~/my-node-project/\nnode ./serve.js --foo bar --baz\n```\n\nThen you would add it as a system service like this:\n\n```bash\nsudo serviceman add node ./serve.js --foo bar --baz\n```\n\nIt's important that any paths start with `./` and have the `.js`\nso that serviceman knows to resolve the full path.\n\n```bash\n# Bad Examples\nsudo serviceman add node ./demo # Wouldn't work for 'demo.js' - not a real filename\nsudo serviceman add node demo   # Wouldn't work for './demo/' - doesn't look like a directory\n```\n\nSee **Using with scripts** for more detailed information.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eUsing with python\u003c/summary\u003e\n\nIf normally you run your python script something like this:\n\n```bash\npushd ~/my-python-project/\npython ./serve.py --config ./config.ini\n```\n\nThen you would add it as a system service like this:\n\n```bash\nsudo serviceman add python ./serve.py --config ./config.ini\n```\n\nSee **Using with scripts** for more detailed information.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eUsing with ruby\u003c/summary\u003e\n\nIf normally you run your ruby script something like this:\n\n```bash\npushd ~/my-ruby-project/\nruby ./serve.rb --config ./config.yaml\n```\n\nThen you would add it as a system service like this:\n\n```bash\nsudo serviceman add ruby ./serve.rb --config ./config.yaml\n```\n\nSee **Using with scripts** for more detailed information.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eSetting PATH\u003c/summary\u003e\n\nYou can set the `$PATH` (`%PATH%` on Windows) for your service like this:\n\n```bash\nsudo serviceman add ./myservice --path \"/home/myuser/bin\"\n```\n\nSnapshot your actual path like this:\n\n```bash\nsudo serviceman add ./myservice --path \"$PATH\"\n```\n\nRemember that this takes a snapshot and sets it in the configuration, it's not\na live reference to your path.\n\n\u003c/details\u003e\n\n## Hints\n\n-   If something goes wrong, read the output **completely** - it'll probably be helpful\n-   Run `serviceman` from your **project directory**, just as you would run it normally\n    -   Otherwise specify `--name \u003cservice-name\u003e` and `--workdir \u003cproject directory\u003e`\n-   Use `--` in front of arguments that should not be resolved as paths\n    -   This also holds true if you need `--` as an argument, such as `-- --foo -- --bar`\n\n```\n# Example of a / that isn't a path\n# (it needs to be escaped with --)\nsudo serviceman add dinglehopper config/prod -- --category color/blue\n```\n\n# Logging\n\n### Linux\n\n```bash\nsudo journalctl -xef --unit \u003cNAME\u003e\nsudo journalctl -xef --user-unit \u003cNAME\u003e\n```\n\n### Mac, Windows\n\nWhen you run `serviceman add` it will either give you an error or\nwill print out the location where logs will be found.\n\nBy default it's one of these:\n\n```txt\n~/.local/share/\u003cNAME\u003e/var/log/\u003cNAME\u003e.log\n```\n\n```txt\n/opt/\u003cNAME\u003e/var/log/\u003cNAME\u003e.log\n```\n\nYou set it with one of these:\n\n-   `--logdir \u003cpath\u003e` (cli)\n-   `\"logdir\": \"\u003cpath\u003e\"` (json)\n-   `Logdir: \"\u003cpath\u003e\"` (go)\n\nIf anything about the logging sucks, tell me... unless they're your logs\n(which they probably are), in which case _you_ should fix them.\n\nThat said, my goal is that it shouldn't take an IT genius to interpret\nwhy your app failed to start.\n\n# Debugging\n\n-   `serviceman add --dryrun \u003cnormal options\u003e`\n-   `serviceman run --config \u003cspecial config\u003e`\n\nOne of the most irritating problems with all of these launchers is that they're\nterrible to debug - it's often difficult to find the logs, and nearly impossible\nto interpret them, if they exist at all.\n\nThe config files generate by `serviceman` are simple, template-generated and\ntested, and therefore gauranteed to work - **_if_** your\napplication runs with the parameters given, which is big 'if'.\n\n`serviceman` tries to make sure that all necessary files and folders\nexist and give clear error messages if they don't (be sure to check the logs,\nmentioned above).\n\nThere's also a `run` utility that can be used to test that the parameters\nyou've given are being interpreted correctly (absolute paths and such).\n\n```bash\nserviceman run --config ./conf.json\n```\n\nWhere `conf.json` looks something like\n\n**For Binaries**:\n\n```json\n{\n\t\"title\": \"Demo\",\n\t\"exec\": \"/Users/me/go-demo/demo\",\n\t\"argv\": [\"--foo\", \"bar\", \"--baz\", \"qux\"]\n}\n```\n\n**For Scripts**:\n\nScripts can't be run directly. They require a binary `interpreter` - bash, node, ruby, python, etc.\n\nIf you're running from the folder containing `./demo.js`,\nand `node.exe` is in your PATH, then you can use executable\nnames and relative paths.\n\n```json\n{\n\t\"title\": \"Demo\",\n\t\"interpreter\": \"node.exe\",\n\t\"exec\": \"./bin/demo.js\",\n\t\"argv\": [\"--foo\", \"bar\", \"--baz\", \"qux\"]\n}\n```\n\nThat's equivalent to this:\n\n```json\n{\n\t\"title\": \"Demo\",\n\n\t\"name\": \"demo\",\n\n\t\"exec\": \"node.exe\",\n\t\"argv\": [\"./bin/demo.js\", \"--foo\", \"bar\", \"--baz\", \"qux\"]\n}\n```\n\nMaking `add` and `run` take the exact same arguments is on the TODO list.\nThe fact that they don't is an artifact of `run` being created specifically\nfor Windows.\n\nIf you have gripes about it, tell me. It shouldn't suck. That's the goal anyway.\n\n## Peculiarities of Windows\n\n# Console vs No Console\n\nWindows binaries can be built either for the console or the GUI.\n\nWhen they're built for the console they can hide themselves when they start.\nThey must open up a terminal window.\n\nWhen they're built for the GUI they can't print any output - even if they're started in the terminal.\n\nThis is why there's a **Debug version** for the windows binaries -\nso that you can get your arguments correct with the one and then\nswitch to the other.\n\nThere's probably a clever way to work around this, but I don't know what it is yet.\n\n# No userspace launcher\n\nWindows doesn't have a userspace daemon launcher.\nThis means that if your application crashes, it won't automatically restart.\n\nHowever, `serviceman` handles this by not directly adding your application\nto `HKEY_CURRENT_USER/.../Run`, but rather installing a copy of _itself_\ninstead, which runs your application and automatically restarts it whenever it\nexits.\n\nIf the application fails to start `serviceman` will retry continually,\nbut it does have an exponential backoff of up to 1 minute between failed\nrestart attempts.\n\nSee the bit on `serviceman run` in the **Debugging** section up above for more information.\n\n# Building\n\n```bash\ngit clone https://git.coolaj86.com/coolaj86/go-serviceman.git\n```\n\n```bash\npushd ./go-serviceman\n```\n\n```bash\ngo generate -mod=vendor ./...\n```\n\n**Windows**:\n\n```bash\ngo build -mod=vendor -ldflags \"-H=windowsgui\" -o serviceman.exe\n```\n\n**Linux, MacOS**:\n\n```bash\ngo build -mod=vendor -o /usr/local/bin/serviceman\n```\n\n# More Why\n\nI created this for two reasons:\n\n1. Too often I just run services in `screen -xRS foo` because systemd `.service` files are way too hard to get right and even harder to debug. I make stupid typos or config mistakes and get it wrong. Then I get a notice 18 months later from digital ocean that NYC region 3 is being rebooted and to expect 5 seconds of downtime... and I don't remember if I remembered to go back and set up that service with systemd or not.\n2. To make it easier for people to install [Telebit](https://telebit.io) on Windows.\n\n\u003c!-- {{ if .Legal }} --\u003e\n\n# Legal\n\n[serviceman](https://git.coolaj86.com/coolaj86/go-serviceman) |\nMPL-2.0 |\n[Terms of Use](https://therootcompany.com/legal/#terms) |\n[Privacy Policy](https://therootcompany.com/legal/#privacy)\n\nCopyright 2019 AJ ONeal.\n\n\u003c!-- {{ end }} --\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftherootcompany%2Fserviceman","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftherootcompany%2Fserviceman","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftherootcompany%2Fserviceman/lists"}