「速通Shell」常用命令(中)——进程、网络与系统信息

0 阅读10分钟

上一篇我们聊了文件操作和文本处理,那是 shell 工程师日常使用频率最高的一组命令。这一篇换个主题,聊聊另外三块同样重要的内容:进程管理、网络工具、系统信息。

这三块是日常运维的另一半。写脚本时除了处理文件,你大概率还要跟运行中的程序打交道——查进程、查网络、查系统状态。掌握好这一篇的命令,你的 shell 脚本就能覆盖 90% 的运维场景。

一、三类工具的共同点

进程、网络、系统信息这三类命令看似不相关,其实有一个共同特点:它们都在"观察和控制运行中的系统"。跟上一篇的"操作静态文件"不同,这里的命令往往:

  • 输出的内容是动态变化的(每秒都在刷新)
  • 跨进程、跨主机、跨网络边界
  • 误用可能影响线上服务(kill 错进程、网络断连)

所以这一篇的命令要更谨慎地使用。我们按"观察 → 控制"的顺序来:先学怎么看,再学怎么动。

二、进程管理

进程是 shell 工程师打交道最多的实体。你的脚本启动后是一个进程,调用外部命令会创建子进程,部署的服务也是进程。理解进程的状态和它们之间的关系,是写出可靠脚本的基础。

2.1 ps:看一眼进程

ps 是 process status 的缩写,它把当前系统里的进程列出来。语法是 ps [options]

最常用的几个组合:

# 查看当前用户的所有进程
ps
​
# 查看所有进程(包括其他用户)
ps -ef
# 或者
ps aux
​
# 查找特定进程
ps -ef | grep nginx

ps -ef 和 ps aux 是两种主流写法,前者是 System V 风格,后者是 BSD 风格。两者的输出列不同,但都能用。日常推荐 ps -ef,跨平台兼容性好。

输出字段解读(以 ps -ef 为例):

UID    PID  PPID  C STIME TTY      STAT   TIME     CMD
root     1     0  0 822 ?        00:00:01 /sbin/init
root   123     1  0 822 ?        00:00:00 nginx: master process
  • UID:进程所有者
  • PID:进程 ID
  • PPID:父进程 ID
  • STAT:进程状态(R 运行、S 睡眠、Z 僵尸、T 停止等)
  • CMD:启动命令

几个实用的查询组合

# 按进程名过滤
ps -ef | grep -v grep | grep nginx
​
# 按用户过滤
ps -u www-data
​
# 按 PID 查详情
ps -p 1234 -o pid,ppid,cmd
​
# 自定义输出列
ps -eo pid,ppid,user,pcpu,pmem,cmd --sort=-pcpu | head

最后一行尤其常用——找出最占 CPU 的几个进程

2.2 top / htop:动态看

ps 是一次的快照,top 是动态刷新的"实时监控器"。

top                  # 启动 top,默认 3 秒刷新
top -p 1234          # 只监控指定 PID
top -u www-data      # 只监控指定用户
top -n 1             # 只刷新一次(适合脚本里用)

top 的输出分两部分:上半部分是系统整体(负载、CPU、内存),下半部分是进程列表。几个看重点:

  • load average:三个数字分别是 1 分钟、5 分钟、15 分钟的平均负载
  • %Cpu(s):用户态、内核态、空闲 CPU 占比
  • KiB Mem:总内存、已用、空闲、缓存

top 里几个交互命令

  • P:按 CPU 排序
  • M:按内存排序
  • k:kill 进程(输入 PID)
  • 1:展开多核 CPU
  • q:退出

htop 是 top 的升级版——支持鼠标、彩色、树形视图。如果有 htop 就用 htop,体验比 top 好太多。安装:apt install htopyum install htop

2.3 jobs / fg / bg:前后台切换

这是 shell 自己的进程管理,跟操作系统的进程管理是分开的。

# 启动一个后台任务
sleep 100 &
​
# 查看当前 shell 的后台任务
jobs
# 输出:[1]+ Running    sleep 100 &# 把后台任务切到前台
fg %1
​
# 把前台任务切到后台(先用 Ctrl+Z 暂停)
# 按 Ctrl+Z
bg %1

& 是"后台启动"。jobs 列出当前 shell 的后台任务(注意是当前 shell,子 shell 的任务看不到)。

关键概念:前台任务会占用终端,你按 Ctrl+C 它就死了。后台任务不占用终端,Ctrl+C 不会影响它。所以长时间运行的任务应该用 & 放后台

但放后台的任务在终端关闭时可能被 SIGHUP 杀掉——解决方案是 nohup,后面讲。

2.4 nohup:脱离终端

nohup long_running.sh &

nohup 让进程忽略 SIGHUP 信号——终端断开时不会被杀,& 让它在后台跑。这是"启动一个能跑很久的服务"的标准组合。

输出默认会写到 nohup.out,除非你重定向:

nohup long_running.sh > /var/log/myservice.log 2>&1 &

注意 nohup 不是万能的,它只处理 SIGHUP,不处理其他信号。真正的守护进程需要用 systemd 或专门的 daemon 工具

2.5 kill / pkill / killall:发信号

kill 的本意是"发信号",不是"杀进程"——只是发 TERM 信号是它的默认行为。前面信号那篇讲过细节,这里只讲实战用法。

# 发 TERM(默认,优雅退出)
kill 1234
​
# 发 KILL(强制,9 号信号)
kill -9 1234
​
# 发 HUP(重载配置,常见于 nginx/apache)
kill -HUP 1234
​
# 按名字杀
pkill nginx
​
# 强杀所有匹配
pkill -9 nginx
​
# 杀整个进程组(比如杀某个脚本启动的所有子进程)
kill -- -1234   # 注意负号

几个安全实践

  • 永远先 kill(默认 TERM),给进程 5-10 秒清理时间,再 kill -9
  • pkill 之前先用 pgrep 看看会杀哪些进程:pgrep nginx 先确认
  • 不要 pkill 名字太通用的进程(比如 pkill sh 会杀掉很多不相关的东西)

2.6 nice / renice:调整优先级

nice 调整进程优先级(niceness 值),范围是 -20 到 19。值越大优先级越低,越不抢CPU。普通用户只能调正值(降低优先级),root 可以调任何值。

# 启动时设置优先级
nice -n 19 long_running.sh &
​
# 调整已运行进程的优先级
renice -n 10 -p 1234

什么时候用:批量任务、定时任务、备份脚本等不影响主业务的进程,调高 nice 值让它们礼貌地跑。

三、网络工具

shell 工程师的另一大任务是跟网络打交道——调 API、传文件、查连接、查 DNS。这一节把最常用的网络工具过一遍。

3.1 ping:基本连通性

# 简单 ping
ping example.com
​
# 限制次数
ping -c 4 example.com
​
# 设置间隔
ping -i 0.5 example.com
​
# 不解析域名(纯 IP ping)
ping -n 8.8.8.8

ping 的实战用法

# 等待服务启动(轮询 + ping)
until ping -c 1 -W 1 myservice.local &>/dev/null; do
    sleep 1
done
echo "服务已就绪"

但注意 ping 不一定反映服务的真实状态,主机能 ping 通不代表端口能连上(防火墙可能禁 ICMP)。测试服务可用性用 curl 或 nc。

3.2 curl / wget:HTTP 客户端

curl 和 wget 都是 HTTP 客户端,但curl 更通用,wget 更专注下载。

# 简单 GET
curl https://example.com
​
# 跟随重定向
curl -L https://example.com
​
# 输出 HTTP 头
curl -I https://example.com
​
# POST 请求
curl -X POST -d 'name=alice&age=25' https://api.example.com/users
​
# JSON POST
curl -X POST -H 'Content-Type: application/json' \
    -d '{"name":"alice","age":25}' \
    https://api.example.com/users
​
# 携带 cookie
curl -b cookies.txt -c cookies.txt https://example.com
​
# 显示详细请求
curl -v https://example.com
​
# 下载文件
curl -O https://example.com/file.zip
curl -o myfile.zip https://example.com/file.zip

curl 的常用选项

  • -X:指定 HTTP 方法
  • -H:自定义 header
  • -d:请求体
  • -o:输出到文件
  • -O:保持远程文件名
  • -I:只显示响应头
  • -L:跟随重定向
  • -k:忽略证书错误(不推荐生产用)
  • -s:静默模式(不显示进度)
  • -v:详细模式(调试用)

curl 的几个实战组合

# 测试 API 健康
curl -sf https://api.example.com/health || echo "API 不健康"# 调 API 并解析 JSON(配合 jq)
curl -s https://api.example.com/users | jq '.[] | .name'# 下载并限速
curl --limit-rate 1M -O https://example.com/bigfile.zip
​
# 跟踪重定向
curl -L -o file.html https://bit.ly/shortlink

-f 是"失败时返回非零" 。配合 set -e 用,curl 失败时脚本会立即退出。这是 shell 脚本里调 API 的标准做法。

wget 跟 curl 的取舍:curl 功能更强、支持更多协议(FTP、SFTP、SMTP 等),wget 专注 HTTP 下载、递归下载更简单。日常 API 调用用 curl,批量下载用 wget。

3.3 ssh / scp / rsync:远程操作

ssh 是最常用的远程登录工具,scp 是基于 ssh 的文件传输,rsync 是更强大的同步工具。

# 登录远程
ssh user@host# 指定端口
ssh -p 2222 user@host# 执行远程命令
ssh user@host 'ls -la'# 拷贝文件到远程
scp file.txt user@host:/remote/path/# 从远程拷贝文件
scp user@host:/remote/file.txt ./
​
# 拷贝目录
scp -r dir/ user@host:/remote/path/

ssh 的几个实用技巧

# 免密码登录(用密钥)
ssh-keygen -t ed25519                 # 生成密钥
ssh-copy-id user@host                 # 上传公钥# SSH 配置文件(~/.ssh/config)
Host myserver
    HostName 192.168.1.100
    User alice
    Port 2222
    IdentityFile ~/.ssh/work_key
​
# 配置后直接用别名
ssh myserver
scp file.txt myserver:/tmp/

rsync 比 scp 强大得多——增量同步、保留权限、断点续传。

# 本地同步
rsync -av src/ dst/
​
# 远程同步
rsync -av -e ssh src/ user@host:/remote/path/# 删除目标里多余的文件
rsync -av --delete src/ dst/
​
# 排除某些文件
rsync -av --exclude='*.tmp' src/ dst/
​
# 模拟运行(看看会同步哪些文件,但不真做)
rsync -avn src/ dst/

rsync 的关键选项

  • -a:归档模式(保留所有属性,等于 -rlptgoD)
  • -v:详细输出
  • -z:传输时压缩
  • --progress:显示进度
  • --delete:删除目标端多余文件
  • -n:模拟运行(dry-run)

rsync 的经典用法

# 备份脚本(每天跑)
rsync -av --delete /data/ /backup/data/
​
# 部署到多台服务器
for host in server1 server2 server3; do
    rsync -az -e ssh ./app/ $host:/opt/app/
done

3.4 ss / netstat:网络连接

ss 是新一代的网络连接查看工具(替代 netstat)。netstat 在新系统上逐步被淘汰——如果系统有 ss 就用 ss。

# 查看所有 TCP 连接
ss -t
​
# 查看所有监听端口
ss -tlnp
​
# 查看所有 UDP 连接
ss -u
​
# 查看建立的连接
ss -t state established
​
# 按端口过滤
ss -tlnp 'sport = :80'# 统计各状态的连接数
ss -tan | awk '{print $1}' | sort | uniq -c

ss 跟 netstat 的输出差别:netstat 把"地址"和"端口"合成一列,ss 分开两列。机器可读性 ss 更好,awk 解析更简单。

3.5 dig / nslookup / host:DNS 查询

# 查询 A 记录
dig example.com
​
# 简短输出
dig +short example.com
​
# 查询特定记录类型
dig example.com MX
dig example.com TXT
​
# 指定 DNS 服务器
dig @8.8.8.8 example.com
​
# 反向 DNS(IP 查域名)
dig -x 8.8.8.8

host 是更简洁的版本,输出更友好:

host example.com
host 8.8.8.8

nslookup 是最老的,现在一般不推荐用。dig 输出的信息最全,是排查 DNS 问题时的首选。

3.6 nc / ncat:网络瑞士军刀

nc(netcat)是一个底层网络工具,可以读写 TCP/UDP 连接。调试网络问题时特别有用

# 监听端口(作为 server)
nc -l 12345
​
# 连接端口(作为 client)
nc example.com 80
​
# 端口扫描
nc -zv example.com 80-100
​
# 文件传输(简单的两端)
# 接收端
nc -l 12345 > file.txt
# 发送端
nc host 12345 < file.txt

nc 的实战用法

# 测试端口是否开放
nc -zv example.com 80
​
# 调试 HTTP 请求(手动发)
printf "GET / HTTP/1.0\r\nHost: example.com\r\n\r\n" | nc example.com 80
​
# 等待服务启动(比 ping 更靠谱)
until nc -z myservice 8080; do
    sleep 1
done

四、系统信息

最后一组命令是查系统状态——查内核、查内存、查磁盘、查用户。日常脚本里经常用这些做"环境检查"。

4.1 uname:系统信息

# 系统信息
uname -a
​
# 单独看内核
uname -r
​
# 单独看主机名
uname -n

4.2 hostname:主机名

hostname                # 显示主机名
hostname -I             # 显示所有 IP 地址
hostname -f             # 显示完整域名(FQDN)

4.3 date / uptime:时间信息

date                    # 当前时间
date +%Y-%m-%d          # 格式化输出
date +%s                # Unix 时间戳
date -d "2024-01-15"    # 解析字符串为日期
date -d "@1704067200"   # 时间戳转日期
date -u                 # UTC 时间
date -R                 # RFC 2822 格式uptime                  # 系统运行时间和负载

date 在脚本里的常见用法

# 日志文件加日期后缀
log_file="app_$(date +%Y%m%d).log"# 计算时间差
start=$(date +%s)
do_something
end=$(date +%s)
echo "耗时 $((end - start)) 秒"# 7 天前的时间
date -d "7 days ago" +%Y-%m-%d

4.4 who / whoami / id:用户信息

whoami                  # 当前用户名
id                      # 详细信息(UID、GID、组)
who                     # 登录的用户
w                       # 更详细的登录信息

id 在脚本里最常用——判断当前是不是 root:

if [ "$(id -u)" -ne 0 ]; then
    echo "请用 root 权限运行"
    exit 1
fi

4.5 free:内存

free                    # 内存使用情况
free -h                 # 人类可读
free -m                 # 以 MB 为单位
free -s 5               # 每 5 秒刷新

输出字段:total 总内存、used 已用、free 空闲、shared 共享、buff/cache 缓存、available 可用。注意 available 才是"真正能用的" ——buff/cache 算上才准。

4.6 df / du:磁盘

上一篇讲过 df 和 du 的基础用法,这里补充几个组合:

# 看磁盘 IO 统计
iostat
​
# 看文件系统类型
df -T
​
# 找出最大的 5 个文件
find /var -type f -exec du -h {} + | sort -rh | head -5
​
# 找出大于 1G 的文件
find / -type f -size +1G 2>/dev/null

4.7 lscpu / lsblk / lspci:硬件信息

lscpu                   # CPU 信息
lsblk                   # 块设备(磁盘)信息
lspci                   # PCI 设备
lsusb                   # USB 设备

这些命令在排查硬件问题时偶尔用到,日常脚本里用得不多

4.8 /proc 文件系统

Linux 把进程和内核信息暴露在 /proc 下——很多命令的输出其实就是从这里读的

# 当前进程信息
cat /proc/self/status
​
# CPU 信息
cat /proc/cpuinfo
​
# 内存信息
cat /proc/meminfo
​
# 系统启动时间
cat /proc/uptime
​
# 进程的命令行
cat /proc/1234/cmdline

脚本里读 /proc 比调用命令更高效——不用 fork 进程。比如判断系统启动时间:

uptime_seconds=$(awk '{print $1}' /proc/uptime)

五、总结

这一篇我们覆盖了另外三组常用命令:

  • 进程管理:ps、top、jobs、fg、bg、nohup、kill、pkill、nice
  • 网络工具:ping、curl、wget、ssh、scp、rsync、ss、dig、nc
  • 系统信息:uname、hostname、date、uptime、who、id、free、df

跟上一篇一样,重点不是记住每个命令的参数,而是知道什么时候用哪个、怎么组合。

下一篇是这个系列的最后一部分——讲归档、压缩、权限、用户、还有几个进阶工具(xargs、tee、cron、screen/tmux)。这是 shell 工具箱的最后一组拼图,写完这三篇,你对 shell 日常命令的掌握就完整了。