KILL TREE
A library and CLI tool that kills all of target process and its children recursively not depending on the other commands such as kill
, ps
, pgrep
, taskkill
or wmic
.
This is written in Rust and powered by Tokio.
This project is inspired by node-tree-kill. Thank you. đ¤
Why Did I Make
This is my first Rust crate and CLI tool. it means that I started because it was a suitable project to development with Rust.
There was no multi-platform library and CLI to allow the process to be terminated 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.
I had an issue in Node.js environment where I create a child process on the Windows platform, I run an application or a batch script through cmd
and the grandchild process would not be terminated.
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.
And when I terminate the application I distributed, I wanted all of the child processes to be terminate.
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 dependence is quite deep. because internally, this invoke 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 load and evaluate the script and call taskkill
from the script to 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.
And the interface was unified because the CLI tool that kill the process varies from platform to platform.
Why use Rust
Rust is a battery included system programming language that does not have a garbage collector and includes package manager, basic package registry and a variety of other utility features.
And it supports asynchronous grammer at the language level so that you don't need a green thread.
I started programming in C language, and I used C++ as my main programming language.
And I also used Go, JavaScript (including Typescript, Node.js).
The C and C++ language do not have a package manager and a basic package registry. (There is, but I didn't see it as mainstream.)
Node.js, the JavaScript runtime, operates on an event basis. but an event loop works in one thread and you have to have multiple event loops to use multiple threads.
The Go programming language is battery included and has a green thread goroutine and a channel for communication between goroutine.
If I didn't know Rust, I might have compromised in Go language. đ
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 asynchronous runtime framework written in Rust. and it's 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 is not uniform throughput between threads and can be heavy on certain threads.
However, Task based parallelism is likely to equalize throughput between threads so that computing resources are not wasted.
Tokio runtime written in Rust allows I 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.
âšī¸ Signals are ignored on Windows platforms.
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.
âšī¸ Also, signals are ignored on Windows platforms.
Using as Rust Library
â ī¸ This library must be called in Tokio runtime.
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.
So, when this query or kill a process, consider it a success even if it fails.
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 |