如何用Bash脚本自动关闭本地Kafka集群?
本地Kafka集群自动化关闭解决方案
核心问题原因
你记录的PID是启动脚本(如kafka-server-start.sh)的父进程ID,但这类脚本会fork出JVM子进程实际运行Kafka服务。仅杀死父进程不会终止子进程,导致集群无法彻底关闭,这就是你看到多个关联PID的原因。
方法一:使用Kafka官方停止脚本(最可靠)
Kafka自带配套的停止脚本,能自动识别对应配置的进程并终止,无需手动管理PID。
关闭脚本代码
#!/bin/bash KAFKA_SERVER_DIR="./kafka-3.7.0-src" cd "$KAFKA_SERVER_DIR" || exit # 关闭两个Kafka Broker echo "Stopping Kafka brokers..." bin/kafka-server-stop.sh config/server.properties bin/kafka-server-stop.sh config/server1.properties # 关闭Zookeeper echo "Stopping Zookeeper..." bin/zookeeper-server-stop.sh config/zookeeper.properties # 可选:清理集群临时数据目录 rm -rf /tmp/kafka-logs /tmp/kafka-logs1 /tmp/zookeeper /tmp/kraft-combined-logs
方法二:改进启动脚本,记录进程组ID并批量终止
如果需要自定义进程管理,可记录每个服务的进程组ID,通过杀死整个进程组来彻底终止所有关联进程。
改进后的启动脚本
#!/bin/bash KAFKA_SERVER_DIR="./kafka-3.7.0-src" cd "$KAFKA_SERVER_DIR" || exit PID_FILE="kafka_pids.txt" PGID_FILE="kafka_pgids.txt" # 清理旧数据和记录文件 rm -rf /tmp/kafka-logs /tmp/kafka-logs1 /tmp/zookeeper /tmp/kraft-combined-logs rm -f "$PID_FILE" "$PGID_FILE" # 启动Zookeeper并记录进程组ID start_zookeeper() { echo "Starting Kafka Zookeeper..." bin/zookeeper-server-start.sh config/zookeeper.properties } start_zookeeper & ZK_PID=$! ZK_PGID=$(ps -o pgid= -p $ZK_PID | grep -o '[0-9]*') echo "$ZK_PID $ZK_PGID" >> "$PID_FILE" echo "$ZK_PGID" >> "$PGID_FILE" sleep 1 # 启动第一个Broker create_broker() { local config_file="$1" echo "Creating Kafka broker with config $config_file " bin/kafka-server-start.sh "$config_file" } create_broker "config/server.properties" & BROKER1_PID=$! BROKER1_PGID=$(ps -o pgid= -p $BROKER1_PID | grep -o '[0-9]*') echo "$BROKER1_PID $BROKER1_PGID" >> "$PID_FILE" echo "$BROKER1_PGID" >> "$PGID_FILE" sleep 2 # 启动第二个Broker create_broker "config/server1.properties" & BROKER2_PID=$! BROKER2_PGID=$(ps -o pgid= -p $BROKER2_PID | grep -o '[0-9]*') echo "$BROKER2_PID $BROKER2_PGID" >> "$PID_FILE" echo "$BROKER2_PGID" >> "$PGID_FILE" sleep 2 # 创建Topic(该进程执行后自动退出,无需记录) make_topic() { local topic_name="$1" local replication_factor="$2" local num_partitions="$3" bin/kafka-topics.sh --create --topic "$topic_name" --bootstrap-server localhost:9092 --replication-factor $replication_factor --partitions $num_partitions } make_topic "test_topic" 2 3 > make_topic_error.log &
对应的关闭脚本
#!/bin/bash KAFKA_SERVER_DIR="./kafka-3.7.0-src" cd "$KAFKA_SERVER_DIR" || exit PGID_FILE="kafka_pgids.txt" if [ -f "$PGID_FILE" ]; then echo "Stopping Kafka cluster..." # 遍历进程组ID,先发送终止信号,再强制清理残留进程 while read -r PGID; do if [ -n "$PGID" ]; then echo "Killing process group $PGID..." kill -TERM -- -$PGID sleep 1 kill -KILL -- -$PGID 2>/dev/null fi done < "$PGID_FILE" # 清理记录文件和临时数据 rm -f "$PGID_FILE" "$PID_FILE" rm -rf /tmp/kafka-logs /tmp/kafka-logs1 /tmp/zookeeper /tmp/kraft-combined-logs else echo "No running Kafka cluster detected (missing PGID file)." fi
方法三:通过端口查找进程并终止
如果不想修改启动脚本,可根据服务端口直接查找并杀死进程(需确保端口未被其他进程占用):
#!/bin/bash # 关闭Zookeeper(默认端口2181) echo "Stopping Zookeeper..." lsof -i :2181 | grep LISTEN | awk '{print $2}' | xargs kill -TERM sleep 1 lsof -i :2181 | grep LISTEN | awk '{print $2}' | xargs kill -KILL 2>/dev/null # 关闭Kafka Broker(默认端口9092、9093) echo "Stopping Kafka brokers..." lsof -i :9092,:9093 | grep LISTEN | awk '{print $2}' | xargs kill -TERM sleep 1 lsof -i :9092,:9093 | grep LISTEN | awk '{print $2}' | xargs kill -KILL 2>/dev/null # 清理临时数据 rm -rf /tmp/kafka-logs /tmp/kafka-logs1 /tmp/zookeeper /tmp/kraft-combined-logs
内容的提问来源于stack exchange,提问作者SarthakSin
相关产品推荐
相关产品推荐

