网络聚合命令
网络配置命令(IP/网关/DNS/NTP/聚合)
逻辑:备份 → 写配置文件 → NTP → 重启网络生效 → 输出。不读旧配置内容。
网口:IFACE='*'自动探测(优先 bond/team > eth > ens/enp,排除 docker/k8s 等);已有 IP 优先,无 IP 时选 UP 物理口。
Ubuntu netplan:备份后重写原 yaml(含该网口的文件,否则取第一个),删除其余 yaml 避免冲突。
CentOS/Rocky:写最小 ifcfg(仅 IP/网关/DNS)→ 配 NTP → 生效。CentOS 7 优先nmcli device reapply读 ifcfg;无 NM 时用restart network;兜底用ip命令。
DNS:默认留空,空时自动使用 GW 作为 DNS。
说明:以下四条命令均 ≤2000 字符,可直接复制;IP/GW各一行,其余参数共一行。
1. Ubuntu/Debian 单网口(netplan)
sudo ip link set ens18 up && sudo ip addr add 10.129.240.33/24 dev ens18 && sudo ip route replace default via 10.129.240.254 dev ens18
sudo bash <<'EOF'
IP='10.10.10.10'
GW='10.10.10.254'
DNS='';NTP='';MASK='24';IF='*'
[ -z "$DNS" ]&&DNS=$GW
P(){ r=$(ip -br -4 a|awk '$1!~"^(lo|docker|veth|kube|cni|br-|flannel)"&&$2=="UP"&&$3~/\//{print($1~/^bond/?100:$1~/^eth/?90:$1~/^(ens|enp)/?80:10),$1}'|sort -rn|head -1|awk '{print $2}');[ -n "$r" ]&&echo "$r"||ip -br link|awk '$1!~"^(lo|docker|veth|kube|cni|br-|bond|team|flannel)"&&$2=="UP"{print($1~/^eth/?90:$1~/^(ens|enp)/?80:10),$1}'|sort -rn|head -1|awk '{print $2}'; }
[ "$IF"="*" ]&&IF=$(P);[ -n "$IF" ]||{ echo FAIL:iface;exit 1; }
echo "CFG: $IF $IP/$MASK gw=$GW dns=$DNS${NTP:+ ntp=$NTP}"
D=/root/nb-$(date +%Y%m%d%H%M%S);mkdir -p $D;cp -a /etc/netplan $D/ 2>/dev/null&&echo OK:backup:$D||echo FAIL:backup
shopt -s nullglob;Y=(/etc/netplan/*.yaml);T=$(printf '%s\n' "${Y[@]}"|sort|head -1)
for f in "${Y[@]}";do grep -q " $IF:" "$f"&&T=$f;done;[ -z "$T" ]&&T=/etc/netplan/01-netcfg.yaml
R=$(grep -h renderer: $D/netplan/*.yaml 2>/dev/null|awk '{print $2}'|head -1);R=${R:-networkd}
for f in /etc/netplan/*.yaml;do [ "$f"!="$T" ]&&rm -f "$f";done;shopt -u nullglob
cat>$T<<E
network:
version: 2
renderer: $R
ethernets:
$IF:
dhcp4: no
addresses: [$IP/$MASK]
routes: [{to: default, via: $GW}]
nameservers: {addresses: [$DNS]}
E
echo OK:file:$T
[ -n "$NTP" ]&&{ grep -q '^\[Time\]' /etc/systemd/timesyncd.conf||echo '[Time]'>>/etc/systemd/timesyncd.conf; sed -i "s/^NTP=.*/NTP=$NTP/" /etc/systemd/timesyncd.conf 2>/dev/null||sed -i "/^\[Time\]/a NTP=$NTP" /etc/systemd/timesyncd.conf; systemctl restart systemd-timesyncd 2>/dev/null; systemctl is-active systemd-timesyncd&>/dev/null&&echo OK:ntp||echo FAIL:ntp; }||echo SKIP:ntp
netplan apply&&echo OK:apply||{ echo FAIL:apply;exit 1; }
a=$(ip -4 -o a show dev $IF|awk '{print $4}'|head -1);g=$(ip route show default|awk '{print $3}'|head -1)
[ "$a"="$IP/$MASK" ]&&echo OK:ip||echo FAIL:ip:$a;[ "$g"="$GW" ]&&echo OK:gw||echo FAIL:gw:$g
EOF
2. CentOS/Rocky 单网口(ifcfg)
sudo nmcli con mod eth0 ipv4.addresses 10.129.240.33/24 ipv4.gateway 10.129.240.254 ipv4.method manual && sudo nmcli con up eth0
sudo bash <<'EOF'
IP='10.10.10.10'
GW='10.10.10.254'
DNS='';NTP='';MASK='24';IF='*'
[ -z "$DNS" ]&&DNS=$GW
P(){ r=$(ip -br -4 a|awk '$1!~"^(lo|docker|veth|kube|cni|br-|flannel)"&&$2=="UP"&&$3~/\//{print($1~/^bond/?100:$1~/^team/?100:$1~/^eth/?90:$1~/^(ens|enp)/?80:10),$1}'|sort -rn|head -1|awk '{print $2}');[ -n "$r" ]&&echo "$r"||ip -br link|awk '$1!~"^(lo|docker|veth|kube|cni|br-|bond|team|flannel)"&&$2=="UP"{print($1~/^eth/?90:$1~/^(ens|enp)/?80:10),$1}'|sort -rn|head -1|awk '{print $2}'; }
[ "$IF"="*" ]&&IF=$(P);[ -n "$IF" ]||{ echo FAIL:iface;exit 1; }
echo "CFG: $IF $IP/$MASK gw=$GW dns=$DNS${NTP:+ ntp=$NTP}"
D=/root/nb-$(date +%Y%m%d%H%M%S);mkdir -p $D /etc/sysconfig/network-scripts;cp -a /etc/sysconfig/network-scripts/ifcfg-* $D/ 2>/dev/null;echo OK:backup:$D
cat>/etc/sysconfig/network-scripts/ifcfg-$IF<<C
DEVICE=$IF
ONBOOT=yes
BOOTPROTO=none
IPADDR=$IP
PREFIX=$MASK
GATEWAY=$GW
DNS1=$DNS
C
echo OK:file:ifcfg-$IF
[ -n "$NTP" ]&&{ mkdir -p /etc/chrony.d;echo "server $NTP iburst">/etc/chrony.d/99-custom.conf;systemctl restart chronyd 2>/dev/null; pgrep chronyd&>/dev/null&&echo OK:ntp||echo FAIL:ntp; }||echo SKIP:ntp
if nmcli dev status&>/dev/null;then nmcli con reload 2>/dev/null;(nmcli con up $IF||nmcli con up "System $IF")&>/dev/null;else systemctl restart network&>/dev/null;fi
a=$(ip -4 -o a show dev $IF|awk '{print $4}'|head -1);g=$(ip route show default|awk '{print $3}'|head -1)
[ "$a"="$IP/$MASK" ]&&echo OK:apply||echo FAIL:apply;[ "$a"="$IP/$MASK" ]&&echo OK:ip||echo FAIL:ip:$a;[ "$g"="$GW" ]&&echo OK:gw||echo FAIL:gw:$g
EOF
3. Ubuntu/Debian 双网口聚合 bond0(netplan)
sudo bash <<'EOF'
IP='10.10.10.10'
GW='10.10.10.254'
DNS='';NTP='';MASK='24';S1='*';S2='*';BO=bond0
[ -z "$DNS" ]&&DNS=$GW
L(){ { ip -br -4 a|awk '$1!~"^(lo|docker|veth|kube|cni|br-|bond|team|flannel)"&&$2=="UP"&&$3~/\//{print($1~/^eth/?90:$1~/^(ens|enp)/?80:50)+50,$1}'; ip -br link|awk '$1!~"^(lo|docker|veth|kube|cni|br-|bond|team|flannel)"&&$2=="UP"{print($1~/^eth/?90:$1~/^(ens|enp)/?80:50),$1}'; }|awk '!s[$2]||$1+0>s[$2]{s[$2]=$1+0} END{for(i in s)print s[i],i}'|sort -rn|awk '{print $2}'; }
if [ "$S1"="*" ];then
[ -r /sys/class/net/$BO/bonding/slaves ]&&read S1 S2 _ </sys/class/net/$BO/bonding/slaves
[ -z "$S1" ]&&{ A=($(L));S1=${A[0]};S2=${A[1]}; }
[ -n "$S1" ]&&[ -n "$S2" ]||{ echo FAIL:iface;exit 1; }
fi
echo "CFG: $BO($S1+$S2) $IP/$MASK gw=$GW dns=$DNS${NTP:+ ntp=$NTP}"
D=/root/nb-$(date +%Y%m%d%H%M%S);mkdir -p $D;cp -a /etc/netplan $D/ 2>/dev/null&&echo OK:backup:$D||echo FAIL:backup
shopt -s nullglob;Y=(/etc/netplan/*.yaml);T=$(printf '%s\n' "${Y[@]}"|sort|head -1)
for f in "${Y[@]}";do grep -qE "bonds:| $BO:" "$f"&&T=$f;done
R=$(grep -h renderer: $D/netplan/*.yaml 2>/dev/null|awk '{print $2}'|head -1);R=${R:-networkd}
for f in /etc/netplan/*.yaml;do [ "$f"!="$T" ]&&rm -f "$f";done;shopt -u nullglob
cat>$T<<E
network:
version: 2
renderer: $R
ethernets:
$S1: {dhcp4: no}
$S2: {dhcp4: no}
bonds:
$BO:
dhcp4: no
interfaces: [$S1, $S2]
parameters: {mode: active-backup}
addresses: [$IP/$MASK]
routes: [{to: default, via: $GW}]
nameservers: {addresses: [$DNS]}
E
echo OK:file:$T
[ -n "$NTP" ]&&{ grep -q '^\[Time\]' /etc/systemd/timesyncd.conf||echo '[Time]'>>/etc/systemd/timesyncd.conf; sed -i "s/^NTP=.*/NTP=$NTP/" /etc/systemd/timesyncd.conf 2>/dev/null||sed -i "/^\[Time\]/a NTP=$NTP" /etc/systemd/timesyncd.conf; systemctl restart systemd-timesyncd 2>/dev/null; systemctl is-active systemd-timesyncd&>/dev/null&&echo OK:ntp||echo FAIL:ntp; }||echo SKIP:ntp
netplan apply&&echo OK:apply||{ echo FAIL:apply;exit 1; }
a=$(ip -4 -o a show dev $BO|awk '{print $4}'|head -1);g=$(ip route show default|awk '{print $3}'|head -1)
[ "$a"="$IP/$MASK" ]&&echo OK:ip||echo FAIL:ip:$a;[ "$g"="$GW" ]&&echo OK:gw||echo FAIL:gw:$g
EOF
4. CentOS/Rocky 双网口聚合 team0(ifcfg)
前置:yum install -y teamd NetworkManager-team
sudo bash <<'EOF'
IP='10.10.10.10'
GW='10.10.10.254'
DNS='';NTP='';MASK='24';S1='*';S2='*';TM=team0
[ -z "$DNS" ]&&DNS=$GW
L(){ { ip -br -4 a|awk '$1!~"^(lo|docker|veth|kube|cni|br-|bond|team|flannel)"&&$2=="UP"&&$3~/\//{print($1~/^eth/?90:$1~/^(ens|enp)/?80:50)+50,$1}'; ip -br link|awk '$1!~"^(lo|docker|veth|kube|cni|br-|bond|team|flannel)"&&$2=="UP"{print($1~/^eth/?90:$1~/^(ens|enp)/?80:50),$1}'; }|awk '!s[$2]||$1+0>s[$2]{s[$2]=$1+0} END{for(i in s)print s[i],i}'|sort -rn|awk '{print $2}'; }
if [ "$S1"="*" ];then
[ -d /sys/class/net/$TM ]&&{ A=($(ls /sys/class/net/$TM/lower_* 2>/dev/null|xargs -n1 basename|sed 's/^lower_//')); S1=${A[0]};S2=${A[1]}; }
[ -z "$S1" ]&&{ A=($(L));S1=${A[0]};S2=${A[1]}; }
[ -n "$S1" ]&&[ -n "$S2" ]||{ echo FAIL:iface;exit 1; }
fi
echo "CFG: $TM($S1+$S2) $IP/$MASK gw=$GW dns=$DNS${NTP:+ ntp=$NTP}"
D=/root/nb-$(date +%Y%m%d%H%M%S);mkdir -p $D;cp -a /etc/sysconfig/network-scripts/ifcfg-* $D/ 2>/dev/null&&echo OK:backup:$D||echo FAIL:backup
cat>/etc/sysconfig/network-scripts/ifcfg-$TM<<C
DEVICE=$TM
DEVICETYPE=Team
TEAM_CONFIG={"runner": {"name": "activebackup"}}
BOOTPROTO=none
ONBOOT=yes
IPADDR=$IP
PREFIX=$MASK
GATEWAY=$GW
DNS1=$DNS
C
for S in $S1 $S2;do cat>/etc/sysconfig/network-scripts/ifcfg-$S<<C
DEVICE=$S
DEVICETYPE=TeamPort
TEAM_MASTER=$TM
BOOTPROTO=none
ONBOOT=yes
C
done
echo OK:file:ifcfg-$TM,$S1,$S2
[ -n "$NTP" ]&&{ mkdir -p /etc/chrony.d;echo "server $NTP iburst">/etc/chrony.d/99-custom.conf;systemctl restart chronyd 2>/dev/null; pgrep chronyd&>/dev/null&&echo OK:ntp||echo FAIL:ntp; }||echo SKIP:ntp
if nmcli dev status&>/dev/null;then nmcli con reload 2>/dev/null;nmcli con up $TM 2>/dev/null||nmcli dev reapply $TM 2>/dev/null;else systemctl restart network 2>/dev/null;fi
a=$(ip -4 -o a show dev $TM|awk '{print $4}'|head -1);g=$(ip route show default|awk '{print $3}'|head -1)
[ "$a"!="$IP/$MASK" ]&&{ ip link set $TM up;ip addr flush dev $TM 2>/dev/null;ip addr add $IP/$MASK dev $TM;ip route replace default via $GW dev $TM;a=$IP/$MASK;g=$GW; }
[ "$a"="$IP/$MASK" ]&&echo OK:apply||echo FAIL:apply;[ "$a"="$IP/$MASK" ]&&echo OK:ip||echo FAIL:ip:$a;[ "$g"="$GW" ]&&echo OK:gw||echo FAIL:gw:$g
EOF
主机与网络信息查看命令
一键输出主机 OS、物理机/虚拟机、网卡类型,以及业务网卡的 IP、掩码、网关、DNS、NTP、MAC 等网络配置,用于现场排查或填写网络工单。自动识别业务网卡(优先 bond > eth > ens/enp),排除 Docker、K8s、Flannel 等内部网卡;
sudo -E timeout 10 bash <<'EOF'
IFACE='*'
_o(){ . /etc/os-release 2>/dev/null&&echo "${PRETTY_NAME:-$NAME}"||uname -sr;}
_h(){ v=$(systemd-detect-virt 2>/dev/null|head -1|tr -d ' \t\r\n');[ "$v" = none -o -z "$v" ]&&echo physical||echo "VM($v)";}
_n(){ [ -r /sys/class/net/$1/bonding/slaves ]&&{ echo bond;return;}
d=$(sudo ethtool -i $1 2>/dev/null|awk '/driver:/{print $2;exit}')
case $d in virtio*|vmxnet3|veth|tap|tun) echo "virtual($d)";;""|unknown) echo unknown;;*) echo "physical($d)";; esac;}
_p(){ ip -br -4 a 2>/dev/null|awk '$1!~"^(lo|docker|cni|flannel|nodelocaldns|veth|kube|calico|tun|tap|virbr|br-|podman)"&&$2=="UP"&&$3~/\//{
ip=$3;sub(/\/.*/,"",ip);if(ip~/^10\.|^192\.168\.|^172\.(1[6-9]|2[0-9]|3[0-1])\./)print ($1~/^bond/?100:$1~/^eth/?90:$1~/^(ens|enp)/?80:10),$1,$3}'|sort -rn|head -1|awk '{print $2,$3}';}
_d(){ if=$1;n=;command -v nmcli&>/dev/null&&n=$(nmcli -t -f IP4.DNS dev show "$if" 2>/dev/null|awk -F: '$2~/^[0-9]/{print $2}')
[ -z "$n" ]&&[ -f /etc/sysconfig/network-scripts/ifcfg-$if ]&&n=$(grep -E '^DNS[0-9]+=' /etc/sysconfig/network-scripts/ifcfg-$if|cut -d= -f2)
[ -z "$n" ]&&command -v resolvectl&>/dev/null&&n=$(resolvectl dns "$if" 2>/dev/null|grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}')
[ -z "$n" ]&&n=$(awk '/^nameserver /{print $2}' /etc/resolv.conf 2>/dev/null|grep -Ev '^127\.');echo "$n"|sort -u|paste -sd ', ' -;}
_t(){ s=$(grep -Erh '^(server|pool) ' /etc/chrony.conf /etc/chrony/chrony.conf /etc/chrony.d/ /etc/ntp.conf 2>/dev/null|
grep -v '^#'|awk '{print $2}'|grep -E '^[0-9a-zA-Z]'|sort -u|paste -sd ', ' -)
[ -z "$s" ]&&[ -f /etc/systemd/timesyncd.conf ]&&s=$(awk -F= '/^(NTP|FallbackNTP)=/{gsub(/ /,"",$2);if($2)print $2}' /etc/systemd/timesyncd.conf|
tr ' ' '\n'|grep -E '^[0-9a-zA-Z]'|paste -sd ', ' -);echo "${s:-—}";}
if [ "$IFACE" = '*' ];then read IF CIDR _ < <(_p);else
CIDR=$(ip -br -4 a show dev "$IFACE" 2>/dev/null|awk '$2=="UP"{print $3;exit}');IF=$IFACE;fi
[ -n "${IF:-}" -a -n "${CIDR:-}" ]||{ echo;echo "[ERROR] no business NIC found";exit 1;}
ADDR=${CIDR%%/*};PFX=${CIDR#*/}
MASK=$(awk -v p=$PFX 'BEGIN{for(i=0;i<4;i++){n=p-i*8;if(n>=8)m[i]=255;else if(n<=0)m[i]=0;else m[i]=256-2^(8-n)}printf "%d.%d.%d.%d",m[0],m[1],m[2],m[3]}')
GW=$(ip -4 route show default dev "$IF" 2>/dev/null|awk '{print $3;exit}');GW=${GW:-$(ip -4 route show default 2>/dev/null|awk '{print $3;exit}')};GW=${GW:-—}
MAC=$(cat /sys/class/net/$IF/address 2>/dev/null||echo —);DNS=$(_d "$IF");NTP=$(_t);[ -z "$DNS" ]&&DNS=—
echo
echo "=== Host ==="
echo "OS: $(_o)"
echo "Type: $(_h)"
echo "Hostname: $(hostname -f 2>/dev/null||hostname)"
echo
echo "=== Business NIC ($IF) ==="
echo "NIC: $(_n "$IF")"
echo "MAC: $MAC"
echo "IPv4: $ADDR"
echo "Netmask: $MASK (/$PFX)"
echo "Gateway: $GW"
echo "DNS: $DNS"
echo "NTP: $NTP"
EOF
ping 网段可用 IP 探测命令
在内网服务器上快速探测本机所在私网 /24 网段中哪些 IP 可能可用,用于申请或分配 IP 前的初步筛选。
- 自动识别业务网卡(优先
bond>eth>ens/enp),排除 Docker、K8s、Flannel 等内部网卡 - 仅探测与本机同 /24 网段(.1–.254),避免跨网段误扫
- 有 ping 响应 → 已占用;无响应 → 可能可用(目标可能禁 ping,需二次确认)
- 输出 OS、物理机/虚拟机、网卡类型;连续 IP 合并显示(如
10.129.243.31-40) - 整段上限 10s,25 路并行,单包等待 1s;非 root 可用
sudo执行
判读: In Use 已占用 | Possibly Free 可能可用(需二次确认)
sudo -E bash <<'EOF'
T=10; W=1; P=${PRL:-25}
_os(){ . /etc/os-release 2>/dev/null; echo "${PRETTY_NAME:-$(uname -s)} | $(uname -r)"; }
_hv(){ v=$(systemd-detect-virt 2>/dev/null|head -1|tr -d ' \t\r\n');[ "$v" = none -o -z "$v" ]&&echo physical||echo "VM($v)"; }
_nc(){ d=$(sudo ethtool -i "$1" 2>/dev/null|awk '/^driver:/{print $2;exit}');
[ -r "/sys/class/net/$1/bonding/slaves" ]&&echo "$1|bond"||echo "$1|${d:-unknown}"; }
_pk(){ ip -br -4 a 2>/dev/null|awk '
$1!~"^(lo|docker|cni|flannel|veth|kube|calico|tun|tap|virbr|br-|podman)"&&$2=="UP"&&$3~/\/24$/{
sub(/\/.*/,"",$3); if($3~/^10\.|^192\.168\.|^172\.(1[6-9]|2[0-9]|3[0-1])\./)
print ($1~/^bond/?100:$1~/^eth/?90:$1~/^(ens|enp)/?80:10),$1,$3
}'|sort -rn|head -1|awk '{print $2,$3}'; }
_rg(){ awk -F. 'function r(a,b,p,q){split(a,p,".");split(b,q,".");if(p[3]==q[3])return a"-"q[4];return a"-"b}
{n++;o[n]=$4+0;i[n]=$0} END{if(!n){print"(none)";exit}s=1;for(j=2;j<=n;j++)if(o[j]!=o[j-1]+1){
if(s==j-1)print i[s];else print r(i[s],i[j-1]);s=j} if(s==n)print i[s];else print r(i[s],i[n])}'; }
read IF IP _ <<<"$(_pk)"; [ -n "$IF" ]||{ echo "[ERR] no private /24 iface"; exit 1; }
IFS=. read -r a b c _ <<<"$IP"; S="$a.$b.$c"; f=$(mktemp); trap 'rm -f "$f"' EXIT
echo "=== Host Info ==="
echo "OS: $(_os)"
echo "Type: $(_hv)"
echo "NIC: $(_nc "$IF") ($IP/24)"
echo
echo "=== Ping Scan (${T}s, ${P} parallel, ${W}s/pkt) ==="
timeout "$T" bash -c 'seq 1 254|xargs -P '"$P"' -I{} sh -c '\''
ip="'"$S"'.$1"; ping -c1 -W'"$W"' -q "$ip" >/dev/null 2>&1 && echo u "$ip" || echo f "$ip"'\'' _ {}' >"$f" || true
sort -t. -k4 -n "$f" -o "$f"
u=$(grep -c '^u ' "$f" 2>/dev/null||echo 0); v=$(grep -c '^f ' "$f" 2>/dev/null||echo 0)
echo
echo "=== In Use ($u) ==="
grep '^u ' "$f" 2>/dev/null|awk '{print $2}'|_rg||echo "(none)"
echo
echo "=== Possibly Free ($v) ==="
grep '^f ' "$f" 2>/dev/null|awk '{print $2}'|_rg||echo "(none)"
echo
echo "=== Summary ==="
echo "In use: $u | Possibly free: $v | Scanned: $((u+v))/254"
[ "$((u+v))" -lt 254 ]&&echo "Note: ${T}s timeout; partial scan"
EOF
系统内核优化(CentOS 7 / Ubuntu 20 通用)
逻辑:备份 → 写 sysctl / limits / systemd 配置 → 立即生效 → 校验输出。
范围:仅通用项(句柄数、进程数、TCP 连接/端口/超时/保活、连接队列、基础内核参数)。
不含:BBR、网卡中断绑核、透明大页、swap 等场景化或争议项。
说明:复制整段执行;新 SSH 会话后ulimit -n才反映 limits 变更;已运行服务需重启后生效。
sudo bash <<'EOF'
set -e
# ========== 可调参数(按需修改) ==========
NOFILE=1048576 # 单进程最大打开文件数(句柄)| 默认1024 | 调大 | 每连接占1句柄,防too many open files
NPROC=65535 # 单用户最大进程数 | 默认4096~16384 | 调大 | 多进程/线程服务防上限
FILE_MAX=2097152 # 系统级文件句柄上限 | 默认约10万级 | 调大 | 系统总句柄池,支撑高并发
SOMAXCONN=65535 # accept队列长度 | 默认128~4096 | 调大 | 握手完成待accept,防连接被拒
PORT_MIN=1024 # 本地端口范围下限 | 默认32768 | 调小 | 扩大可用临时端口下限
PORT_MAX=65535 # 本地端口范围上限 | 默认60999 | 调大 | 出站短连接多,防端口耗尽
TCP_FIN_TIMEOUT=30 # FIN_WAIT2超时(秒)| 默认60 | 调小 | 异常关闭时更快释放FIN_WAIT2
TCP_KEEPALIVE_TIME=600 # 无数据时首次发keepalive(秒)| 默认7200 | 调小 | 空闲连接更早探测,穿透NAT/LB
TCP_KEEPALIVE_INTVL=30 # keepalive探测间隔(秒)| 默认75 | 调小 | 缩短探测间隔,加快发现死连接
TCP_KEEPALIVE_PROBES=3 # 判定断开前探测次数 | 默认9 | 调小 | 减少无效探测,更快判定断开
# ========== 0. 环境检查 ==========
[ "$(id -u)" -eq 0 ] || { echo FAIL:root; exit 1; }
if [ -f /etc/os-release ]; then
. /etc/os-release
OS_ID=${ID:-unknown}
OS_VER=${VERSION_ID:-}
else
OS_ID=unknown; OS_VER=
fi
case "$OS_ID" in
centos|rhel|rocky|almalinux) OS_FAMILY=rhel ;;
ubuntu|debian) OS_FAMILY=debian ;;
*) OS_FAMILY=other ;;
esac
echo "=== OS: ${PRETTY_NAME:-$OS_ID $OS_VER} (family=$OS_FAMILY) ==="
TS=$(date +%Y%m%d%H%M%S)
BK=/root/ko-bak-$TS
mkdir -p "$BK"
cp -a /etc/sysctl.conf "$BK/" 2>/dev/null || true
cp -a /etc/sysctl.d "$BK/" 2>/dev/null || true
cp -a /etc/security/limits.conf "$BK/" 2>/dev/null || true
cp -a /etc/security/limits.d "$BK/" 2>/dev/null || true
cp -a /etc/systemd/system.conf "$BK/" 2>/dev/null || true
cp -a /etc/systemd/system.conf.d "$BK/" 2>/dev/null || true
echo OK:backup:$BK
# ========== 1. sysctl 内核网络/句柄参数 ==========
SYSCTL_F=/etc/sysctl.d/99-common-kernel-tuning.conf
cat >"$SYSCTL_F" <<S
# common kernel tuning - generated $(date '+%F %T')
# fs / process
fs.file-max = $FILE_MAX
fs.nr_open = $FILE_MAX
kernel.pid_max = 4194304
# connection queue
net.core.somaxconn = $SOMAXCONN
net.core.netdev_max_backlog = $SOMAXCONN
net.ipv4.tcp_max_syn_backlog = $SOMAXCONN
# tcp port / orphan / recycle
net.ipv4.ip_local_port_range = $PORT_MIN $PORT_MAX
net.ipv4.tcp_max_orphans = 262144
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = $TCP_FIN_TIMEOUT
net.ipv4.tcp_slow_start_after_idle = 0
# tcp keepalive
net.ipv4.tcp_keepalive_time = $TCP_KEEPALIVE_TIME
net.ipv4.tcp_keepalive_intvl = $TCP_KEEPALIVE_INTVL
net.ipv4.tcp_keepalive_probes = $TCP_KEEPALIVE_PROBES
# tcp retry / syncookie
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_retries2 = 5
net.ipv4.tcp_syncookies = 1
# socket buffer (conservative universal)
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
S
echo OK:file:$SYSCTL_F
if sysctl --system &>/dev/null; then
sysctl --system &>/dev/null && echo OK:sysctl-apply || { echo FAIL:sysctl-apply; exit 1; }
else
sysctl -p "$SYSCTL_F" &>/dev/null && echo OK:sysctl-apply || { echo FAIL:sysctl-apply; exit 1; }
fi
# ========== 2. limits 句柄 / 进程数 ==========
LIMITS_F=/etc/security/limits.d/99-common-nofile.conf
cat >"$LIMITS_F" <<L
# common limits - generated $(date '+%F %T')
* soft nofile $NOFILE
* hard nofile $NOFILE
* soft nproc $NPROC
* hard nproc $NPROC
root soft nofile $NOFILE
root hard nofile $NOFILE
root soft nproc $NPROC
root hard nproc $NPROC
L
echo OK:file:$LIMITS_F
# ========== 3. systemd 默认 limits(两发行版均适用) ==========
mkdir -p /etc/systemd/system.conf.d
SD_F=/etc/systemd/system.conf.d/99-common-limits.conf
cat >"$SD_F" <<D
[Manager]
DefaultLimitNOFILE=$NOFILE
DefaultLimitNPROC=$NPROC
D
echo OK:file:$SD_F
if command -v systemctl &>/dev/null; then
systemctl daemon-reexec 2>/dev/null && echo OK:systemd-reexec || echo WARN:systemd-reexec
fi
# ========== 4. 校验输出 ==========
echo
echo "=== Verify (runtime) ==="
printf "fs.file-max = %s (expect %s)\n" "$(sysctl -n fs.file-max 2>/dev/null)" "$FILE_MAX"
printf "net.core.somaxconn = %s (expect %s)\n" "$(sysctl -n net.core.somaxconn 2>/dev/null)" "$SOMAXCONN"
printf "tcp_fin_timeout = %s (expect %s)\n" "$(sysctl -n net.ipv4.tcp_fin_timeout 2>/dev/null)" "$TCP_FIN_TIMEOUT"
printf "tcp_keepalive_time = %s (expect %s)\n" "$(sysctl -n net.ipv4.tcp_keepalive_time 2>/dev/null)" "$TCP_KEEPALIVE_TIME"
printf "ip_local_port_range = %s (expect %s %s)\n" "$(sysctl -n net.ipv4.ip_local_port_range 2>/dev/null)" "$PORT_MIN" "$PORT_MAX"
echo
echo "=== Note ==="
echo "limits 对新登录会话生效;已运行进程/服务需重启后应用新 nofile。"
echo "回滚: 恢复 $BK 下文件后执行 sysctl --system"
EOF
五、出站 TCP 探测(15 站点)
在待测客户端或服务端执行,探测常用 yum/apt/k8s/docker/GitHub/Helm 等站点 80/443 TCP 是否可达(非 HTTP 内容检测)。每端口超时 3s,并行执行,整段上限 12s;无需 root。
判读: OK 已连通 | refused 主动拒绝 | reset 连接被 RST | unreach 无路由 | timeout 超过 3s 无响应(多为防火墙 DROP)
timeout 12 bash <<'EOF'
cfn(){ e="$1"; c="$2"
[ "$c" -eq 0 ] && echo OK && return
[ "$c" -eq 124 ] && echo timeout && return
e=$(printf '%s' "$e" | tr '\n' ' ' | sed 's/ */ /g;s/^bash: //g')
echo "$e" | grep -qi refused && echo refused && return
echo "$e" | grep -qi reset && echo reset && return
echo "$e" | grep -qi unreachable && echo unreach && return
echo "$e" | grep -qi 'no route' && echo unreach && return
echo "$e" | grep -qi timeout && echo timeout && return
printf 'err(%.28s)' "$e"
}
p(){ l="$1"; h="$2"; o=""
for pt in 80 443; do
e=$(timeout 3 bash -c "echo >/dev/tcp/${h}/${pt}" 2>&1); c=$?
o="${o} ${pt}:$(cfn "$e" "$c")"
done
printf "%-14s %-28s%s\n" "$l" "$h" "$o"
}
echo "=== Egress TCP probe (80+443/host, 3s/port, parallel) ==="
echo "Legend: OK=connected | refused=reject | reset=RST | unreach=no route | timeout=>3s no reply"
echo ""
while IFS='|' read -r l h; do p "$l" "$h" & done <<'T'
Aliyun|mirrors.aliyun.com
Tsinghua|mirrors.tuna.tsinghua.edu.cn
Tencent-yum|mirrors.cloud.tencent.com
Ubuntu-apt|archive.ubuntu.com
Ubuntu-sec|security.ubuntu.com
GitHub|github.com
Google|www.google.com
DockerHub|registry-1.docker.io
Docker-pkg|download.docker.com
K8s|pkgs.k8s.io
Helm|get.helm.sh
Quay|quay.io
Debian|deb.debian.org
GCS|storage.googleapis.com
MS-pkg|packages.microsoft.com
T
wait
echo ""
echo "=== Done ==="
EOF