ppp-off 是一个用于断开PPP(点对点协议)拨号连接的Shell脚本,通常与ppp-on配对使用。它通过发送终止信号给pppd进程来关闭拨号连接,释放网络接口,并清理相关资源。虽然现代Linux系统通常使用网络管理工具或poff命令,但在一些遗留系统或脚本中仍可能遇到。
ppp-off 是较老的PPP连接管理脚本,现代Linux系统中更多使用poff、ifdown或NetworkManager等工具。但在一些嵌入式系统或自定义拨号脚本中仍在使用。
# 基本格式
ppp-off [选项] [连接名称]
# 常用格式
ppp-off # 断开默认连接
ppp-off dsl-provider # 断开指定连接
ppp-off -a # 断开所有连接
sudo ppp-off # 需要root权限
注意:在某些系统中,ppp-off可能是一个脚本文件,位于/usr/sbin/、/etc/ppp/或/etc/ppp/scripts/目录下。
| 特性 | ppp-off |
poff |
|---|---|---|
| 实现方式 | Shell脚本 | pppd工具的一部分 |
| 功能完整性 | 基本功能,断开连接 | 完整功能,管理连接 |
| 配置依赖 | 需要单独的脚本文件 | 使用pppd配置文件 |
| 连接名称支持 | 有限支持 | 完整支持(通过peers) |
| 错误处理 | 简单 | 详细错误信息 |
| 日志记录 | 有限 | 完整日志支持 |
| 系统集成 | 独立脚本 | 与pppd深度集成 |
| 现代使用 | 遗留系统,简单脚本 | 推荐用于pppd连接 |
| 灵活性 | 可自定义修改 | 标准化,功能固定 |
| 发行版支持 | 部分发行版预装 | 所有支持ppp的发行版 |
在一些系统中,ppp-off可能需要手动安装或创建:
# 1. 检查是否已安装
which ppp-off
# 或
ls -la /usr/sbin/ppp-off /etc/ppp/ppp-off
# 2. 安装ppp包(包含ppp-off脚本)
# Debian/Ubuntu
sudo apt-get update
sudo apt-get install ppp
# RHEL/CentOS
sudo yum install ppp
# 或
sudo dnf install ppp
# 安装后,ppp-off通常位于:
# /usr/sbin/ppp-off
# 或
# /etc/ppp/ppp-off
# 3. 手动创建ppp-off脚本
# 如果系统没有提供,可以手动创建
sudo nano /usr/local/bin/ppp-off
# 内容如下:
#!/bin/bash
# ppp-off脚本
# 断开PPP连接
# 默认设置
CONFIG_FILE="/etc/ppp/ppp-off.conf"
LOG_FILE="/var/log/ppp-off.log"
PID_FILE="/var/run/ppp0.pid"
INTERFACE="ppp0"
VERBOSE=0
FORCE=0
# 加载配置文件
[ -f "$CONFIG_FILE" ] && source "$CONFIG_FILE"
# 解析参数
while [ $# -gt 0 ]; do
case $1 in
-a|--all)
DISCONNECT_ALL=1
shift
;;
-h|--help)
echo "用法: ppp-off [选项]"
echo "选项:"
echo " -a, --all 断开所有PPP连接"
echo " -h, --help 显示此帮助"
echo " -v, --verbose 详细模式"
echo " -q, --quiet 安静模式"
echo " -f, --force 强制断开"
echo " -c CONN 指定连接名称"
echo " -i IFACE 指定接口(如ppp0)"
echo " -p PIDFILE 指定PID文件"
exit 0
;;
-v|--verbose)
VERBOSE=1
shift
;;
-q|--quiet)
VERBOSE=0
shift
;;
-f|--force)
FORCE=1
shift
;;
-c)
shift
CONNECTION=$1
shift
;;
-i)
shift
INTERFACE=$1
shift
;;
-p)
shift
PID_FILE=$1
shift
;;
*)
# 非选项参数作为连接名
CONNECTION=$1
shift
;;
esac
done
# 日志函数
log_message() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE"
[ $VERBOSE -eq 1 ] && echo "$1"
}
# 检查是否以root运行
if [ "$(id -u)" != "0" ]; then
echo "错误: 需要root权限运行ppp-off"
exit 1
fi
# 断开连接函数
disconnect_ppp() {
local iface=$1
local pid_file=$2
log_message "断开PPP连接: 接口 $iface"
# 检查接口是否存在
if ! ip link show "$iface" >/dev/null 2>&1; then
log_message "接口 $iface 不存在,可能已断开"
return 0
fi
# 获取PID
local pid=""
if [ -f "$pid_file" ]; then
pid=$(cat "$pid_file")
else
# 尝试从进程列表获取
pid=$(ps aux | grep "pppd.*$iface" | grep -v grep | awk '{print $2}' | head -1)
fi
# 发送终止信号
if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
log_message "发送TERM信号到pppd进程 $pid"
kill -TERM "$pid"
# 等待进程结束
local timeout=10
local count=0
while kill -0 "$pid" 2>/dev/null && [ $count -lt $timeout ]; do
sleep 1
count=$((count + 1))
done
# 如果进程仍在运行,强制杀死
if kill -0 "$pid" 2>/dev/null; then
if [ $FORCE -eq 1 ]; then
log_message "强制杀死pppd进程 $pid"
kill -KILL "$pid"
else
log_message "警告: pppd进程 $pid 仍在运行"
fi
else
log_message "pppd进程 $pid 已终止"
fi
else
log_message "未找到运行的pppd进程"
fi
# 清理PID文件
[ -f "$pid_file" ] && rm -f "$pid_file"
# 删除路由
log_message "清理路由表..."
ip route del default dev "$iface" 2>/dev/null
# 关闭接口
log_message "关闭接口 $iface"
ip link set "$iface" down
# 删除接口
ip link delete "$iface" 2>/dev/null
log_message "PPP连接 $iface 已断开"
return 0
}
# 主程序
main() {
log_message "=== 开始断开PPP连接 ==="
if [ "$DISCONNECT_ALL" = "1" ]; then
# 断开所有PPP接口
for iface in $(ip link show | grep "ppp" | awk -F: '{print $2}' | tr -d ' '); do
disconnect_ppp "$iface" "/var/run/${iface}.pid"
done
elif [ -n "$CONNECTION" ]; then
# 断开指定连接
disconnect_ppp "$INTERFACE" "/var/run/$CONNECTION.pid"
else
# 断开默认连接
disconnect_ppp "$INTERFACE" "$PID_FILE"
fi
log_message "=== 断开完成 ==="
}
# 执行主程序
main "$@"
# 设置权限
sudo chmod +x /usr/local/bin/ppp-off
# 4. 创建配置文件(可选)
sudo nano /etc/ppp/ppp-off.conf
# 内容:
# INTERFACE="ppp0"
# PID_FILE="/var/run/ppp0.pid"
# LOG_FILE="/var/log/ppp-off.log"
# VERBOSE=1
# 5. 测试ppp-off
sudo ppp-off --help
# 应该显示帮助信息
# 6. 创建ppp-on配对脚本
# 通常ppp-off与ppp-on配对使用
sudo cp /usr/local/bin/ppp-off /usr/local/bin/ppp-on
# 然后修改ppp-on为连接脚本
断开PPP连接的基本操作:
# 1. 首先检查当前PPP连接状态
ifconfig ppp0
# 或
ip addr show ppp0
# 输出示例:
# ppp0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 1492
# inet 192.168.1.100 netmask 255.255.255.255 destination 192.168.1.1
# ppp txqueuelen 3 (Point-to-Point Protocol)
# 查看路由表
route -n
# 或
ip route show
# 应该看到默认路由通过ppp0
# 2. 使用ppp-off断开连接
sudo ppp-off
# 输出示例:
# 断开PPP连接: 接口 ppp0
# 发送TERM信号到pppd进程 1234
# pppd进程 1234 已终止
# 清理路由表...
# 关闭接口 ppp0
# PPP连接 ppp0 已断开
# 3. 验证连接已断开
ifconfig ppp0
# 应该显示: ppp0: error fetching interface information: Device not found
# 或没有输出
ip link show ppp0
# 接口应该不存在
# 4. 检查路由表
route -n
# 默认路由应该不再通过ppp0
# 5. 查看ppp-off日志
tail -f /var/log/ppp-off.log
# 输出断开连接的详细日志
# 6. 检查pppd进程
ps aux | grep pppd
# 应该没有pppd进程运行
# 7. 查看系统日志
tail -f /var/log/syslog | grep ppp
# 或
journalctl -f | grep ppp
# 8. 清理残留文件
# 检查PID文件
ls -la /var/run/*.pid
# 如果仍有ppp相关PID文件,可以删除
sudo rm -f /var/run/ppp*.pid
使用不同选项断开PPP连接:
# 1. 断开所有PPP连接
sudo ppp-off -a
# 或
sudo ppp-off --all
# 这会断开ppp0, ppp1, ppp2等所有PPP接口
# 2. 指定接口断开
sudo ppp-off -i ppp1
# 只断开ppp1接口
# 3. 指定连接名称断开
sudo ppp-off -c dsl-provider
# 断开名为"dsl-provider"的连接
# 会使用/var/run/dsl-provider.pid作为PID文件
# 4. 强制断开
sudo ppp-off -f
# 或
sudo ppp-off --force
# 不等待正常终止,直接发送KILL信号
# 5. 详细模式
sudo ppp-off -v
# 或
sudo ppp-off --verbose
# 显示详细执行过程
# 6. 安静模式
sudo ppp-off -q
# 或
sudo ppp-off --quiet
# 不显示任何输出,只记录到日志
# 7. 调试模式
sudo ppp-off -d
# 显示调试信息,包括执行的每个步骤
# 8. 指定PID文件
sudo ppp-off -p /tmp/myppp.pid
# 使用指定的PID文件
# 9. 设置超时
# 修改ppp-off脚本,添加超时选项
# 或使用timeout命令
timeout 10 sudo ppp-off
# 10秒后强制终止
# 10. 组合选项
sudo ppp-off -v -f -i ppp0
# 详细模式 + 强制断开 + 指定接口
# 11. 在脚本中使用
#!/bin/bash
# 自动断开重连脚本
MAX_RETRIES=3
RETRY_DELAY=5
for i in $(seq 1 $MAX_RETRIES); do
echo "尝试断开连接 (尝试 $i/$MAX_RETRIES)"
if sudo ppp-off -q; then
echo "连接已成功断开"
break
else
echo "断开失败,等待 ${RETRY_DELAY}秒后重试..."
sleep $RETRY_DELAY
fi
done
if [ $i -eq $MAX_RETRIES ]; then
echo "错误: 无法断开PPP连接"
exit 1
fi
# 12. 通过信号直接断开
# 找到pppd进程ID
PPPD_PID=$(ps aux | grep pppd | grep -v grep | awk '{print $2}')
# 发送断开信号
sudo kill -TERM $PPPD_PID
# 等待断开
sleep 2
# 如果仍在运行,强制杀死
sudo kill -KILL $PPPD_PID 2>/dev/null
创建完整的ppp-on和ppp-off脚本对:
#!/bin/bash
# 文件名: ppp-on
# 完整的PPP连接脚本
CONFIG_FILE="/etc/ppp/ppp-on.conf"
LOG_FILE="/var/log/ppp-on.log"
PID_FILE="/var/run/ppp0.pid"
VERBOSE=1
# 加载配置
[ -f "$CONFIG_FILE" ] && source "$CONFIG_FILE"
# 日志函数
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE"
[ $VERBOSE -eq 1 ] && echo "$1"
}
# 检查root权限
check_root() {
if [ "$(id -u)" != "0" ]; then
echo "错误: 需要root权限"
exit 1
fi
}
# 检查调制解调器
check_modem() {
if [ ! -c "$DEVICE" ]; then
log "错误: 调制解调器设备 $DEVICE 不存在"
return 1
fi
# 检查设备权限
if [ ! -r "$DEVICE" ] || [ ! -w "$DEVICE" ]; then
log "错误: 对 $DEVICE 没有读写权限"
return 1
fi
return 0
}
# 建立连接
establish_connection() {
log "开始建立PPP连接"
# 清理可能存在的旧连接
if [ -f "$PID_FILE" ]; then
OLD_PID=$(cat "$PID_FILE")
if kill -0 "$OLD_PID" 2>/dev/null; then
log "发现旧的pppd进程 $OLD_PID,正在终止..."
kill -TERM "$OLD_PID"
sleep 2
fi
rm -f "$PID_FILE"
fi
# 启动pppd
log "启动pppd: 设备=$DEVICE, 速率=$SPEED"
pppd "$DEVICE" "$SPEED" \
noauth \
defaultroute \
usepeerdns \
persist \
holdoff 10 \
maxfail 0 \
debug \
nodetach \
"$@" \
> /tmp/pppd.log 2>&1 &
PPPD_PID=$!
echo $PPPD_PID > "$PID_FILE"
log "pppd已启动,PID: $PPPD_PID"
# 等待连接建立
log "等待连接建立..."
local timeout=30
local connected=0
for i in $(seq 1 $timeout); do
if grep -q "local IP address" /tmp/pppd.log 2>/dev/null; then
connected=1
break
fi
sleep 1
done
if [ $connected -eq 1 ]; then
# 获取分配的IP
LOCAL_IP=$(grep "local IP address" /tmp/pppd.log | awk '{print $NF}')
REMOTE_IP=$(grep "remote IP address" /tmp/pppd.log | awk '{print $NF}')
log "连接建立成功"
log "本地IP: $LOCAL_IP"
log "远程IP: $REMOTE_IP"
log "接口: ppp0"
# 显示连接信息
ifconfig ppp0
route -n | grep ppp0
return 0
else
log "错误: 连接超时"
kill -TERM $PPPD_PID 2>/dev/null
rm -f "$PID_FILE"
return 1
fi
}
# 主程序
main() {
check_root
log "=== 开始PPP连接 ==="
# 检查必要参数
if [ -z "$DEVICE" ]; then
DEVICE="/dev/ttyS0"
fi
if [ -z "$SPEED" ]; then
SPEED="115200"
fi
if ! check_modem; then
exit 1
fi
# 建立连接
if establish_connection "$@"; then
log "=== 连接成功 ==="
exit 0
else
log "=== 连接失败 ==="
exit 1
fi
}
# 执行
main "$@"
#!/bin/bash
# 文件名: ppp-off
# 完整的PPP断开脚本
CONFIG_FILE="/etc/ppp/ppp-off.conf"
LOG_FILE="/var/log/ppp-off.log"
PID_FILE="/var/run/ppp0.pid"
INTERFACE="ppp0"
VERBOSE=1
FORCE=0
# 加载配置
[ -f "$CONFIG_FILE" ] && source "$CONFIG_FILE"
# 日志函数
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE"
[ $VERBOSE -eq 1 ] && echo "$1"
}
# 检查root权限
check_root() {
if [ "$(id -u)" != "0" ]; then
echo "错误: 需要root权限"
exit 1
fi
}
# 断开连接
disconnect() {
local iface=$1
local pid_file=$2
log "断开PPP连接: 接口 $iface"
# 检查接口
if ! ip link show "$iface" >/dev/null 2>&1; then
log "接口 $iface 不存在"
return 0
fi
# 获取IP信息(记录用)
local ip_info=$(ip addr show "$iface" 2>/dev/null | grep "inet " || echo "无IP地址")
log "接口信息: $ip_info"
# 获取PID
local pid=""
if [ -f "$pid_file" ] && [ -s "$pid_file" ]; then
pid=$(cat "$pid_file")
if ! kill -0 "$pid" 2>/dev/null; then
log "PID文件存在但进程 $pid 未运行"
pid=""
fi
fi
if [ -z "$pid" ]; then
# 从进程列表查找
pid=$(ps aux | grep "pppd.*$iface" | grep -v grep | awk '{print $2}' | head -1)
fi
# 终止进程
if [ -n "$pid" ]; then
log "找到pppd进程: $pid"
if [ $FORCE -eq 1 ]; then
log "强制终止进程 $pid"
kill -KILL "$pid" 2>/dev/null
else
log "发送终止信号到进程 $pid"
kill -TERM "$pid" 2>/dev/null
# 等待终止
local timeout=10
for i in $(seq 1 $timeout); do
if ! kill -0 "$pid" 2>/dev/null; then
log "进程 $pid 已终止"
break
fi
sleep 1
done
# 检查是否仍在运行
if kill -0 "$pid" 2>/dev/null; then
log "进程仍在运行,强制终止"
kill -KILL "$pid" 2>/dev/null
fi
fi
else
log "未找到pppd进程"
fi
# 清理PID文件
[ -f "$pid_file" ] && rm -f "$pid_file"
# 清理路由
log "清理路由表..."
ip route del default dev "$iface" 2>/dev/null
# 关闭并删除接口
log "关闭接口 $iface"
ip link set "$iface" down 2>/dev/null
ip link delete "$iface" 2>/dev/null
# 清理DNS
log "恢复DNS设置..."
# 这里可以添加恢复原DNS服务器的代码
log "PPP连接 $iface 已断开"
return 0
}
# 断开所有连接
disconnect_all() {
log "断开所有PPP连接"
# 查找所有PPP接口
local interfaces=$(ip link show | grep -o "ppp[0-9]\+" | sort -u)
if [ -z "$interfaces" ]; then
log "没有找到PPP接口"
return 0
fi
for iface in $interfaces; do
disconnect "$iface" "/var/run/${iface}.pid"
done
# 清理残留进程
local pppd_pids=$(ps aux | grep pppd | grep -v grep | awk '{print $2}')
if [ -n "$pppd_pids" ]; then
log "清理残留pppd进程"
kill -TERM $pppd_pids 2>/dev/null
sleep 1
kill -KILL $pppd_pids 2>/dev/null
fi
# 清理所有PID文件
rm -f /var/run/ppp*.pid
log "所有PPP连接已断开"
}
# 主程序
main() {
check_root
log "=== 开始断开PPP连接 ==="
# 解析参数
while [ $# -gt 0 ]; do
case $1 in
-a|--all)
disconnect_all
exit 0
;;
-f|--force)
FORCE=1
shift
;;
-q|--quiet)
VERBOSE=0
shift
;;
-v|--verbose)
VERBOSE=1
shift
;;
-i)
shift
INTERFACE=$1
shift
;;
-p)
shift
PID_FILE=$1
shift
;;
*)
# 连接名
INTERFACE="ppp0"
PID_FILE="/var/run/$1.pid"
shift
;;
esac
done
# 执行断开
disconnect "$INTERFACE" "$PID_FILE"
log "=== 断开完成 ==="
}
# 执行
main "$@"
# 创建配置文件
sudo nano /etc/ppp/ppp-on.conf
# 内容:
DEVICE="/dev/ttyS0"
SPEED="115200"
TELEPHONE="1234567"
USERNAME="myuser"
PASSWORD="mypass"
# 可选:调制解调器初始化字符串
MODEM_INIT="ATZ"
# 可选:调试级别
DEBUG=1
# 设置权限
sudo chmod +x /usr/local/bin/ppp-on
sudo chmod +x /usr/local/bin/ppp-off
# 创建日志目录
sudo mkdir -p /var/log/ppp
sudo touch /var/log/ppp-on.log /var/log/ppp-off.log
sudo chmod 644 /var/log/ppp/*.log
# 测试连接
sudo ppp-on
# 等待连接建立...
# 测试断开
sudo ppp-off
# 创建systemd服务(可选)
sudo nano /etc/systemd/system/ppp-connection.service
# 内容:
[Unit]
Description=PPP Dial-up Connection
After=network.target
[Service]
Type=forking
ExecStart=/usr/local/bin/ppp-on
ExecStop=/usr/local/bin/ppp-off
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
# 启用服务
sudo systemctl daemon-reload
sudo systemctl enable ppp-connection
sudo systemctl start ppp-connection
sudo systemctl status ppp-connection
ppp-off故障排查和连接恢复:
# 1. ppp-off无法断开连接
# 检查是否有多个pppd进程
ps aux | grep pppd
# 如果有多个,全部终止
sudo killall pppd
# 或
sudo pkill -9 pppd
# 2. 接口仍存在
# 检查接口
ip link show ppp0
# 如果存在,手动删除
sudo ip link delete ppp0
# 如果提示"Operation not permitted",可能是接口忙
# 先关闭
sudo ip link set ppp0 down
sudo ip link delete ppp0
# 3. 路由未清理
# 检查路由
route -n
# 或
ip route show
# 删除残留路由
sudo ip route del default dev ppp0
sudo ip route del 192.168.1.0/24 dev ppp0 # 示例
# 4. PID文件残留
# 检查PID文件
ls -la /var/run/*.pid
# 删除所有ppp相关PID文件
sudo rm -f /var/run/ppp*.pid
sudo rm -f /var/run/pppd*.pid
# 5. 调制解调器未重置
# 重置串行端口
sudo stty -F /dev/ttyS0 sane
# 发送调制解调器复位命令
echo "ATZ" | sudo tee /dev/ttyS0
# 等待响应
sleep 2
# 6. 系统日志检查
# 查看相关日志
sudo tail -f /var/log/syslog | grep -E "ppp|pppd|ppp-off"
sudo dmesg | grep ppp
sudo journalctl -f | grep ppp
# 7. 网络命名空间问题
# 检查是否在特定网络命名空间中
ip netns list
# 如果在命名空间中,需要在其中执行
sudo ip netns exec NAMESPACE ppp-off
# 8. 权限问题
# 检查sudo配置
sudo -l
# 检查脚本权限
ls -la /usr/local/bin/ppp-off
# 应为root可执行
sudo chown root:root /usr/local/bin/ppp-off
sudo chmod 4755 /usr/local/bin/ppp-off
# 9. 脚本语法错误
# 检查脚本语法
bash -n /usr/local/bin/ppp-off
# 调试执行
bash -x /usr/local/bin/ppp-off
# 10. 配置文件问题
# 检查配置文件语法
source /etc/ppp/ppp-off.conf
# 或
. /etc/ppp/ppp-off.conf
# 不应有错误
# 11. 资源冲突
# 检查端口占用
sudo lsof /dev/ttyS0
# 如果有其他进程使用,终止
sudo kill -9 $(sudo lsof -t /dev/ttyS0)
# 12. 恢复网络设置
# 断开后恢复原有网络配置
# 如果有网络管理器,重新启动
sudo systemctl restart NetworkManager
# 或
sudo systemctl restart network
# 13. 自动恢复脚本
#!/bin/bash
# 自动恢复网络连接
MAX_ATTEMPTS=3
LOG_FILE="/var/log/network-recovery.log"
log() {
echo "$(date) - $1" >> $LOG_FILE
}
recover_network() {
log "开始恢复网络连接"
# 1. 断开所有PPP连接
if which ppp-off >/dev/null 2>&1; then
sudo ppp-off -a
else
sudo poff -a
fi
# 2. 清理残留
sudo pkill -9 pppd
sudo ip link delete ppp0 2>/dev/null
sudo ip link delete ppp1 2>/dev/null
# 3. 重启网络服务
if systemctl is-active NetworkManager >/dev/null 2>&1; then
sudo systemctl restart NetworkManager
elif systemctl is-active network >/dev/null 2>&1; then
sudo systemctl restart network
fi
# 4. 等待恢复
sleep 5
# 5. 测试连接
if ping -c 2 -W 2 8.8.8.8 >/dev/null 2>&1; then
log "网络恢复成功"
return 0
else
log "网络恢复失败"
return 1
fi
}
# 主程序
for i in $(seq 1 $MAX_ATTEMPTS); do
log "恢复尝试 $i/$MAX_ATTEMPTS"
if recover_network; then
log "恢复成功"
exit 0
fi
sleep 10
done
log "无法恢复网络连接"
exit 1
使用现代工具断开PPP连接:
# 1. 使用poff (pppd工具的一部分)
# 断开默认连接
sudo poff
# 断开指定连接
sudo poff dsl-provider
# 断开所有连接
sudo poff -a
# 强制断开
sudo poff -c
# 显示帮助
poff --help
# 2. 使用ifdown
# 断开PPP接口
sudo ifdown ppp0
# 通过接口配置
sudo ifdown ppp0
# 如果配置了/etc/network/interfaces
# auto ppp0
# iface ppp0 inet ppp
# provider dsl-provider
# 3. 使用NetworkManager
# 命令行
nmcli connection down ppp0
# 或
nmcli connection down id "My PPP Connection"
# 查看连接
nmcli connection show
# 断开所有
nmcli connection down --all
# 4. 使用systemd
# 停止ppp服务
sudo systemctl stop pppd@dsl-provider
# 禁用自动启动
sudo systemctl disable pppd@dsl-provider
# 查看状态
sudo systemctl status pppd@dsl-provider
# 5. 使用wvdial
# 如果使用wvdial拨号
sudo killall wvdial
# 或
sudo pkill wvdial
# 断开连接
wvdial --disconnect
# 6. 使用chat/pppd直接控制
# 找到pppd PID
PPP_PID=$(ps aux | grep pppd | grep -v grep | awk '{print $2}')
# 发送断开信号
sudo kill -TERM $PPP_PID
# 或通过控制文件
echo "quit" > /var/run/ppp0.pid
# 7. 使用ppp工具集
# 查看活动连接
plog
# 查看连接统计
pppstats
# 断开连接
# 先找到连接信息,然后终止对应进程
# 8. 使用Python脚本
#!/usr/bin/env python3
# 现代Python PPP断开脚本
import subprocess
import sys
import os
import signal
import time
def disconnect_ppp(interface="ppp0", force=False):
"""断开PPP连接"""
# 检查权限
if os.geteuid() != 0:
print("需要root权限", file=sys.stderr)
return False
print(f"断开PPP连接: {interface}")
# 检查接口是否存在
result = subprocess.run(
["ip", "link", "show", interface],
capture_output=True,
text=True
)
if result.returncode != 0:
print(f"接口 {interface} 不存在")
return True
# 查找pppd进程
result = subprocess.run(
["pgrep", "-f", f"pppd.*{interface}"],
capture_output=True,
text=True
)
pids = result.stdout.strip().split()
if pids:
for pid in pids:
if pid:
print(f"终止进程: {pid}")
if force:
os.kill(int(pid), signal.SIGKILL)
else:
os.kill(int(pid), signal.SIGTERM)
# 等待进程结束
for _ in range(10):
try:
os.kill(int(pid), 0)
time.sleep(1)
except OSError:
break
else:
print("未找到pppd进程")
# 删除接口
subprocess.run(["ip", "link", "delete", interface], capture_output=True)
# 清理路由
subprocess.run(["ip", "route", "del", "default", "dev", interface], capture_output=True)
print("连接已断开")
return True
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser(description="断开PPP连接")
parser.add_argument("-i", "--interface", default="ppp0", help="PPP接口名")
parser.add_argument("-f", "--force", action="store_true", help="强制断开")
parser.add_argument("-a", "--all", action="store_true", help="断开所有PPP连接")
args = parser.parse_args()
if args.all:
# 查找所有PPP接口
result = subprocess.run(
["ip", "-o", "link", "show"],
capture_output=True,
text=True
)
for line in result.stdout.splitlines():
if "ppp" in line:
iface = line.split(":")[1].strip()
disconnect_ppp(iface, args.force)
else:
disconnect_ppp(args.interface, args.force)
排查步骤:
ps aux | grep pppd
# 如果存在,手动终止
sudo killall pppd
# 或
sudo pkill -9 pppd
ip link show
# 查找ppp接口
# 手动删除
sudo ip link delete ppp0
# 如果忙,先关闭
sudo ip link set ppp0 down
sudo ip link delete ppp0
route -n
# 或
ip route show
# 删除ppp相关路由
sudo ip route del default dev ppp0
# 删除特定路由
sudo ip route del 192.168.1.0/24 dev ppp0
ls -la /var/run/*.pid
# 删除残留文件
sudo rm -f /var/run/ppp*.pid
sudo rm -f /var/run/pppd*.pid
# 重置串行端口
sudo stty -F /dev/ttyS0 sane
# 发送调制解调器命令
echo "ATH0" | sudo tee /dev/ttyS0
# 挂断调制解调器
sudo tail -f /var/log/syslog | grep ppp
sudo dmesg | grep ppp
sudo journalctl -f | grep ppp
sudo ppp-off -f
# 或
sudo ppp-off --force
迁移步骤:
# Debian/Ubuntu
sudo apt-get install ppp
# RHEL/CentOS
sudo yum install ppp
# 创建连接配置
sudo nano /etc/ppp/peers/dsl-provider
# 内容:
/dev/ttyS0
115200
noauth
defaultroute
usepeerdns
persist
maxfail 0
holdoff 10
debug
# 认证信息(在单独文件中)
# PAP认证
sudo nano /etc/ppp/pap-secrets
# 内容:
# 用户名 服务 密码 IP地址
myuser * mypass *
# CHAP认证
sudo nano /etc/ppp/chap-secrets
# 类似格式
# 原:ppp-on
# 新:pon dsl-provider
# 创建别名
alias ppp-on='pon dsl-provider'
# 原:ppp-off
# 新:poff
# 或指定连接
# poff dsl-provider
# 创建别名
alias ppp-off='poff'
# 建立连接
pon dsl-provider
# 查看状态
plog
# 断开连接
poff
# 或
poff dsl-provider
# 查找使用ppp-off的脚本
grep -r "ppp-off" /etc/ /usr/local/bin/ 2>/dev/null
# 替换为poff
sudo sed -i 's/ppp-off/poff/g' /path/to/script.sh
# 查看连接日志
plog
# 或
tail -f /var/log/ppp.log
安全断开步骤:
# 发送通知
echo "PPP连接将在5分钟后断开进行维护" | wall
# 或
notify-send "网络维护" "PPP连接将断开"
# 检查使用ppp0的连接
sudo lsof -i @ppp0
# 或
sudo netstat -tunap | grep ppp0
# 检查NFS、数据库等连接
# 备份路由表
ip route show > /tmp/routes-backup-$(date +%s).txt
# 备份接口配置
ip addr show ppp0 > /tmp/ppp0-backup.txt
# 正常断开
sudo ppp-off
# 或
sudo poff
# 等待完成
sleep 5
# 检查接口
ip link show ppp0
# 应该不存在
# 检查进程
ps aux | grep pppd
# 应该没有
# 清理残留接口
ip link delete ppp0 2>/dev/null
# 清理路由
ip route del default dev ppp0 2>/dev/null
# 清理PID文件
rm -f /var/run/ppp*.pid
# 记录到系统日志
logger "PPP连接已安全断开"
# 记录到专用日志
echo "$(date) - PPP连接断开 by $(whoami)" >> /var/log/ppp-maintenance.log
# 测试重新连接
pon dsl-provider
# 检查连接
ping -c 2 8.8.8.8
# 断开测试连接
poff
#!/bin/bash
# 安全断开PPP连接脚本
SAFE_DISCONNECT_TIMEOUT=30
NOTIFICATION_MESSAGE="PPP连接将在${SAFE_DISCONNECT_TIMEOUT}秒后断开"
# 发送通知
echo "$NOTIFICATION_MESSAGE" | wall
# 等待通知时间
sleep $SAFE_DISCONNECT_TIMEOUT
# 执行断开
if sudo ppp-off; then
echo "PPP连接已安全断开" | logger -t ppp-off
exit 0
else
echo "PPP连接断开失败" | logger -t ppp-off -p err
exit 1
fi
容器中使用ppp-off的注意事项:
# Docker运行参数
docker run --privileged --net=host ...
# 或
docker run --cap-add=NET_ADMIN --device=/dev/ttyS0 ...
# Kubernetes Pod配置
# securityContext:
# privileged: true
# 或
# securityContext:
# capabilities:
# add: ["NET_ADMIN"]
# Docker设备映射
docker run --device=/dev/ttyS0:/dev/ttyS0 ...
# 多个设备
docker run \
--device=/dev/ttyS0:/dev/ttyS0 \
--device=/dev/ppp:/dev/ppp \
...
#!/bin/bash
# 容器专用ppp-off
PPP_INTERFACE="${PPP_INTERFACE:-ppp0}"
# 检查接口
if ip link show "$PPP_INTERFACE" >/dev/null 2>&1; then
echo "断开PPP连接: $PPP_INTERFACE"
# 查找pppd进程
PPPD_PID=$(pgrep -f "pppd.*$PPP_INTERFACE")
if [ -n "$PPPD_PID" ]; then
kill -TERM "$PPPD_PID"
sleep 2
kill -KILL "$PPPD_PID" 2>/dev/null
fi
# 清理接口
ip link delete "$PPP_INTERFACE" 2>/dev/null
echo "连接已断开"
else
echo "接口 $PPP_INTERFACE 不存在"
fi
# 在主机命名空间中运行
nsenter --net=/proc/1/ns/net ppp-off
# 或使用主机网络
docker run --net=host ...
# 在容器内操作主机网络
ip netns exec host ppp-off
# Docker健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD ! ip link show ppp0 || exit 1
# Kubernetes存活探针
# livenessProbe:
# exec:
# command:
# - sh
# - -c
# - "! ip link show ppp0"
# 日志输出到stdout/stderr
exec ppp-off 2>&1 | logger -t ppp-off
# Docker日志驱动
docker run --log-driver=syslog ...
# 日志卷
docker run -v /var/log/ppp:/var/log/ppp ...
FROM alpine:latest
# 安装必要工具
RUN apk add --no-cache ppp iproute2
# 复制ppp-off脚本
COPY ppp-off /usr/local/bin/
RUN chmod +x /usr/local/bin/ppp-off
# 设置入口点
ENTRYPOINT ["ppp-off"]
CMD []
# Kubernetes Job用于断开连接
apiVersion: batch/v1
kind: Job
metadata:
name: ppp-disconnect
spec:
template:
spec:
containers:
- name: ppp-off
image: my-ppp-off:latest
securityContext:
capabilities:
add: ["NET_ADMIN"]
command: ["ppp-off"]
args: ["-a"]
restartPolicy: Never