欢迎光临
我们一直在努力

从零玩转 Linux 命令行:一位后端菜鸟的硬核笔记

🐧 从零玩转 Linux 命令行:一位后端菜鸟的 9 天硬核笔记

最近正在系统性地补计算机基础,第一块啃的是 Linux 命令行。
虽然是后端开发,日常也跟服务器打交道,但以前都是"知其然而不知其所以然"。
这一周从 FHS 目录结构开始,到系统巡检脚本收尾,花了 9 天把 Linux 基础过了一遍。
下文按"命令 → 说明 → 执行结果"来组织,方便对照学习。


一、Linux 的目录结构

第一次打开终端敲 ls -la /,面对那一大堆目录,我当时是懵的:/bin、/sbin、/usr、/etc、/var、/tmp、/proc、/dev……这都什么跟什么?

其实这些目录的摆放有标准叫 FHS(Filesystem Hierarchy Standard)。Linux 圈子商量好了——大家按规矩来,某些目录放某些东西。这样换发行版也不用重新学。

根目录结构

ls -la /

以长格式 + 隐藏文件方式列出根目录下所有内容。这是你认识 Linux 的第一步。

$ ls -la /
total 2044520
drwxr-xr-x 20 root root 4096 Jun 8 10:00 .
lrwxrwxrwx 1 root root 7 Jun 1 2024 bin –> usr/bin
drwxr-xr-x 4 root root 4096 Jun 1 2024 boot
drwxr-xr-x 144 root root 12288 Jun 8 10:00 etc
drwxr-xr-x 3 root root 4096 Jun 1 2024 home
dr-xr-xr-x 289 root root 0 Jun 8 09:29 proc
drwxrwxrwt 23 root root 4096 Jun 8 11:00 tmp
drwxr-xr-x 11 root root 4096 Jun 1 2024 usr
drwxr-xr-x 13 root root 4096 Jun 1 2024 var

注意 bin、sbin、lib 前面有个 l(链接符号),说明它们是指向 /usr/bin 等目录的软链接。这是新发行版的趋势——把根目录下的东西合并到 /usr,减少混乱。

各目录的职责:

目录放什么一句话理解
/bin /sbin 系统命令 启动就得用的,如 ls、fdisk
/usr 用户软件 相当于 Windows 的 Program Files
/etc 配置文件 Nginx、MySQL 配置都在这
/var 可变数据 日志在 /var/log
/tmp 临时文件 重启就清空
/proc /sys 虚拟文件系统 内核实时信息,不占磁盘
/dev 设备文件 硬件也是文件
/home 用户家目录 各用户自己的空间

/proc 和 /sys 很特别——它们不占用磁盘空间,是内核运行时映射出来的。你读它们等于在读内核的实时状态。这种"一切皆文件"的设计是 Unix 哲学的核心理念。

查看文件信息

ls -lh

以长格式 + 人类易读大小列出文件。-l 显示权限/所有者/大小/时间,-h 把字节数转成 K/M/G。

$ ls -lh
total 24M
-rw-r–r– 1 hengjun devops 1.2K Jun 8 10:00 app.log
-rw-r–r– 1 hengjun devops 24M Jun 7 12:00 dump.sql

ls -ltr

按修改时间倒序排列(旧的在上)。查日志时按时间顺序追踪问题很好用。

ls -lS

按文件大小从大到小排列。

stat file

查看文件的完整元数据——Inode(唯一编号)、Links(硬链接数)、三个时间戳。

$ stat app.log
File: app.log
Size: 245890 Inode: 1234567 Links: 1
Access: 2024-06-08 10:00:00
Modify: 2024-06-08 11:30:00
Change: 2024-06-08 11:30:00

内容没变但 Change 时间更新了?说明有人动过权限。

file file

根据文件头的"魔数"判断真实类型。Linux 不看后缀名。

$ file app.jar
app.jar: Java archive data (ZIP)
$ file logo.png
logo.png: PNG image data, 800 x 600, 8-bit/color RGBA

通配符

ls *.log

* 匹配任意多个字符,列出所有 .log 结尾的文件。

ls ?.txt

? 匹配恰好一个字符。a.txt 能匹配,long.txt 不行。

ls file[123].txt

[] 匹配括号内的某个字符。

mkdir -p src/{main,test}/{java,resources}

花括号批量展开,一键创建 4 个目录。

帮助系统

man ls

打开 ls 的完整参考手册(按 q 退出)。

ls –help

快速查看 ls 的用法摘要。

which ls

查看 ls 命令的绝对路径。

type ls

查看 ls 是否为别名。

whereis ls

连源码位置和 man 手册位置一起显示。


二、文件操作命令

创建和删除

touch file

创建空文件。文件已存在则刷新其时间戳。

mkdir -p a/b/c

创建多级目录,中间目录不存在就自动创建,不会报错。

rm -rf dir/

递归强制删除目录。没有回收站,敲之前一定 ls 确认路径!

dd if=/dev/zero of=test bs=1M count=100

底层数据拷贝工具,常用来创建指定大小文件或测磁盘速度。

$ dd if=/dev/zero of=testfile bs=1M count=100
100+0 records in, 100+0 records out
104857600 bytes (105 MB) copied, 0.345 s, 303 MB/s

复制和移动

cp source dest

复制文件到目标位置。

cp -r src/ dst/

递归复制整个目录。

cp -a src/ dst/

完整复制(保留权限、时间戳、软链接),相当于完整克隆。

cp -p src dst

保留原文件的修改时间。

$ cp -p source.txt dest.txt
$ ls -l source.txt dest.txt
-rw-r–r– 1 hengjun devops 456 Jun 8 10:00 source.txt
-rw-r–r– 1 hengjun devops 456 Jun 8 10:00 dest.txt # 时间保留了!

mv src dst

移动或重命名文件。Linux 里"重命名"本质就是移动。

权限管理——先搞懂基本概念

在 Linux 里,每个文件都有三组权限,分别针对三种角色:

角色代号含义
u user 文件所有者(你是这个文件的主人)
g group 所属组(和你在同一个团队的人)
o other 其他人(既不是主人也不在团队里的人)

每组权限都有三种操作:

权限代号对文件对目录
r 4 读文件内容 列出目录下的文件列表
w 2 修改文件内容 在目录里增删文件
x 1 执行文件(脚本/程序) 进入目录(cd 进去)

三种角色 × 三种权限,用 9 个字符表示。看一个实际的例子:

$ ls -l script.sh
-rwxr-xr– 1 hengjun devops 1234 Jun 8 10:00 script.sh
# ↑——— 权限位,拆开来看:
# – (文件类型)
# rwx (所有者 u:可读可写可执行)
# r-x (所属组 g:可读可执行,不能写)
# r– (其他人 o:只能读)

第一位的 – 是文件类型,常见的还有 d(目录)、l(链接)。后面九位每三位一组,分别是 u、g、o 的权限,每组按 rwx 顺序排列,有权限就写字母,没有就写 -。


修改权限有两种方式,理解透了才能随手写出正确的命令。

方式一:符号模式——用字母表达,直观好懂

格式:chmod 角色 操作 权限 文件

角色含义操作含义
u 所有者 + 加上某权限
g 所属组 去掉某权限
o 其他人 = 设为指定的权限(覆盖之前的)
a 全部三种角色

# 给 script.sh 的所有者(u)加(+)执行权限(x)
$ chmod u+x script.sh

# 去掉所属组(g)的写权限(w)
$ chmod g-w app.log

# 把其他人(o)的权限设(=)为只读(r)
$ chmod o=r notes.txt

# 一次性设置多组:所有者全部权限,组给读+执行,其他人不给任何权限
$ chmod u=rwx,g=rx,o= notes.txt

方式二:数字模式——基于权限编码,写着快

每种权限对应一个数字:r=4、w=2、x=1。把三个数字加起来,就得到这组权限的编码。

r + w + x = 4 + 2 + 1 = 7
r + x = 4 + 0 + 1 = 5
r = 4 + 0 + 0 = 4

然后三个数字分别代表 u、g、o 的权限:

# 755 = 所有者7(rwx) + 组5(r-x) + 其他人5(r-x)
$ chmod 755 script.sh
$ ls -l script.sh
-rwxr-xr-x 1 hengjun devops 123 Jun 8 10:00 script.sh

# 644 = 所有者6(rw-) + 组4(r–) + 其他人4(r–)
$ chmod 644 app.log
$ ls -l app.log
-rw-r–r– 1 hengjun devops 1.2K Jun 8 10:00 app.log

# 600 = 所有者6(rw-) + 组0(—) + 其他人0(—)
$ chmod 600 id_rsa
$ ls -l id_rsa
-rw——- 1 hengjun devops 1679 Jun 1 2024 id_rsa

常见的权限组合:

数字权限适用场景
755 rwxr-xr-x 可执行文件、目录(最常见的可执行权限)
644 rw-r–r– 普通文件(最常见的文件权限)
600 rw——- SSH 私钥、配置文件(只有自己能看)
700 rwx—— 私人脚本(只有自己能执行)
777 rwxrwxrwx 不推荐——所有用户都能改,安全隐患

特别注意:SSH 私钥必须设成 600(rw——-),否则 SSH 会直接拒绝使用,提示 Permissions 0644 for 'id_rsa' are too open. 这是为了阻止其他用户私钥。

chown user:group file

修改文件的所有者和所属组。user 是新的所有者,group 是新的所属组。

# 把 file.txt 的所有者设为 zhangsan
$ sudo chown zhangsan file.txt

# 同时修改所有者和组
$ sudo chown zhangsan:devops file.txt

# 递归修改整个目录
$ sudo chown -R zhangsan:devops /opt/app/

chgrp group file

只修改文件的所属组,不改所有者。

umask

查看或设置"默认权限掩码"。为什么新创建的文件自动就是 644,目录就是 755?因为 umask 在背后起作用。

$ umask
0022

umask 的计算规则:最终权限 = 最大权限 – umask。文件的"最大权限"是 666(因为文件默认不给执行权限),目录的最大权限是 777。

umask=022 时:
文件:666 – 022 = 644(rw-r–r–)
目录:777 – 022 = 755(rwxr-xr-x)

umask=027 时(更安全):
文件:666 – 027 = 640(rw-r—–)
目录:777 – 027 = 750(rwxr-x—)

特殊权限

三种特殊权限挂在普通权限之上,用的场景特定,但遇到了要认识。

chmod u+s myapp

SUID(Set User ID)。设置了 SUID 的可执行文件,任何人执行它时都临时获得文件所有者的身份。最经典的例子是 /usr/bin/passwd:

$ ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 68208 Jun 1 2024 /usr/bin/passwd
# ^ 注意:所有者的 x 变成了 s

普通用户改密码时,需要写入 /etc/shadow 文件,但这个文件属于 root,普通用户本来没有权限写。passwd 设置了 SUID,所以普通用户执行它时就临时"变身"成 root,改完密码就退回去。

chmod g+s /shared/dir

SGID(Set Group ID)。对目录设置 SGID 后,在该目录下新建的文件自动继承目录的所属组。团队协作时特别有用——大家创建一个共享目录,设置 SGID 后,所有成员在里面创建的文件都属于同一个组,不需要每个人手动 chgrp。

$ sudo mkdir /shared/project
$ sudo chgrp devops /shared/project
$ sudo chmod g+s /shared/project
$ ls -ld /shared/project
drwxrwsr-x 2 root devops 4096 Jun 8 10:00 /shared/project
# ^ 组的 x 变成了 s

chmod +t /tmp

Sticky Bit。设置了 Sticky Bit 的目录,任何用户都可以写文件,但只能删除自己的文件。/tmp 就是最典型的例子——任何人都能在这里创建临时文件,但不能删别人的文件。

$ ls -ld /tmp
drwxrwxrwt 23 root root 4096 Jun 8 11:00 /tmp/
# ^ 其他人的 x 变成了 t

硬链接和软链接

这两个概念新手很容易搞混,我用大白话解释一下。

先想一个问题:Linux 里存一个文件,到底需要几样东西?

答案是两样:①文件内容本身(就是那一堆数据),②一个"名字标签"指向这份数据。这个"名字标签"在 Linux 里就叫"文件名",一个文件内容可以有好几个名字标签。

打个比方:你家小区里住了个叫"张三"的人。硬链接和软链接的区别就像是:

硬链接 = 张三有两个外号,“三哥"和"阿三”。不管叫哪个名字,找的都是同一个人。你把"三哥"这个名字划掉了(删了),张三还在,别人叫"阿三"照样能找到他。

软链接 = 墙上贴了张纸条写着"张三家在 3 单元 201"。你顺着纸条能找到他家。但如果张三搬走了(原文件删了),纸条还在但人没了,你就找不到了。

来看实际操作:

ln original.txt hardlink.txt

创建硬链接——相当于给同一份文件内容起了另一个名字。两个名字指向同一份数据,改一个另一个也跟着变。

ln -s original.txt softlink.txt

创建软链接(符号链接)——相当于创建一个快捷方式,里面只记了"original.txt 这个路径"。原文件删了,快捷方式就废了。

# 先创建一个原始文件
$ echo "Hello World" > original.txt

# 分别创建硬链接和软链接
$ ln original.txt hardlink.txt
$ ln -s original.txt softlink.txt

# 看看效果
$ ls -l
-rw-r–r– 2 hengjun devops 12 Jun 8 10:00 original.txt
-rw-r–r– 2 hengjun devops 12 Jun 8 10:00 hardlink.txt
lrwxrwxrwx 1 hengjun devops 12 Jun 8 10:00 softlink.txt –> original.txt
# ↑ 看到了吗?
# 软链接会显示一个箭头 -> 指向它"引用的文件"
# 硬链接和原文件一模一样,光看 ls 分不出来

# 关键实验:删掉原文件
$ rm original.txt

# 硬链接还能用!
$ cat hardlink.txt
Hello World

# 软链接废了!
$ cat softlink.txt
cat: softlink.txt: No such file or directory

这就很清楚了——硬链接是"另一个名字",软链接是"指向那个名字的牌子"。牌子指向的名字被删了,牌子就没用了。

什么时候用哪个?

场景用哪个为什么
给一个文件起多个名字 硬链接 省空间,两个名字指向同一份数据
跨文件系统链接 软链接 ✅ 硬链接不能跨文件系统
链接目录 软链接 ✅ 硬链接不能链接目录
做个快捷方式方便访问 软链接 ✅ 比如把 /var/log/nginx/access.log 软链接到 ~/logs/
删其中一个不影响另一个 硬链接 ✅ 删一个名字,数据还在

实际工作中,软链接用得比硬链接多得多。最常见的用法:部署新版本的时候,创建一个 current -> v2.0 的软链接,回滚时改成 current -> v1.0,这就是很多部署工具(如 Capistrano)的原理。


三、文本查看与搜索

做后端开发的,查日志占日常工作的很大一部分。

文件浏览

nl file

带行号输出文件内容。

head -n 50 file

查看文件前 50 行。

tail -n 100 file

查看文件最后 100 行。

tail -f file

实时追踪文件新写入的内容。排查线上问题的头号神器。

tail -f app.log | grep ERROR

只显示错误日志的实时流,干净利落。

less file

分页查看文件。按 / 搜索关键字、n 跳到下一个、g/G 到首尾、q 退出。

grep 基础搜索

grep "pattern" file

找出文件中所有包含 pattern 的行。

$ grep "ERROR" app.log
2024-06-08 10:00:01.567 ERROR PaymentService – 支付超时: 订单 98765
2024-06-08 10:00:02.001 ERROR PaymentService – 余额不足: 用户 12345

grep -v "pattern" file

反向匹配——排除某些"噪音"日志。

grep -c "pattern" file

只统计匹配数量,适合脚本中做告警判断。

$ grep -c "ERROR" app.log
3

grep -i "pattern" file

忽略大小写搜索。

grep -n "pattern" file

显示匹配行号。

grep 上下文搜索

grep -C 5 "pattern" file

显示匹配行前后各 5 行。排查问题时几乎必用——只看单独一行 ERROR 信息不够。

$ grep -C 1 "余额不足" app.log
2024-06-08 10:00:01.567 ERROR PaymentService – 支付超时: 订单 98765
2024-06-08 10:00:02.001 ERROR PaymentService – 余额不足: 用户 12345
2024-06-08 10:00:02.345 INFO PaymentService – 用户 12345 余额查询

grep -A 20 "Exception" file

显示匹配行后面 20 行,看 Java 异常堆栈够用了。

grep -B 5 "ERROR" file

显示匹配行前面 5 行。

grep 递归和正则

grep -r "TODO" src/

在目录中递归搜索。

grep -r –include="*.java" "FIXME" src/

只搜 Java 文件。

grep -r -l "BeanUtils" src/

只输出匹配的文件名。

grep -E "pattern" file

使用扩展正则表达式。

grep -oP "pattern" file

使用 Perl 风格正则 + 只输出匹配的部分。

$ grep -oP "订单 \\d+" app.log
订单 98765
订单 98766


四、管道与文本处理

单个命令能力有限,用 | 把命令串起来就能做出强大的数据处理流水线。

排序和去重

sort -n file

按数字大小排序。不加 -n 按字母序,会把 11 排在 2 前面。

sort -rn file

数字倒序排。

sort -k2 -t: file

按第二列排序、冒号分隔。

sort -u file

排序加去重。

uniq -c file

统计每行出现次数。重点:必须先 sort,因为 uniq 只能去重相邻的行。

$ sort ips.txt | uniq -c
4 192.168.1.1
1 192.168.1.2
1 192.168.1.3

数据裁剪和转换

cut -d',' -f1,3 file

按分隔符裁剪列。

tr 'a-z' 'A-Z'

字符替换——小写转大写。

tr -d '\\r' < win.txt > unix.txt

删除 Windows 回车符。

管道分叉

tee

把数据同时写到文件和屏幕。

$ cat access.log | grep "ERROR" | tee errors.txt | wc -l
42
# 屏幕显示 42,errors.txt 存了完整的 42 行错误日志

管道组合实战

cat access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -10

统计日志中访问最多的 10 个 IP。

$ cat access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -5
4823 192.168.1.100
1209 10.0.0.55
876 203.0.113.42

最上面的 IP 远超其他,很可能是爬虫或攻击。

du -sh /* | sort -rh | head -5

找出占用磁盘最大的 5 个目录。

$ du -sh /* | sort -rh | head -5
4.2G /usr
1.8G /var
456M /opt

ss -tan | awk '{print $1}' | sort | uniq -c | sort -rn

查看 TCP 连接状态分布。

$ ss -tan | awk '{print $1}' | sort | uniq -c | sort -rn
245 ESTAB
32 TIME-WAIT # 太多说明短连接频繁
8 LISTEN
5 CLOSE-WAIT # 程序没正确关闭连接才会出现

重定向

echo "Hello" > file

覆盖写入文件。

echo "World" >> file

追加写入文件。

ls /nonexistent 2> error.log

重定向标准错误(文件描述符 2)到文件。

nohup java -jar app.jar > app.log 2>&1 &

生产环境部署的经典写法:nohup 忽略退出终端信号,> app.log 标准输出写日志,2>&1 错误输出也写进同一日志,& 后台运行。

command > /dev/null 2>&1

完全丢弃所有输出。/dev/null 是 Linux 的"黑洞"。


五、进程管理

进程查看

ps aux

列出所有进程的快照。

$ ps aux | head -3
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.4 168352 11732 ? Ss Jun08 0:23 /sbin/init
hengjun 1234 2.3 8.5 4281592 245680 ? Sl Jun08 23:45 java -jar app.jar

PID 是进程 ID,%CPU 是单核占比(超 100% 说明多线程),RSS 是实际物理内存(以这个为准)。STAT 中 R 运行中、S 休眠、D 不可中断(大量 D 说明磁盘瓶颈)、Z 僵尸(说明有 Bug)。

ps aux | grep java

快速找 Java 进程的 PID。

ps -T -p 1234

查看进程 1234 内的所有线程。

top

实时监控面板,每 3 秒刷新。按 P 按 CPU 排序,M 按内存排序,1 展开各 CPU 核心,H 切线程模式。

$ top -bn1 | head -3
top11:02:34 up 2 days, load average: 0.08, 0.12, 0.10
%Cpu(s): 2.3 us, 0.5 sy, 0.2 wa

load average 超过 CPU 核心数说明 CPU 不够用。wa 是等待 IO 占比,持续偏高说明磁盘是瓶颈。

进程控制

kill -15 PID

发 SIGTERM(优雅终止)。进程可以捕获信号做清理——关闭连接、刷新缓冲区。优先使用。

kill -9 PID

发 SIGKILL(强制杀死)。进程没机会做清理,可能导致数据丢失。不能上来就用。 正确流程:先 -15 尝试优雅关闭,不行再 -15,最后无奈才 -9。

kill -3 PID

发 SIGQUIT——不杀进程,只让 Java 输出线程 dump(排查死锁的黄金证据)。

nohup cmd &

在后台运行进程,退出终端也不终止。

Ctrl+Z → bg → fg

前后台切换:Ctrl+Z 暂停,bg 放后台继续,fg 拉回前台,jobs 查看后台任务。

进程优先级

nice -n 10 ./cmd

以低优先级启动(nice 值越高越谦让,范围 -20~19,默认 0)。

renice -n 5 -p PID

运行时调整优先级。普通用户只能调高 nice 值(更谦让),不能调低。


六、网络工具与包管理

网络排查四步走

ping -c 4 host

看机器通不通。看两个指标:丢包率和延迟。

$ ping -c 4 baidu.com
64 bytes from 39.156.66.10: icmp_seq=1 ttl=128 time=12.3 ms
4 packets transmitted, 4 received, 0% packet loss

0 丢包说明网络基本正常。ping 不通先查网线和 IP 配置。

nc -zv host port

看端口开没开。nc(netcat)比 telnet 更轻量。

$ nc -zv 192.168.1.100 3306
Connection to 192.168.1.100 3306 port [tcp/mysql] succeeded!

nc -zv -w 3 host 1-1000

扫描 1-1000 端口。

dig host +short

看域名解析。解析错了啥都连不上。

$ dig baidu.com +short
39.156.66.10

ss -tlnp

看本地监听端口。-t TCP、-l 只显示监听、-n 不解析服务名、-p 显示进程。

$ ss -tlnp
LISTEN 0 128 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=2345))

curl

curl url

发送 GET 请求。

curl -X POST -H "Content-Type: application/json" -d '{}' url

发送 POST 请求。

curl -v url

查看完整交互过程——DNS、TCP 握手、TLS 握手、请求头、响应头,调试必用。

curl -w "format" -o /dev/null -s url

测量接口各阶段耗时。一行命令定位瓶颈——网络慢还是服务慢?

$ curl -w "DNS:%{time_namelookup}s 业务处理:%{time_starttransfer}s 总耗时:%{time_total}s\\n" \\
-o /dev/null -s https://api.example.com/endpoint

DNS:0.003s 业务处理:0.234s 总耗时:0.298s

curl -I url

只看响应头。

curl -o file -L url

下载文件并跟随重定向。

包管理

sudo apt install -y nginx

Debian/Ubuntu 系列安装软件。

sudo apt update

刷新软件源缓存(安装前先执行)。

sudo apt remove nginx

卸载软件。

sudo yum install nginx

CentOS/RHEL 系列安装软件。

sudo dpkg -i package.deb

本地安装 .deb 包。

sudo rpm -ivh package.rpm

本地安装 .rpm 包。


七、systemd 与 SSH

systemd——管理服务

systemctl start nginx

启动服务。

systemctl stop nginx

停止服务。

systemctl restart nginx

重启服务。

systemctl reload nginx

重载配置(不中断服务)。

systemctl status nginx

查看服务状态。看 Active 行——active (running) 正常,inactive (dead) 已停止,failed 启动失败。

$ systemctl status nginx
● nginx.service – A high performance web server
Active: active (running) since Sat 2024-06-08 10:00:01 CST

systemctl enable nginx

设置开机自启。

systemctl disable nginx

取消开机自启。

systemd——查看日志

journalctl -u myapp -f -n 100

查看 myapp 服务的日志。-f 实时追踪,-n 100 最近 100 行。

systemd——注册服务

编辑 /etc/systemd/system/myapp.service,将应用注册为系统服务:

[Unit]
Description=我的应用
After=network.target mysqld.service

[Service]
ExecStart=/usr/bin/java -jar /opt/app.jar
Restart=on-failure
RestartSec=10
StartLimitBurst=5

[Install]
WantedBy=multi-user.target

systemctl daemon-reload 重载配置,systemctl enable myapp 开机自启,systemctl start myapp 启动。

定时任务

crontab -e

编辑定时任务。

crontab -l

查看定时任务。

格式:分 时 日 月 周 命令

# 每天凌晨 3 点备份
0 3 * * * /opt/scripts/backup.sh

# 每 10 分钟检查健康状态
*/10 * * * * /opt/scripts/healthcheck.sh

注意 crontab 的环境变量和终端不一样,脚本中用到的 JAVA_HOME 要自己在脚本里设。

SSH

ssh-keygen -t ed25519 -C "you@company.com"

生成密钥对。ed25519 比 RSA 更快更安全。

ssh-copy-id user@server

把公钥复制到服务器,之后就不用输密码了。

ssh myserver

使用 ~/.ssh/config 中配置的别名登录:

Host myserver
HostName 192.168.1.100
User ubuntu
Port 2222

scp file user@host:/path/

安全复制文件到远程。

rsync -avz src/ dst/

增量同步——只传变化的部分。

# 第一次:全量传
$ rsync -avz logs/ backup@nas:/backup/logs/
sent 12.34M bytes

# 第二次(无变化):只传元数据
$ rsync -avz logs/ backup@nas:/backup/logs/
sent 2.34K bytes

ssh -L 3307:127.0.0.1:3306 user@server

本地端口转发——把本地 3307 映射到远程的 3306。然后 mysql -h 127.0.0.1 -P 3307 就能连远程数据库了,全程加密。


八、用户权限与归档压缩

用户管理

sudo useradd -m -s /bin/bash zhangsan

创建用户。-m 创建家目录,-s 指定 shell。

sudo passwd zhangsan

设置密码。

sudo userdel -r zhangsan

删除用户及家目录。

sudo usermod -aG docker zhangsan

把用户追加到 docker 组。-aG 是追加,不是覆盖(漏了 -a 会踢出其他组)。

sudo visudo

配置 /etc/sudoers。必须用 visudo,不能直接编辑,语法错了 sudo 全崩。

zhangsan ALL=(ALL) ALL
%devops ALL=(ALL) ALL
deploy ALL=(ALL) /usr/bin/systemctl restart myapp

归档压缩

tar -czf archive.tar.gz /path/

打包 + gzip 压缩。

tar -xzf archive.tar.gz -C /dir/

解压到指定目录。

tar -tzf archive.tar.gz

查看包内容(不解压)。

tar -cjf archive.tar.bz2 /path/

bzip2 格式——压缩率更高但慢不少。

tar -cJf archive.tar.xz /path/

xz 格式——压缩率最高但最慢。日常用 gzip 就够了。

zip -r archive.zip /path/

zip 压缩。

unzip archive.zip -d /dir/

zip 解压。

环境变量

export JAVA_HOME=/usr/lib/jvm/java-21

设置环境变量(仅当前 shell 有效)。

echo 'export JAVA_HOME=/usr/lib/jvm/java-21' >> ~/.bashrc && source ~/.bashrc

永久设置。~/.bashrc 每次打开终端加载,source 让变化立即生效。

echo $PATH

查看命令搜索路径。

env

查看所有环境变量。


九、综合实战

练习一:日志分析

网站变慢了,从日志里找线索:

# 哪个 IP 访问最多?
$ cat access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -5
8923 192.168.1.100
56 203.0.113.42

# 每小时请求分布
$ cat access.log | awk '{print $4}' | cut -d' ' -f1 | uniq -c
1203 08/Jun/2024:10
234 08/Jun/2024:04 # 凌晨还有大量请求?

凌晨请求骤增——要么爬虫要么国外用户,有了排查方向。

练习二:系统巡检脚本

#!/bin/bash
echo "=== 系统巡检 $(date) ==="
uptime
free -h | grep Mem | awk '{print "内存已用:" $3 "/" $2}'
df -h | awk 'NR>1 && int($5)>80 {print "⚠️ 磁盘满了:" $1, $5}'
for p in nginx mysql; do
pgrep -x "$p" > /dev/null && echo "✅ $p 运行中" || echo "❌ $p 未运行"
done

$ bash healthcheck.sh
=== 系统巡检 2024-06-08 11:00 ===
11:00 up 2 days, load average: 0.08, 0.12, 0.10
内存已用: 3.4G/7.7G
✅ nginx 运行中
✅ mysql 运行中

练习三:自动备份脚本

#!/bin/bash
BACKUP_DIR="/backup"
SOURCE="/opt/myapp"
TIMESTAMP=$(date +'%Y%m%d')
FILE="myapp_$TIMESTAMP.tar.gz"

tar -czf "$BACKUP_DIR/$FILE" -C "$(dirname $SOURCE)" "$(basename $SOURCE)"
find "$BACKUP_DIR" -name "myapp_*.tar.gz" -mtime +7 -delete
echo "备份完成: $FILE"

# 加到 crontab 每天凌晨自动执行:
0 3 * * * /opt/scripts/backup.sh


写在最后

命令看起来多,但真正每天用的也就二三十个命令。关键在于理解设计思想——“一切皆文件”、管道哲学、“每个命令只做一件事”。

命令行光看没有用,必须自己敲。照着上面在终端里跑一遍,一次记不住没关系,在真实场景里用上两三次就记住了。

加油 🚀

赞(0)
未经允许不得转载:171主机测评 » 从零玩转 Linux 命令行:一位后端菜鸟的硬核笔记
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址