Kill Tree
đŗ Kill Tree is a library and CLI tool designed to terminate a specified process and all its child processes recursively, operating independently of other commands like kill or taskkill.
It is written in Rust and powered by Tokio.
This project was inspired by node-tree-kill. Thank you. đ¤
Why Did I Make
This is my first Rust crate and CLI tool. it means I started it because it was a suitable project for development with Rust.
No multi-platform library or CLI existed that could terminate processes recursively.
In the past, various types of CLI tools had to be invoked to implement features in the Node.js project.
It was a project that should be able to run shell scripts for general purposely like CI/CD tools.
In the Node.js environment on Windows, I encountered an issue where creating a child process and running an application or batch script via cmd would not terminate the grandchild process.
The reason is that the Windows platform does not have Signal.
I had to call taskkill to cancel or force kill nested shell scripts that user ran on Windows platforms.
When terminating the distributed application, I wanted all child processes to be terminated.
So, I solved it using a library called tree-kill in Npm.js. functionally, I was satisfied.
However, if I need this feature for similar reasons next time, I will need to install Node.js and I fetch tree-kill library and run it.
This creates a deep dependency because it internally invokes CLI tools such as taskkill.
In summary, Node.js runtime (including npm package manager), tree-kill package and taskkill CLI tool are required.
If I run this with an npx or wrapped Node.js script, it takes quite a while.
because it loads and evaluates the script, then calls taskkill from the script to terminate the child process.
And it is often necessary to terminate the process in a terminal environment, with different commands for each platform.
For example, kill -9 777
or taskkill /T /F /PID 777
.
So I made it possible to recursively kill the processes directly from the code if it was a Rust project.
I also unified the interface, as the CLI tool to kill processes varies across platforms.
Why use Rust
Rust is a 'battery-included' system programming language without a garbage collector, featuring a package manager, basic package registry, and various utility features.
It also supports an asynchronous programming model at the language level, eliminating the need for green threads.
Having started my programming journey with C and primarily using C++, I've also explored Go and JavaScript (including TypeScript and Node.js).
Unlike C and C++, which lack a mainstream package manager and registry, and Node.js, which relies on a single-threaded event loop, Rust offers a comprehensive ecosystem.
Go's 'battery-included' approach with goroutines and channels for concurrency was appealing, but Rust's capabilities convinced me otherwise.
(If I didn't know Rust, I might have compromised in Go. đ)
This is why I use Rust, and it hasn't been long since I used it, so I think I'll try more.
Why use Tokio
I like Task based parallelism.
Tokio is an asynchronous runtime framework written in Rust, and it is one of the most widely used.
In the current environment where Standard async runtime is not yet available, I think using Tokio is a pretty reasonable option.
Tokio's robust and many features help me focus on my business logic.
When I first learned programming, I learned Role based parallelism, and I use this.
For example, UI thread (main thread), http request thread, loading thread, etc.
This approach does not guarantee uniform throughput across threads, potentially overburdening certain threads.
However, Task based parallelism is likely to equalize throughput between threads so that computing resources are not wasted.
The Tokio runtime, written in Rust, allows me to work on Zero cost task based parallelism without having to pay attention to detail implementation.
How to Use
Using as CLI Tool
Below is an example of sending SIGTERM
signals to a process with process ID 777
, and to all child processes.
âšī¸ On Windows platforms, all signals including SIGTERM and SIGKILL are ignored.
If you want to send another signal, you can enter that signal as the second parameter.
Below is an example of sending a SIGKILL
signal to a process with process ID 777
and to all child processes.
Using as Rust Library
â ī¸ Ensure this library is executed within a Tokio runtime environment.
Add kill_tree
to your dependencies.
# Cargo.toml
[]
= "0.1"
Kill process and its children recursively with default signal SIGTERM
.
Returns a list of process information when a function is called.
Process information is Killed
or MaybeAlreadyTerminated
.
If process information is Killed
type, it has process_id
, parent_process_id
and name
.
Or MaybeAlreadyTerminated
type, it has process_id
, reason
.
There are two types because they can be killed during the process of querying and killing processes.
Therefore, consider the operation successful even if the query or kill process appears to fail.
This is because the purpose of this library is to make the process not exist
state.
use kill_tree;
async
kill process and its children recursively with signal SIGKILL
.
use kill_tree_with_signal;
async
Support Platform and Architecture
Platform | Architecture | Support |
---|---|---|
Windows | x86_64 | â |
Windows | aarch64 | Not tested |
Linux | x86_64 | â |
Linux | aarch64 | Not tested |
Macos | x86_64 | â |
Macos | aarch64 | â |
This CLI and library depend on an operating system's system library.
Because it's the operating system that owns the processes.
Platform | Dependencies |
---|---|
Windows | kernel32.dll |
oleaut32.dll | |
ntdll.dll | |
advapi32.dll | |
bcrypt.dll | |
Linux | - |
Macos | libiconv.dylib |
libSystem.dylib |