{"id":15294088,"url":"https://github.com/catern/supervise","last_synced_at":"2025-04-13T13:26:38.901Z","repository":{"id":57472434,"uuid":"85633756","full_name":"catern/supervise","owner":"catern","description":"A minimal unprivileged process supervisor making use of modern Linux features","archived":false,"fork":false,"pushed_at":"2021-10-04T11:02:57.000Z","size":137,"stargazers_count":66,"open_issues_count":2,"forks_count":6,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-04-11T02:54:33.450Z","etag":null,"topics":["linux"],"latest_commit_sha":null,"homepage":null,"language":"Python","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/catern.png","metadata":{"files":{"readme":"README.org","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}},"created_at":"2017-03-20T22:31:34.000Z","updated_at":"2024-12-11T13:51:20.000Z","dependencies_parsed_at":"2022-08-31T07:11:51.839Z","dependency_job_id":null,"html_url":"https://github.com/catern/supervise","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/catern%2Fsupervise","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/catern%2Fsupervise/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/catern%2Fsupervise/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/catern%2Fsupervise/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/catern","download_url":"https://codeload.github.com/catern/supervise/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248719566,"owners_count":21150759,"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":["linux"],"created_at":"2024-09-30T16:57:25.936Z","updated_at":"2025-04-13T13:26:38.874Z","avatar_url":"https://github.com/catern.png","language":"Python","readme":"* Summary\n\nThis provides a superior API for process management and supervision on Linux,\nin the form of a minimal and unprivileged executable \"supervise\".\nsupervise is designed to be used as a wrapper for child processes you execute.\nTherefore supervise is designed to only wake up when there is an event to be handled,\nand it otherwise consumes no CPU time.\n\nThere are three main benefits of using supervise to wrap child processes:\n\n- The ability to get notified of child process exit or status change through a file descriptor interface\n- Automatic termination of your child processes when you exit (by virtue of the fd interface)\n- Guaranteed termination of all the transitive children of a child\n  process; no possibility of orphans lingering on the system\n\nIt is a fully supported design goal for supervise to be usable in a nested way.\nYou can wrap a child process with `supervise` which in turn forks off more child processes and wraps them in `supervise`,\nin arbitrary configurations and depths.\n\n* Behavior\nWhen supervise is exec'd, it expects to have a stdin, stdout, and stderr.\nsupervise further expects to have some number of child processes already started (and it provides no mechanism to start more).\nAnd most importantly, supervise expects to have already had =CHILD_SUBREAPER= turned on through =prctl=.\n\nOnce supervise starts up, supervise has three primary functions:\n** Read from stdin and send the specified signals to child processes\nsupervise reads from stdin,\nparsing the input as =struct supervise_send_signal=.\nThis instructs supervise to send a specific signal to a specific pid.\nsupervise checks if that pid is an immediate child of supervise, and if it is, then supervise sends the signal to that pid.\nOtherwise it does nothing.\n** Write child process status changes to stdout\nsupervise waits for any of its immediate children to change status,\nand writes the child status changes to stdout,\nin the form of =siginfo_t= structures as returned by =waitid=.\n** When stdin closes, SIGKILL all transitive child processes and exit\nWhen stdin closes, supervise exits.\nIf supervise exits for any reason, it first SIGKILLs all its transitive child processes.\n* Invocation and use\nsupervise takes no arguments and reads no environment variables, so those need not be supplied.\n\nWhile supervise is a standalone executable,\nit cannot practically be used from the shell;\nusage requires more fine grained control over file descriptors than the shell provides.\nThus it is primarily useful when used as part of a library in a programming language.\n\nOne interface for such a library could be something like this:\n\n#+BEGIN_SRC\nspawnfd : string list -\u003e file_descriptor\n#+END_SRC\n\nwhich, making use of [[https://github.com/catern/sfork][sfork]], is implemented in Python something like this:\n\n#+BEGIN_SRC python\ndef spawnfd(args: List[str]) -\u003e int:\n    parent_side, supervise_side = socketpair(AF_UNIX, SOCK_CLOEXEC)\n    with sfork.subprocess() as supervise_proc:\n        prctl.set_child_subreaper(True)\n        parent_side.close()\n        with sfork.subprocess() as child_proc:\n            supervise_side.close()\n            child_proc.exec(args[0], args)\n        supervise_side.dup2(0)\n        supervise_side.dup2(1)\n        supervise_proc.exec(supervise_utility_location, [])\n    supervise_side.close()\n    return parent_side\n#+END_SRC\n\nAn implementation with traditional =fork= is also possible.\n\n* libsupervise\n\nTo get the definition of =struct supervise_send_signal=,\nso you can send it to supervise's stdin to signal its children,\nyou can link against libsupervise and include =supervise.h=.\n\n* References and inspiration\n\nSee [[http://catern.com/posts/fork.html][my blog post]] about the Unix process API for more.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcatern%2Fsupervise","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcatern%2Fsupervise","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcatern%2Fsupervise/lists"}