CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
Shell 与 Bash 入门/课时/网络命令
RawBlame
课时目录12 节

Shell 与 Bash 入门

  1. 01Shell 是什么
  2. 02目录与文件导航
  3. 03文件操作与权限
  4. 04管道与文本处理
  5. 05变量与字符串
  6. 06条件与循环
  7. 07函数与脚本结构
  8. 08正则表达式
  9. 09进程与定时任务
  10. 10网络命令
  11. 11系统管理与编辑器
  12. 12综合练习

网络命令

curl、ssh、wget、scp。

30 分钟

网络命令

这一课你将能做到

  1. 用 curl 完成 GET/POST 请求、带头带体带超时,并用 -w 输出状态码和耗时做接口巡检
  2. 用 ss -tlnp 查端口监听与归属进程,判断「服务到底起没起来」
  3. 用 ping / dig / ssh / scp 完成基础连通性、域名解析和远程文件传输

为什么要学

「接口打不通」是后端最高频的线上问题之一,而它从来不是一个问题,是四个候选答案:进程没起?端口没监听?防火墙拦了?域名解析错了?每种答案对应一条 Shell 命令。curl 还是你测试 Spring Boot 接口的终端版 Postman——CI 流水线里的健康检查、发布脚本的探活循环、联调时快速验证参数,全是 curl。面试聊「502 怎么排查」,Nginx→后端这条链路的每个环节都得能用命令验证。

人话:curl 是「终端里的浏览器」,ss 是「端口门卫登记表」,ping 测「路通不通」,dig 查「门牌号对不对」,ssh/scp 是「远程遥控器 + 快递员」。五件套在手,网络问题的排查路径就闭环了。

先建立图像

一次 HTTP 请求的排查地图:

浏览器/curl ──→ DNS 解析 ──→ TCP 连接 ──→ Nginx ──→ Spring Boot
   │              │            │           │            │
   curl 命令    dig 域名      ss/ping    nginx -t     ps/jstack
                查解析对不对  看端口监听  查配置语法   查应用状态

「服务没起来」的四层候选与对应命令:

症状可能原因验证命令
curl: connection refused进程没起或端口没监听ss -tlnp | grep 8080
卡住后 timeout防火墙/安全组拦截ping、云控制台安全组
404进程在,路由不对curl -i 看响应头
502Nginx 在,后端挂了curl 后端端口 + ps

跟着做

步骤 1:curl 基本功:GET 与状态码

curl https://httpbin.org/get            # 输出响应体
curl -i https://httpbin.org/get         # 连响应头一起看
curl -s -o /dev/null -w "%{http_code}\n" https://httpbin.org/status/200
# 输出:200   ← 巡检脚本里最有用的一行

curl -sL -o /dev/null -w "%{http_code} %{time_total}s\n" http://example.com
# -L 跟随重定向;%{time_total} 总耗时,性能初判

-s 静默(不显示进度条),-o /dev/null 丢弃响应体只要状态码,-w 自定义输出格式——这三件套组合是接口巡检的工业标准写法。

步骤 2:POST 与常见参数

# JSON POST(对接 Spring Boot 接口)
curl -s -X POST http://localhost:8080/api/order \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer token123" \
  -d '{"productId":1,"count":2}'

# 表单 POST
curl -s -X POST -d "username=tom&password=123" http://localhost:8080/login

# 必加超时!否则脚本会被无响应接口挂死
curl -s -m 5 --connect-timeout 2 http://localhost:8080/actuator/health

整体最多 5 秒, 建连最多 2 秒。写进脚本的 curl 不带超时是事故预备役。

-m 5
--connect-timeout 2

步骤 3:本机起个服务练手

没有现成接口也能练,Python 一行起个服务(绝大多数 Linux 自带):

cd ~/net-lab 2>/dev/null || mkdir -p ~/net-lab && cd ~/net-lab
echo "hello from server" > index.html
nohup python3 -m http.server 8000 > server.log 2>&1 &
sleep 1
curl -s http://localhost:8000/            # hello from server
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8000/   # 200

步骤 4:ss 查端口监听(netstat 的现代替代)

ss -tlnp | grep 8000
# LISTEN 0 511 0.0.0.0:8000 0.0.0.0:* users:(("python3",pid=1234,fd=3))
# -t TCP  -l 监听中  -n 数字显示  -p 显示进程

ss -tlnp | grep -E ':(80|443|8080)\s'    # 一次查三个常用端口
ss -tn state established | head          # 当前已建立的连接(看谁连着我)
ss -s                                    # 连接状态汇总(TIME_WAIT 多不多一眼看出)

老系统没有 ss 用 netstat -tlnp,参数几乎同名。看到 0.0.0.0:8080 是对所有网卡监听(外部可访问),127.0.0.1:8080 只有本机能访问——排查「本地好好的外部访问不了」第一查这个。

步骤 5:ping 与 dig

ping -c 3 baidu.com              # 发 3 个包就停;通=网络层可达
dig +short api.example.com       # 查域名解析结果
dig +short api.example.com @8.8.8.8   # 指定 DNS 服务器对比

「解析不对」的经典现场:本机 dig 出来的 IP 和预期不符,八成是 hosts 文件或内网 DNS 劫持——grep 域名 /etc/hosts 先查本地映射。

步骤 6:ssh 与 scp 远程操作

ssh 用户名@服务器IP                    # 交互登录
ssh -p 2222 deploy@10.0.0.5           # 非默认端口
ssh deploy@10.0.0.5 'uptime && df -h' # 非交互执行远程命令,批量巡检的基础

scp app.jar deploy@10.0.0.5:/opt/myapp/      # 推文件到远程
scp deploy@10.0.0.5:/var/log/app.log ./      # 从远程拉文件
scp -r config/ deploy@10.0.0.5:/opt/myapp/   # 递归推目录

ssh 主机 '命令' 是「批量巡检脚本」的原子能力:外层 for 循环节点列表,内层远程执行检查命令,第 12 课综合练习组装它。

步骤 7:组装一个接口巡检脚本

cat > health-check.sh << 'EOF'
#!/bin/bash
set -uo pipefail
URLS=(
  "http://localhost:8000/"
  "http://localhost:9999/"        # 故意放一个不存在的端口
)
for url in "${URLS[@]}"; do
  code=$(curl -s -m 3 -o /dev/null -w "%{http_code}" "$url" || echo "ERR")
  if [ "$code" = "200" ]; then
    echo "OK    $url"
  else
    echo "FAIL  $url  (code=$code)"
  fi
done
EOF
bash health-check.sh
# OK    http://localhost:8000/
# FAIL  http://localhost:9999/  (code=ERR)

注意这里用 set -uo pipefail 而没加 -e:因为 curl 失败恰恰是我们要采集的信息,不能让它中途退出——工具服务于目的。

讲清楚要点

  1. curl 排查接口问题的顺序:先 -i 看响应头有没有(连接层问题还是应用层问题),再换状态码区分 404/502/超时,最后 -v 看完整握手过程。-v 输出里能直接看到 TCP 建连、TLS、请求头三个阶段卡在哪。
  2. ss -tlnp 的输出要会读三样:监听地址(0.0.0.0 全网卡 / 127.0.0.1 仅本机)、端口、进程名+PID。Nginx 起来了但 ss 里没有 80/443 → 配置语法错或被占用,nginx -t 验证。
  3. TIME_WAIT 是正常的连接收尾状态,几千个不必慌;真正要警惕的是大量 CLOSE_WAIT——那是对端已关闭、我方应用没调 close,通常意味着代码里连接泄漏(HttpClient 没关、连接池配置错误)。
  4. 502 的本质是 Nginx 连不上后端:排查动作 = curl 后端健康接口 + ss -tlnp | grep 后端端口 + tail nginx error log。三步定位是「Nginx 挂了」还是「后端挂了」还是「网络不通」。
  5. 防火墙有两层:系统层 firewalld/iptables(sudo firewall-cmd --list-ports 或 sudo iptables -L -n),云层安全组在控制台配。本地 curl 通、外部不通,九成是这两层之一。
  6. ssh 免密是自动化的前置条件:ssh-keygen -t ed25519 生成密钥,ssh-copy-id 用户@主机 分发公钥,之后脚本里的 ssh/scp 不再要密码。生产密钥必须加 passphrase 存入 agent。

你可能会懵的地方

  • curl 返回 000 是什么意思? 连接根本没建立(拒绝、超时、DNS 失败),没有 HTTP 状态码可言。curl -v 看具体卡在哪一步。脚本里 000/ERR 要当独立分支处理,别和 404 混为一谈。

  • 127.0.0.1、0.0.0.0、localhost 有什么区别? 127.0.0.1 是回环地址(本机自己);0.0.0.0 是「所有网卡」(监听地址里出现=外部可访问;路由里出现=默认路由);localhost 是主机名,默认解析到 127.0.0.1。应用绑 127.0.0.1 时外部永远访问不了,改绑定 0.0.0.0 并配合防火墙。

  • ping 通但 curl 不通,为什么? ping 走 ICMP,curl 走 TCP。防火墙常放行 ICMP 拦截 TCP 端口。所以「ping 得通」只证明主机可达,不证明服务可用——排查要逐层来,不能跳步。

  • nc(netcat)什么时候用? 纯 TCP 探活:nc -zv 10.0.0.5 3306,验证 MySQL 端口通不通比 curl 直接(curl 是 HTTP 语义)。批量验端口段也方便:for p in 80 443 3306 6379; do nc -z -w1 本机IP $p && echo "$p 通" || echo "$p 不通"; done。

  • scp 和 rsync 怎么选? scp 简单直接,一次性传文件;rsync 增量传输(只传差异块)、支持断点续传和排除规则,大目录同步、日常备份用它:rsync -avz --exclude='logs/' config/ deploy@host:/opt/myapp/config/。

错法对照

错法问题正解
脚本里 curl 不加超时无响应接口把发布流水线挂死-m 5 --connect-timeout 2
拿 0.0.0.0 去请求它是监听通配不是目标地址请求用 127.0.0.1 或具体 IP
只 ping 通就认为服务正常ICMP 通≠TCP 端口通加 ss -tlnp + curl 验证
看到大量 TIME_WAIT 就以为出事正常短连接收尾状态警惕的应是 CLOSE_WAIT 堆积
scp 传目录漏 -r报 not a directory 或跳过scp -r,或改用 rsync -a

卡点急救

  1. connection refused:进程没起或没监听该端口。ss -tlnp | grep 端口 验证;没有输出就 ps -ef | grep 应用 看进程,都没有就去翻应用启动日志找崩溃原因。
  2. curl 卡住不动:目标 IP 不可达或防火墙丢包(不拒绝只吞)。Ctrl+C 后加 -m 5 --connect-timeout 2 重试;再查 ping 和云安全组。
  3. ssh 报 Permission denied (publickey):服务器未收录你的公钥或密钥权限不对。重新 ssh-copy-id;确认本机私钥 ~/.ssh/id_ed25519 权限是 600,服务器上 ~/.ssh 是 700。

面试常问

  • 线上接口 502,Nginx 报 connect() failed,你的排查步骤? ① ss -tlnp | grep 后端端口 看后端有没有监听;② curl -m 3 http://127.0.0.1:端口/actuator/health 直接打后端绕过 Nginx;③ ps -ef | grep java 确认进程;④ tail -n 100 nginx错误日志和后端日志 找启动失败/崩溃原因。结论通常是后端进程挂了或端口配错——能按层次说出验证命令就是好答案。

  • 怎么判断一台服务器的某个端口是否对外可访问? 在本机 ss -tlnp | grep 端口 确认监听且地址为 0.0.0.0;在另一台机器 nc -zv 服务器IP 端口 或 curl -m 3 服务器IP:端口 验证外部可达;不通再查 firewalld/iptables 与云安全组。三层验证:监听 → 系统防火墙 → 云层。

  • CLOSE_WAIT 大量堆积说明什么? 对端已关闭连接,本端应用迟迟没有调用 close(),一般是代码层连接泄漏:HttpClient/数据库连接用完未归还或未关闭、连接池 maxLifetime 配置不当。先 ss -tanp | grep CLOSE_WAIT 统计归属进程,再 review 对应代码的连接关闭逻辑,临时缓解可重启应用。

自测三问

  1. ss -tlnp 四个字母分别是什么含义?
  2. 用 curl 输出某接口的 HTTP 状态码和总耗时,命令怎么写?
  3. 0.0.0.0 作为监听地址和作为访问目标时,含义分别是什么?

小结一句话

网络排查是分层验证:dig 查解析、ping 查可达、ss 查监听、curl 查应用、防火墙查拦截——每层一条命令,502 就再也不是玄学。

延伸

  • curl 官方文档
  • 下一课:系统管理与编辑器——磁盘、内存、软件包,外加 vim 生存法则。
加载本节练习…
← 上一课进程与定时任务下一课 →系统管理与编辑器