kill_port 0.1.1

A utility to find and terminate processes by port. 一个通过端口查找并终止进程的工具。
Documentation

kill_port

English | 中文

English

Introduction

kill_port is a utility library for developers. It provides a function to find and terminate processes listening on a specified network port. This is particularly useful in development environments where a port might be unexpectedly occupied, preventing an application from starting.

Usage

Add kill_port as a dependency in your Cargo.toml, then call the function as shown below.

The following example demonstrates how to terminate a process listening on port 8080.

use std::{
  process::{Command, Stdio},
  thread,
  time::Duration,
};

fn test_kill_port() {
  let port = 8080;

  // Start a dummy process that listens on the specified port
  let mut child = Command::new("python")
    .arg("-c")
    .arg(format!(
      "import socket; s = socket.socket(); s.bind(('127.0.0.1', {})); s.listen(1); input()",
      port
    ))
    .stdin(Stdio::piped())
    .spawn()
    .expect("Failed to start dummy process");

  // Give it a moment to start up and bind to the port
  thread::sleep(Duration::from_millis(500));

  // Use the kill_port function to terminate the process
  kill_port::kill_port(port);

  // Wait for the process to terminate
  let status = child.wait().expect("Failed to wait for dummy process");

  // Assert that the process was terminated
  assert!(status.success() == false);
}

Design Philosophy

The library's design is direct and minimalist, adhering to the principle of doing one thing well.

The process flow is as follows:

  1. The kill_port function accepts a port number (u16).
  2. It retrieves its own process ID to prevent self-termination.
  3. It uses the listeners::get_processes_by_port function to identify all processes currently listening on the specified port.
  4. It iterates through the list of found processes.
  5. For each process that is not the program itself, it uses nix::sys::signal::kill to send a SIGTERM signal, requesting a graceful shutdown.

This approach ensures that only the target processes are terminated, leaving the calling process unaffected.

Technology Stack

  • Language: Rust
  • Core Crates:
    • listeners: For discovering processes associated with a specific network port.
    • nix: Provides safe, low-level bindings to POSIX APIs, used here for sending termination signals to processes.

File Structure

The project is organized with a standard Rust library structure.

.
├── Cargo.toml      # Package manifest and dependencies
├── README.mdt      # Project documentation template
├── src
│   └── lib.rs      # Core library code
└── tests
    └── main.rs     # Integration tests

A Little Story: The kill Command

The kill command, a staple for developers and system administrators, was introduced in one of the earliest versions of the Unix operating system. Its name is somewhat misleading; the command does not inherently "kill" processes. Instead, it sends signals.

A signal is a form of inter-process communication. When kill is invoked (e.g., kill <PID>), it sends the default SIGTERM (terminate) signal. This is a polite request asking the process to shut down gracefully, allowing it to save its state and release resources. If a process is stubborn, one might resort to kill -9 <PID>, which sends the SIGKILL signal. SIGKILL cannot be ignored by the process, forcing an immediate and often unclean termination. This distinction between "asking" and "forcing" has been a fundamental concept in process management for decades.


中文

项目简介

kill_port 是一个面向开发者的工具库。它提供了一个函数,用于查找并终止监听指定网络端口的进程。在开发环境中,端口时常被意外占用,导致应用程序无法启动,此工具可用于解决该问题。

项目使用

Cargo.toml 中添加 kill_port 作为依赖,然后如下所示调用函数。

以下示例演示了如何终止监听 8080 端口的进程。

use std::{
  process::{Command, Stdio},
  thread,
  time::Duration,
};

fn test_kill_port() {
  let port = 8080;

  // 启动一个监听指定端口的虚拟进程
  let mut child = Command::new("python")
    .arg("-c")
    .arg(format!(
      "import socket; s = socket.socket(); s.bind(('127.0.0.1', {})); s.listen(1); input()",
      port
    ))
    .stdin(Stdio::piped())
    .spawn()
    .expect("未能启动虚拟进程");

  // 等待片刻,确保进程已启动并绑定到端口
  thread::sleep(Duration::from_millis(500));

  // 使用 kill_port 函数终止该进程
  kill_port::kill_port(port);

  // 等待进程终止
  let status = child.wait().expect("未能等待虚拟进程");

  // 断言该进程已被终止
  assert!(status.success() == false);
}

设计思路

该库的设计直接且简约,遵循“做好一件事”的原则。

其调用流程如下:

  1. kill_port 函数接收一个端口号 (u16) 作为参数。
  2. 获取当前进程ID,以避免自我终止。
  3. 使用 listeners::get_processes_by_port 函数识别所有正在监听指定端口的进程。
  4. 遍历找到的进程列表。
  5. 对于每个非自身的进程,使用 nix::sys::signal::kill 发送 SIGTERM 信号,请求其优雅关闭。

这种方法确保只终止目标进程,而不影响调用进程本身。

技术堆栈

  • 语言: Rust
  • 核心依赖包:
    • listeners: 用于发现与特定网络端口关联的进程。
    • nix: 提供对 POSIX API 的安全、底层绑定,此处用于向进程发送终止信号。

文件结构

项目采用标准的 Rust 库结构进行组织。

.
├── Cargo.toml      # 包清单与依赖项
├── README.mdt      # 项目文档模板
├── src
│   └── lib.rs      # 核心库代码
└── tests
    └── main.rs     # 集成测试

相关故事:kill 命令

kill 命令是开发者和系统管理员的必备工具,它诞生于最早期的 Unix 操作系统版本之一。它的名字有些误导性;该命令本身并不直接“杀死”进程,而是发送信号。

信号是一种进程间通信的形式。当调用 kill (例如 kill <PID>) 时,它会发送默认的 SIGTERM (终止) 信号。这是一个礼貌的请求,要求进程优雅地关闭,允许其保存状态并释放资源。如果一个进程“顽固不化”,人们可能会使用 kill -9 <PID>,它会发送 SIGKILL 信号。SIGKILL 信号无法被进程忽略,会强制其立即、且通常是不干净地终止。几十年来,这种“请求”与“强制”之间的区别一直是进程管理中的一个基本概念。

About

This project is an open-source component of i18n.site ⋅ Internationalization Solution.

关于

本项目为 i18n.site ⋅ 国际化解决方案 的开源组件。