Files

104 lines
4.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: devops.linux.commands
title: 常用命令:文件、文本处理、进程、端口、权限、systemd
type: lesson
domain: devops
stack: [linux]
tags: [grep, awk, ps, ss, chmod, systemd, journalctl]
level: basic
est_hours: 3
related: [devops.linux.troubleshooting, devops.linux.interview]
week: [14]
order: 1
---
# 常用命令:文件、文本处理、进程、端口、权限、systemd
## 解释说明
| 类别 | 命令 | 常用写法 |
| --- | --- | --- |
| 文件 | `ls` `cd` `cp` `mv` `rm` `find` | `find /var/log -name "*.log" -mtime +7`(7 天前的日志) |
| 查看 | `cat` `less` `head` `tail` | `tail -f app.log`(实时跟踪)、`tail -n 200 app.log` |
| 文本 | `grep` `awk` `sort` `uniq` `wc` `sed` | `grep -n "ERROR" app.log`、`awk '{print $1}'`(取第一列) |
| 进程 | `ps` `top` / `htop` `kill` `pgrep` | `ps -ef | grep api`、`kill -15 PID`(先礼后兵,最后才 `-9`) |
| 端口 / 网络 | `ss` `curl` `ping` `dig` | `ss -lntp`(谁在监听哪个端口)、`curl -v http://127.0.0.1:8080/healthz` |
| 磁盘 | `df` `du` | `df -h`、`du -sh /var/log/* | sort -h` |
| 权限 | `chmod` `chown` `sudo` | `chmod 600 .env`、`chown app:app /srv/app -R` |
| 服务 | `systemctl` `journalctl` | `systemctl status api`、`journalctl -u api -f` |
| 传输 | `scp` `rsync` `ssh` | `rsync -avz dist/ user@host:/srv/web/` |
**权限**:`rwx` 分别对应 4、2、1;`chmod 755` = 所有者 rwx、组和其他人 r-x。密钥文件用 `600`。服务不要用 root 运行,单独建一个用户。
**管道和重定向**:`|` 把前一个命令的输出交给后一个;`>` 覆盖写文件、`>>` 追加;`2>&1` 把错误输出也合并进来。
**systemd**:把程序注册成系统服务——开机自启、崩溃自动重启、日志统一交给 journald。
## 案例
- 统计访问日志里请求最多的 10 个 IP:`awk '{print $1}' access.log | sort | uniq -c | sort -rn | head`。
- 统计 5xx 的数量:`awk '$9 >= 500' access.log | wc -l`(combined 格式第 9 列是状态码)。
- 找出占用 8080 端口的进程:`ss -lntp | grep 8080`。
- Go API 部署成 systemd 服务,崩溃 3 秒后自动重启,日志用 `journalctl -u api` 查看。
## 代码示例
文本处理组合(可以对 [examples/log-analysis/sample_access.log](examples/log-analysis/sample_access.log) 直接运行):
```bash
# 状态码分布
awk '{print $9}' sample_access.log | sort | uniq -c | sort -rn
# 请求最多的 IP
awk '{print $1}' sample_access.log | sort | uniq -c | sort -rn | head -n 3
# 耗时超过 1 秒的请求(最后一列是 $request_time)
awk '$NF > 1 {print $NF, $7}' sample_access.log | sort -rn
# 某个时间段的错误
grep '23/Oct/2026:10:00' sample_access.log | grep -E '" 5[0-9]{2} '
```
同样的分析用 Python 写成脚本:[examples/log-analysis/analyze.py](examples/log-analysis/analyze.py)。
Go 服务的 systemd 单元文件 `/etc/systemd/system/api.service`:
```ini
[Unit]
Description=Order API
After=network-online.target
Wants=network-online.target
[Service]
User=app
Group=app
WorkingDirectory=/srv/api
EnvironmentFile=/srv/api/.env
ExecStart=/srv/api/bin/api
Restart=on-failure
RestartSec=3
# 停止时先发 SIGTERM,等 15 秒再强杀
TimeoutStopSec=15
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
```
```bash
sudo systemctl daemon-reload # 修改单元文件后必须执行
sudo systemctl enable --now api # 开机自启并立即启动
systemctl status api
journalctl -u api -f --since "10 min ago"
```
## 易错点
- **`kill -9` 当默认**:进程来不及清理(关闭连接、写完文件)。先 `kill`(SIGTERM),等不及再 `-9`。
- **`rm -rf $DIR/` 变量为空**:变成 `rm -rf /`。脚本里加 `set -u`,或写 `"${DIR:?}"/`。
- **删除正在被写的大日志文件**:空间不释放(进程还持有文件句柄)。用 `: > app.log` 清空,或者重启进程;配置 logrotate。
- **`chmod 777` 解决权限问题**:安全隐患。找出正确的用户和组。
- **修改 systemd 单元文件后忘了 `daemon-reload`**:改动不生效。
- **在服务器上直接 `vim` 改线上配置不留记录**:配置纳入 Git,通过部署流程发布。
## 面试常问
见 [Linux 面试题](interview.md):查端口占用、查日志、统计、软链接和硬链接、进程信号。