Linux 基础指令从入门到精通:基础指令、重定向、管道与权限完全指南

作者:meilindehuzi_a日期:2026/7/15

Linux 基础指令从入门到精通:基础指令、重定向、管道与权限完全指南

  • 前言
  • 1. Linux、操作系统与终端
    • 1.1 从 UNIX 到 Linux
    • 1.2 操作系统、Shell 与远程登录
  • 2. Linux 文件系统与路径
    • 2.1 一切皆文件与目录树
    • 2.2 绝对路径、相对路径与定位命令
    • 2.3 使用 ls 读懂目录信息
  • 3. 文件与目录的创建、复制、移动和删除
    • 3.1 touch、stat、mkdir 与 tree
    • 3.2 cp 与通配符
    • 3.3 mv、rmdir 与 rm
  • 4. 查看文件、帮助与检索
    • 4.1 cat、more、less、head 与 tail
    • 4.2 grep、find、which、whereis 与 file
    • 4.3 man 手册、alias 与命令补全
  • 5. 标准输入输出、重定向与管道
    • 5.1 三个标准数据流
    • 5.2 管道把小工具组合起来
  • 6. 时间、压缩、系统信息与管理
    • 6.1 date、时间戳与 cal
    • 6.2 zip、unzip、tar 与文件传输
    • 6.3 top、uname、版本信息与关机
    • 6.4 常见扩展命令地图
  • 7. 深入理解 Shell 的命令执行过程
    • 7.1 从输入到内核的完整链路
    • 7.2 快捷键与退出状态
  • 8. Linux 权限模型与实战
    • 8.1 用户、组、文件类型与 rwx
    • 8.2 chmod、chown 与 chgrp
    • 8.3 umask 如何决定默认权限
    • 8.4 sudo、目录权限与粘滞位
  • 总结

前言

刚接触 Linux 时,最容易产生的错觉是:命令很多、参数很杂,只能靠死记硬背。实际上,Linux 命令背后有一套非常稳定的逻辑:目录树负责定位资源,权限模型负责约束访问,Shell 负责解释命令,重定向和管道负责连接数据。理解这四条主线之后,大多数命令都只是同一套思想在不同场景下的应用。

本文以 Ubuntu 云服务器为实操环境,终端提示符统一写成 moss@ubuntu:~$。其中 moss 是当前用户,ubuntu 是主机名,~ 表示当前位于用户家目录,普通用户提示符为 $,root 用户通常为 #。示例中的提示符只用于说明环境,实际输入时不需要敲入。

**学习目标:**不仅会使用常见命令,还要理解路径、文件类型、标准输入输出、Shell 解释过程以及 Linux 权限的判断规则,最终具备独立查看帮助、组合命令和排查基础问题的能力。

1. Linux、操作系统与终端

1.1 从 UNIX 到 Linux

Linux 的思想源头可以追溯到 UNIX。20 世纪 60 年代末,贝尔实验室的 Ken Thompson、Dennis Ritchie 等人在 Multics 项目的经验上开发 UNIX。此后 UNIX 逐渐形成 AT&T System V 与 BSD 等重要分支,BSD 还推动了 TCP/IP 在操作系统中的普及。不同实现之间的竞争,又促成了 POSIX 等标准,使程序能够在相近的类 UNIX 系统上迁移。

1991 年,Linus Torvalds 发布 Linux 内核的早期版本。Linux 借助 GNU 工具链、自由软件和全球开发者协作迅速成长,今天已经广泛用于服务器、云计算、超级计算机、网络设备、嵌入式设备和 Android 系统。

严格来说,Linux 是内核;日常所说的 Ubuntu、Debian、Fedora 等 Linux 系统,是 Linux 内核、GNU 工具、软件包管理器和用户空间程序共同组成的发行版。

常见发行版的定位可以概括如下:

发行版主要特点常见场景
Debian稳定、社区驱动、软件仓库成熟服务器、基础系统
Ubuntu基于 Debian,资料丰富,兼顾桌面、服务器与云新手学习、云服务器、开发环境
RHEL商业支持和认证体系完善企业生产环境
CentOS Stream位于 Fedora 与 RHEL 之间的持续交付分支RHEL 生态开发与测试
Fedora技术更新快,常作为新技术试验场桌面开发、前沿技术体验
Kali Linux基于 Debian,预装安全测试工具合法授权的安全测试

开源并不等于“没有版权”或“只能免费使用”。开源许可证规定了软件可以如何使用、修改与再分发。企业可以基于开源代码提供订阅、技术支持、托管服务和定制开发,这也是 Linux 生态能够长期发展的重要原因。

1.2 操作系统、Shell 与远程登录

操作系统的根本任务,是管理 CPU、内存、磁盘、网络和外设等硬件资源,并向应用程序提供稳定接口。用户不会直接与内核交互,而是借助图形界面或命令行工具发出请求。

Shell 是命令行环境中的命令解释器。它读取命令,完成变量展开、通配符匹配、重定向和管道连接,再启动相应程序;程序执行结束后,Shell 将控制权交还给用户。Ubuntu 默认常用的交互式 Shell 是 Bash,也可以使用 Zsh 等其他 Shell。

1moss@ubuntu:~$ echo "$SHELL"
2/bin/bash
3

云服务器通常不安装桌面环境,因为图形界面会额外占用内存、CPU 和磁盘,也不利于自动化。无论本地使用什么终端软件,连接服务器的核心协议通常都是 SSH:

1# 在服务器控制台查看网卡与 IP 地址
2moss@ubuntu:~$ ip addr
3
4# 在本地终端登录服务器
5ssh moss@服务器IP
6

首次连接会要求确认主机指纹,随后输入密码;生产环境更推荐 SSH 密钥认证。终端中 Ctrl+C 通常用于中断前台程序,不等同于图形界面的复制。多数终端使用 Ctrl+Shift+CCtrl+Shift+V,也可能支持 Ctrl+InsertShift+Insert

2. Linux 文件系统与路径

2.1 一切皆文件与目录树

Linux 把磁盘内容组织成一棵以 / 为根的目录树。普通文件一定是叶子节点,目录既可以为空,也可以继续包含子目录和文件。设备、管道、套接字等资源同样以文件形式暴露,这就是常说的“一切皆文件”:不同资源可以复用统一的打开、读取、写入和关闭接口。

Ubuntu 中常见目录如下:

目录主要用途
/整棵目录树的根
/home普通用户家目录,例如 /home/moss
/rootroot 用户家目录,不是文件系统根目录
/etc系统级配置文件
/bin、/usr/bin常用用户命令;现代 Ubuntu 中 /bin 通常链接到 /usr/bin
/sbin、/usr/sbin系统管理命令
/var日志、缓存、队列等经常变化的数据
/tmp临时文件,内容可能被系统清理
/dev磁盘、终端等设备文件
/proc、/sys内核和进程导出的虚拟文件系统
/lib、/usr/lib共享库与系统组件
/opt可选的第三方软件
/mnt、/media文件系统临时挂载点和移动设备挂载点

2.2 绝对路径、相对路径与定位命令

绝对路径/ 开始,不依赖当前工作目录,适合配置文件、脚本和服务定义;相对路径以当前目录为参照,输入更短,适合交互操作。. 表示当前目录,.. 表示上一级目录,~ 表示当前用户家目录,-cd 中表示上一次所在目录。

1moss@ubuntu:~$ pwd
2/home/moss
3
4moss@ubuntu:~$ cd /var/log       # 绝对路径
5moss@ubuntu:/var/log$ cd ../tmp  # 相对路径,进入 /var/tmp
6moss@ubuntu:/var/tmp$ cd ~       # 回到 /home/moss
7moss@ubuntu:~$ cd -              # 回到 /var/tmp
8

pwd 显示当前工作目录,cd 改变当前工作目录,whoami 显示当前有效用户名。路径之所以能够唯一定位文件,是因为目录树中的节点只有一个直接父目录;符号链接虽然可以提供额外入口,但解析后仍会落到具体对象。

2.3 使用 ls 读懂目录信息

ls [选项] [文件或目录] 用于列出内容。对于目录,它默认列出目录中的条目;对于文件,它显示该文件本身的信息。

选项含义
-a包含以 . 开头的隐藏文件,并显示 .、..
-l使用长格式显示类型、权限、链接数、所有者、组、大小和时间
-h与 -l 搭配,以 KiB、MiB 等可读单位显示大小
-d显示目录本身,而不是展开目录内容
-i显示 inode 编号
-n用数字 UID、GID 代替名称
-F在名称后追加类型标记,如目录 /、可执行文件 *、链接 @
-s、-k显示占用的磁盘块;-k 以 1 KiB 块为单位
-r、-t、-S反向、按时间、按大小排序
-R递归列出子目录
-1每行只显示一个条目
1moss@ubuntu:~$ ls -alh
2drwxr-x--- 6 moss moss 4.0K Jul 12 09:30 .
3drwxr-xr-x 3 root root 4.0K Jul 10 18:00 ..
4-rw-r--r-- 1 moss moss  220 Jul 10 18:00 .bash_logout
5drwxr-xr-x 2 moss moss 4.0K Jul 12 09:30 project
6

长格式第一列并不是“权限字符串”这么简单:第一个字符表示文件类型,后面九个字符才依次表示所有者、所属组、其他用户的 rwx 权限。链接数、所有者和组也会直接影响后续的文件管理与权限判断。

3. 文件与目录的创建、复制、移动和删除

3.1 touch、stat、mkdir 与 tree

touch 最常见的用途是创建空文件;如果文件已存在,它默认更新访问时间和修改时间。-a 只更新访问时间,-m 只更新修改时间,-c--no-create 表示文件不存在时不要创建。查看完整元数据可使用 stat

1moss@ubuntu:~$ touch notes.txt
2moss@ubuntu:~$ touch -m notes.txt
3moss@ubuntu:~$ touch -c missing.txt
4moss@ubuntu:~$ stat notes.txt
5

stat 中常见的三个时间含义不同:

  • Access(atime):文件内容最近一次被访问的时间。
  • Modify(mtime):文件内容最近一次被修改的时间。
  • Change(ctime):inode 元数据最近一次变化的时间,例如权限、所有者或 mtime 改变;它不是“创建时间”。
  • Birth:文件系统支持时记录创建时间,并非所有环境都提供。

mkdir 创建目录,-p 可以自动补齐不存在的父目录;tree 用树状结构查看层级,Ubuntu 如未安装可执行 sudo apt install tree

1moss@ubuntu:~$ mkdir project
2moss@ubuntu:~$ mkdir -p project/src/include
3moss@ubuntu:~$ tree project
4project
5└── src
6    └── include
7

3.2 cp 与通配符

cp [选项] 源 目标 用于复制。复制普通文件不需要额外选项,复制目录需要 -r-R。如果最后一个参数是已存在目录,可以一次把多个源文件复制进去。

1moss@ubuntu:~$ cp notes.txt notes.bak
2moss@ubuntu:~$ cp -i notes.txt notes.bak
3moss@ubuntu:~$ cp *.txt project/
4moss@ubuntu:~$ cp -r project project-backup
5

其中 * 是由 Shell 展开的通配符,表示匹配任意长度的字符;它不是 cp 自己的功能。-i 在覆盖前询问,-f 强制覆盖。日常操作中不要习惯性添加 -f,否则很容易无提示地覆盖重要文件。

3.3 mv、rmdir 与 rm

mv 同时承担移动重命名两种职责:目标是新文件名时完成重命名,目标是已存在目录时把源移动进去。-i 会在覆盖前询问,-f 则直接覆盖。

1moss@ubuntu:~$ mv notes.txt linux-notes.txt
2moss@ubuntu:~$ mv -i linux-notes.txt project/
3moss@ubuntu:~$ mv project/archive ..
4

rmdir 只删除空目录,rmdir -p a/b/c 会从最深层开始删除,并在父目录变空时继续向上删除。rm 可以删除文件,配合 -r 才能递归删除目录:

1moss@ubuntu:~$ rmdir empty-dir
2moss@ubuntu:~$ rm old.txt
3moss@ubuntu:~$ rm -i important.txt
4moss@ubuntu:~$ rm -r old-project
5
命令或选项行为风险提示
rmdir dir仅删除空目录目录非空时拒绝执行
rm file删除文件通常不经过回收站
rm -i file删除前逐个确认适合重要文件
rm -r dir递归删除目录树先用 ls 核对路径
rm -rf dir递归且强制删除高风险,变量为空或路径写错都可能造成严重损失

Linux 服务器上的 rm 通常是不可逆操作。执行递归删除前,先用 pwd 确认位置,再用 ls -- 目标路径 检查对象;路径可能以 - 开头时,用 -- 明确结束选项解析。

4. 查看文件、帮助与检索

4.1 cat、more、less、head 与 tail

这五条命令都能读取文本,但适用场景不同:cat 适合一次看完短文件,moreless 适合分页阅读长文件,headtail 则只截取文件开头或结尾。

cat [选项] [文件...] 会把文件内容写到标准输出。-n 为所有行编号,-b 只给非空行编号,-s 把连续空行压缩成一行。它还能按参数顺序连接多个文件:

1moss@ubuntu:~$ cat > demo.txt
2Ubuntu Server
3
4Linux Command
5^D
6
7moss@ubuntu:~$ cat -n demo.txt
8     1  Ubuntu Server
9     2
10     3  Linux Command
11
12moss@ubuntu:~$ cat -b demo.txt
13     1  Ubuntu Server
14
15     2  Linux Command
16

第一条 cat > demo.txt 从键盘读取内容并写入文件,Ctrl+D 表示输入结束;cat -n 连空行一起编号,cat -b 跳过空行。若执行 cat part1.txt part2.txt,终端会先显示 part1.txt,再紧接着显示 part2.txt。大文件不要直接 cat,否则内容会快速刷过屏幕。

more [选项] 文件 是基础分页器,more -10 long.log 表示每屏先显示 10 行。阅读时按空格翻到下一屏,按回车向下移动一行,按 q 退出。它主要向后翻页,适合临时查看结构简单的长文本。

less [选项] 文件 功能更完整,不会在打开前把整个文件全部载入内存,因此更适合日志等大文件:

1moss@ubuntu:~$ less -N app.log
2

进入 less 后,PageDown 或空格向后翻页,PageUp 向前翻页;输入 /error 向下搜索,输入 ?error 向上搜索,n 重复本次搜索,N 反向重复,q 退出。启动选项 -N 显示行号,-i 让搜索忽略大小写。less 只是阅读文件,不会修改原内容。

head [选项] 文件 默认输出前 10 行,tail [选项] 文件 默认输出后 10 行;-n 可以指定行数:

1moss@ubuntu:~$ printf "line%02d\n" {1..15} > lines.txt
2
3moss@ubuntu:~$ head -n 3 lines.txt
4line01
5line02
6line03
7
8moss@ubuntu:~$ tail -n 3 lines.txt
9line13
10line14
11line15
12

第一条命令生成 15 行测试数据。head -n 3 只取开头 3 行,tail -n 3 只取结尾 3 行。tail -f 会先显示文件末尾内容,然后持续等待新内容追加,常用于观察程序日志:

1moss@ubuntu:~$ tail -f app.log
22026-07-12 10:20:01 server started
32026-07-12 10:20:08 request completed
4

只要其他进程继续向 app.log 写入,新日志就会实时出现在终端;观察结束后按 Ctrl+C,停止的是 tail 进程,不会删除日志文件。

4.2 grep、find、which、whereis 与 file

grep [选项] 模式 [文件...] 在文本中逐行搜索,并输出包含匹配内容的整行。-i 忽略大小写,-n 显示行号,-v 反选,也就是输出不匹配的行;这些选项可以组合。

1moss@ubuntu:~$ cat app.log
2INFO server started
3Error database timeout
4INFO retrying
5ERROR connection failed
6
7moss@ubuntu:~$ grep -ni "error" app.log
82:Error database timeout
94:ERROR connection failed
10
11moss@ubuntu:~$ grep -v "INFO" app.log
12Error database timeout
13ERROR connection failed
14

grep -ni 同时启用了行号和忽略大小写,因此 ErrorERROR 都能匹配;grep -v "INFO" 排除了包含 INFO 的行。如果模式包含 ^$* 等特殊字符,应使用引号保护,例如 grep -v '^#' app.conf 会排除以 # 开头的注释行。

find 起始路径 查找条件 在指定目录及其子目录中搜索文件。常用条件包括 -name 按名称匹配、-type f 只找普通文件、-type d 只找目录。它输出的是找到的路径,不会默认修改或删除文件。

1moss@ubuntu:~$ find ~/project -name "*.c"
2/home/moss/project/main.c
3/home/moss/project/src/net.c
4
5moss@ubuntu:~$ find /var/log -type f -name "*.log"
6/var/log/dpkg.log
7/var/log/apt/term.log
8

"*.c" 必须加引号,让通配符交给 find 在整个搜索范围内匹配;如果不加引号,Shell 可能先用当前目录的文件替换它,导致查找结果异常。find 会真实遍历目录,起点越大,耗时和磁盘访问越多;从 / 开始查找时还可能遇到权限错误,所以应尽量缩小范围。

几个名称相似的定位命令解决的问题并不相同:

命令查找对象示例
find指定目录树中的文件find ~ -name "notes.txt"
which当前 PATH 中实际会执行的命令,并可能显示别名which ls
whereis程序二进制、源文件和 man 手册位置whereis ls
file根据内容特征识别文件类型file archive.gz

which 根据当前 Shell 的 PATH 查找可执行命令,适合确认“输入某个命令时究竟运行哪个程序”:

1moss@ubuntu:~$ which python3
2/usr/bin/python3
3

输出说明当前环境会执行 /usr/bin/python3。如果命令不存在,which 通常没有输出并返回非零状态。别名、函数和内建命令由 Shell 管理,想更完整地判断命令类型可以使用 type ls

whereis 不依赖 PATH 做普通命令解析,而是从系统已知位置查找程序、源文件和 man 手册:

1moss@ubuntu:~$ whereis ls
2ls: /usr/bin/ls /usr/share/man/man1/ls.1.gz
3

这里 /usr/bin/ls 是程序,ls.1.gz 是压缩后的第 1 章手册。file 则不负责寻找路径,而是读取文件特征判断类型:

1moss@ubuntu:~$ cp /bin/ls mystery
2moss@ubuntu:~$ file mystery
3mystery: ELF 64-bit LSB pie executable, x86-64, ...
4

虽然 mystery 没有扩展名,file 仍能识别它是 ELF 可执行程序,说明 Linux 不依赖扩展名决定文件类型。file -z archive.gz 会尝试继续识别压缩内容;file -c 主要用于检查 magic 规则,并不是日常查看文件类型必须使用的选项。

4.3 man 手册、alias 与命令补全

记不住所有参数是正常的,关键能力是会查帮助。man [章节] 名称 打开联机手册,进入后可按空格翻页、输入 /关键字 搜索、按 n 查找下一个结果、按 q 退出。man -k 关键字 按手册名称和简介搜索,man -a 则依次打开所有同名条目。

章节内容示例
1普通用户命令man 1 printf
2Linux 系统调用man 2 open
3C 库函数man 3 printf
4设备与特殊文件man 4 null
5文件格式与配置man 5 passwd
6游戏man 6 游戏名
7约定、协议和杂项man 7 signal
8系统管理命令man 8 shutdown
9内核例程,部分系统提供man 9 函数名

例如 printf 既可能是普通命令,也可能指 C 库函数,章节号能消除歧义:

1moss@ubuntu:~$ man 1 printf   # 查看命令
2moss@ubuntu:~$ man 3 printf   # 查看 C 库函数
3moss@ubuntu:~$ man -k "copy files"
4cp (1)               - copy files and directories
5

如果 Ubuntu 提示没有手册,可以执行 sudo apt install man-db manpages 安装基础手册。alias 别名='实际命令' 用来给常用命令设置简写,别名只影响当前 Shell 的命令解析:

1moss@ubuntu:~$ alias ll='ls -alF'
2moss@ubuntu:~$ ll
3drwxr-x--- 6 moss moss 4096 Jul 12 09:30 ./
4drwxr-xr-x 3 root root 4096 Jul 10 18:00 ../
5
6moss@ubuntu:~$ alias ll
7alias ll='ls -alF'
8moss@ubuntu:~$ unalias ll
9

输入 ll 后,Shell 会把它替换成 ls -alF,所以得到包含隐藏文件和类型标记的长格式列表;unalias ll 删除当前会话中的别名。要永久保存 Bash 别名,应写入 ~/.bashrc 后执行 source ~/.bashrc

命令补全可以减少输入和路径拼写错误。例如输入 cd /var/lo 后按 Tab,若只有一个匹配项,Shell 会补全为 cd /var/log/;若候选项不唯一,连续按两次 Tab 会列出候选项。Ctrl+D 在空提示符处表示 EOF,可以退出当前 Shell,效果接近 exit

5. 标准输入输出、重定向与管道

5.1 三个标准数据流

在理解重定向之前,先把一条命令想象成一台正在工作的机器:它可以从入口接收数据,处理后从出口给出正常结果;如果处理失败,还会从另一条出口报告错误。Linux 把这三条通道分别称为标准输入标准输出标准错误

数据流文件描述符默认来源或去向
标准输入 stdin0命令接收数据的入口,默认连接键盘
标准输出 stdout1命令输出正常结果的通道,默认连接终端
标准错误 stderr2命令输出错误信息的通道,默认也连接终端

这里的 012 是内核为进程标识已打开通道所使用的文件描述符。初学阶段只需要记住:0 代表输入,1 代表正常输出,2 代表错误输出。

先看没有重定向时的情况:

1moss@ubuntu:~/lesson1$ cat
2hello Linux
3hello Linux
4^D
5

没有指定文件时,cat 会从标准输入读取数据。键盘输入 hello Linux 后,cat 又把它写到标准输出,所以终端紧接着显示相同内容;按 Ctrl+D 表示输入结束,cat 随后退出。示例中的 ^D 只是用来标记按下了 Ctrl+D,终端通常不会真的打印这两个字符。这说明默认情况下,标准输入来自键盘,标准输出回到终端。

正常输出和错误输出虽然都显示在同一个终端,看起来很像,但它们实际是两条独立通道:

1moss@ubuntu:~/lesson1$ ls notes.txt not-exist.txt
2ls: cannot access 'not-exist.txt': No such file or directory
3notes.txt
4

notes.txt 存在,所以它的名字属于标准输出;not-exist.txt 不存在,对应的报错属于标准错误。正因为两条通道彼此独立,后面才能只保存正常结果、只保存错误,或者把两者保存到不同文件。

**重定向的本质:**不改变命令本身的功能,只是由 Shell 在命令运行前重新连接数据通道。例如,把原本通向终端的标准输出改接到文件,或者把原本来自键盘的标准输入改接到文件。

常用符号可以先记成下面这张表:

写法含义对已有目标文件的影响
命令 > 文件把标准输出写入文件,等价于 1>清空后重新写入
命令 >> 文件把标准输出追加到文件末尾,等价于 1>>保留原内容
命令 < 文件让命令从文件读取标准输入,等价于 0<不修改输入文件
命令 2> 文件只把标准错误写入文件清空后重新写入
命令 2>> 文件只把标准错误追加到文件末尾保留原内容
命令 > 正常文件 2> 错误文件分别保存正常结果和错误两个文件都重新写入
命令 > 文件 2>&1把正常结果和错误合并到同一文件清空后重新写入

>:覆盖标准输出。

1moss@ubuntu:~/lesson1$ echo "first line" > notes.txt
2moss@ubuntu:~/lesson1$ cat notes.txt
3first line
4
5moss@ubuntu:~/lesson1$ echo "new content" > notes.txt
6moss@ubuntu:~/lesson1$ cat notes.txt
7new content
8

echo 原本会把文字显示在终端,但 > 把它的标准输出改接到 notes.txt,所以执行第一条命令时屏幕没有显示 first line。第二次使用 > 时,原来的 first line 被清空,只剩下新写入的 new content

Shell 会在命令开始运行之前准备重定向,所以即使命令最后执行失败,> 指向的已有文件也可能已经被清空。不要把重要文件随意放在 > 右侧。

>>:追加标准输出。

1moss@ubuntu:~/lesson1$ echo "second line" >> notes.txt
2moss@ubuntu:~/lesson1$ echo "third line" >> notes.txt
3moss@ubuntu:~/lesson1$ cat notes.txt
4new content
5second line
6third line
7

>> 不会删除已有内容,而是每次从文件末尾继续写,适合持续记录日志。可以简单记成:一个 > 重新写,两个 >> 接着写。

<:从文件提供标准输入。

1moss@ubuntu:~/lesson1$ cat > users.txt
2moss
3root
4linuxstudy
5^D
6
7moss@ubuntu:~/lesson1$ grep "root" < users.txt
8root
9

grep "root" 需要一批文本作为输入。< users.txt 告诉 Shell:不要再等待键盘输入,而是把 users.txt 连接到 grep 的标准输入。grep 读到三行内容,只把包含 root 的一行输出到终端。

下面两种写法在这个例子中的结果相同,但数据进入 grep 的方式不同:

1grep "root" users.txt     # users.txt  grep 的文件参数,由 grep 主动打开
2grep "root" < users.txt   # users.txt  Shell 接到 grep 的标准输入
3

2>2>>:单独处理错误信息。

1moss@ubuntu:~/lesson1$ ls notes.txt not-exist.txt 2> errors.log
2notes.txt
3
4moss@ubuntu:~/lesson1$ cat errors.log
5ls: cannot access 'not-exist.txt': No such file or directory
6

命令仍然在终端显示 notes.txt,因为正常输出没有被重定向;错误信息没有出现在终端,而是通过文件描述符 2 写入 errors.log。如果想保留以前的错误记录,应改用 2>> errors.log

把正常结果和错误分别保存。

1moss@ubuntu:~/lesson1$ ls notes.txt not-exist.txt > success.log 2> errors.log
2
3moss@ubuntu:~/lesson1$ cat success.log
4notes.txt
5
6moss@ubuntu:~/lesson1$ cat errors.log
7ls: cannot access 'not-exist.txt': No such file or directory
8

这次终端没有显示命令结果,因为标准输出进入 success.log,标准错误进入 errors.log。这种写法适合脚本和后台任务:正常结果与错误记录互不混杂,排查问题更方便。

2>&1:把错误合并到标准输出当前所在的位置。

1moss@ubuntu:~/lesson1$ ls notes.txt not-exist.txt > all.log 2>&1
2moss@ubuntu:~/lesson1$ cat all.log
3ls: cannot access 'not-exist.txt': No such file or directory
4notes.txt
5

可以从左到右拆解这条命令:

  • > all.log:先让文件描述符 1,也就是标准输出,指向 all.log
  • 2>:准备改变文件描述符 2,也就是标准错误的去向。
  • &1:这里的 1 表示文件描述符 1& 表明它不是一个名为 1 的普通文件。
  • 2>&1 合起来表示:让标准错误去往标准输出此刻正在使用的目标,也就是 all.log

因此正常结果和错误最终都会进入 all.log。Bash 还支持更短的 &> all.log,但理解 2>&1 更重要,因为它能清楚表现两个通道的关系。

重定向按照从左到右的顺序生效,交换顺序会改变结果:

1# 正常输出先进入 all.log,错误随后跟过去:两者都进入文件
2ls notes.txt not-exist.txt > all.log 2>&1
3
4# 错误先复制终端方向,随后只有正常输出改到 all.log:错误仍显示在终端
5ls notes.txt not-exist.txt 2>&1 > all.log
6

还可以把不需要的输出送到 /dev/null。它是一个特殊设备文件,写进去的数据会被直接丢弃:

1moss@ubuntu:~/lesson1$ find / -name "notes.txt" 2> /dev/null
2/home/moss/lesson1/notes.txt
3

find/ 开始搜索时可能遇到许多无权访问的目录。2> /dev/null 丢弃这些权限错误,只保留标准输出中的查找结果。排错时不要滥用这种写法,否则真正有价值的错误信息也会被隐藏。

判断重定向时,可以依次问三个问题:命令从哪里读取输入?正常结果去哪里?错误信息去哪里?把这三条通道分别想清楚,复杂写法就容易拆开了。

5.2 管道把小工具组合起来

重定向负责在“命令与文件”之间改变数据方向,管道则负责在“命令与命令”之间传递数据。管道符 | 会把左侧命令的标准输出连接到右侧命令的标准输入

1命令A的标准输出 -> | -> 命令B的标准输入
2

最简单的例子是统计文本行数:

1moss@ubuntu:~/lesson1$ printf "apple\nbanana\napple\n" | wc -l
23
3

这条命令可以拆成两步理解:

  1. printf 产生三行文本,并把它们写到标准输出。
  2. | 不让这些文本直接显示在终端,而是把它们连接到 wc -l 的标准输入。
  3. wc -l 统计收到的行数,最终把数字 3 输出到终端。

左侧命令不需要知道右侧是谁,右侧也不需要知道数据原来从哪里来。只要一边能产生标准输出,另一边能读取标准输入,就可以通过管道组合。

下面创建一份日志,用它观察多级管道如何逐步缩小数据范围:

1moss@ubuntu:~/lesson1$ cat > app.log
2INFO server started
3ERROR database timeout
4INFO request completed
5ERROR disk full
6ERROR connection failed
7^D
8
9moss@ubuntu:~/lesson1$ cat app.log | grep "ERROR" | wc -l
103
11

这条管道的数据变化如下:

阶段接收到的数据产生的结果
cat app.log文件中的全部 5 行向管道输出 5 行
grep "ERROR"上一步的 5 行筛出包含 ERROR 的 3 行
wc -l筛选后的 3 行输出行数 3

grep 本身不会统计数量,wc -l 也不会判断哪一行包含错误;通过管道组合后,每个命令只完成自己擅长的一步。实际上 grep "ERROR" app.log | wc -l 更简洁,因为 grep 可以直接打开文件,不必额外使用 cat

管道也可以先整理数据,再进行统计:

1moss@ubuntu:~/lesson1$ cat > fruit.txt
2apple
3banana
4apple
5orange
6banana
7apple
8^D
9
10moss@ubuntu:~/lesson1$ sort fruit.txt | uniq -c | sort -nr
11      3 apple
12      2 banana
13      1 orange
14

这里 sort 先把相同单词排到一起,因为 uniq -c 只能统计相邻的重复行uniq -c 为每组内容添加出现次数;最后 sort -nr 按数字倒序排列,所以出现次数最多的 apple 位于第一行。

查看长输出时,可以把结果交给 less

1moss@ubuntu:~/lesson1$ grep -ni "error" app.log | less
2

grep -ni 忽略大小写并附带行号,匹配结果进入 less 后可以前后翻页和搜索。只有按 q 退出 less 后,终端才重新出现命令提示符。

再来看“截取指定行”的经典组合:

1# 查看第 181  200 行,共 20 
2moss@ubuntu:~/lesson1$ head -n 200 app.log | tail -n 20
3line 181
4...
5line 200
6

head -n 200 app.log 先截取原文件第 1 至 200 行,tail -n 20 再从这 200 行中取最后 20 行,所以最终得到原文件第 181 至 200 行。注意:如果希望包含第 180 行,范围长度应该是 21 行,需要写成 head -n 200 app.log | tail -n 21

管道默认只传递标准输出,左侧命令的标准错误仍会直接显示在终端:

1moss@ubuntu:~/lesson1$ ls notes.txt not-exist.txt | wc -l
2ls: cannot access 'not-exist.txt': No such file or directory
31
4

wc -l 只收到正常输出中的 notes.txt,所以结果是 1;报错没有进入管道。如果确实希望正常结果和错误一起交给右侧命令,可以先合并通道:

1moss@ubuntu:~/lesson1$ ls notes.txt not-exist.txt 2>&1 | wc -l
22
3

此时 2>&1 让错误跟随标准输出进入管道,wc -l 收到一行报错和一行文件名,因此得到 2。Bash 中也可以把 2>&1 | 简写成 |&,但初学时写完整形式更容易理解。

tee 可以解决“既想在屏幕上看到结果,又想保存到文件”的问题:

1moss@ubuntu:~/lesson1$ grep "ERROR" app.log | tee errors.txt | wc -l
23
3
4moss@ubuntu:~/lesson1$ cat errors.txt
5ERROR database timeout
6ERROR disk full
7ERROR connection failed
8

tee errors.txt 从标准输入收到三行错误,把同样的数据写入 errors.txt,同时继续从标准输出传给 wc -l。因此终端最终显示数量 3,文件里则保留三行具体内容。tee -a errors.txt 会采用追加方式,作用类似重定向中的 >>

需求推荐写法数据最终去向
用新结果覆盖文件命令 > 文件标准输出进入文件
在文件末尾追加结果命令 >> 文件标准输出追加到文件
从文件读取输入命令 < 文件文件内容进入标准输入
单独保存错误命令 2> 错误文件标准错误进入文件
合并正常结果与错误命令 > 文件 2>&1两类输出进入同一文件
把结果交给另一个命令`命令A命令B`
边显示边保存[`命令tee 文件`](https://xplanc.org/primers/document/zh/10.Bash/90.%E5%B8%AE%E5%8A%A9%E6%89%8B%E5%86%8C/EX.tee.md)

管道传递的是程序产生的字节流,不是文件名,也不是简单地表示“左边完全执行完,再执行右边”。管道两端通常可以同时运行:左侧不断产生数据,右侧不断接收并处理。理解这一点后,再看 tar 的“不生成中间压缩包复制”就容易一些:

1mkdir -p /tmp/project-copy
2tar -C project -cf - . | tar -C /tmp/project-copy -xf -
3

左侧命令中的 -C project 表示先进入 project-c 创建归档,-f - 表示不写入某个 .tar 文件,而是把归档数据送到标准输出。管道把这批数据交给右侧 tar;右侧的 -C /tmp/project-copy 指定解包位置,-x 表示解包,第二个 -f - 表示从标准输入读取归档。执行完成后,project 的内容会出现在 /tmp/project-copy,整个过程不会产生中间 .tar 文件。

学习这部分时,不要先背复杂组合。先分别确认每条命令单独会输出什么,再从左到右追踪标准输出经过 | 后被谁接收。只要数据流向能够画清楚,重定向和管道就不会混乱。

6. 时间、压缩、系统信息与管理

6.1 date、时间戳与 cal

date 显示或格式化时间。%Y%m%d 分别是年、月、日,%H%M%S 是时、分、秒,%F 等价于 %Y-%m-%d%X 表示本地时间格式。

1moss@ubuntu:~$ date
2Sun Jul 12 10:30:00 CST 2026
3
4moss@ubuntu:~$ date '+%Y-%m-%d %H:%M:%S'
52026-07-12 10:30:00
6
7moss@ubuntu:~$ date +%s
81783823400
9
10moss@ubuntu:~$ date -d @1000000000 '+%F %T %Z'
112001-09-09 09:46:40 CST
12

直接执行 date 会显示本地时间、时区和年份;+格式 用于控制输出,适合脚本生成日志名。date +%s 把当前时间转换成 Unix 时间戳,date -d @时间戳 则完成反向转换。时间戳表示从 1970-01-01 00:00:00 UTC 起经过的秒数,通常不计闰秒。由于显示结果会换算为服务器当前时区,同一个时间戳在不同时区下可能显示成不同的钟表时间,但代表的是同一时刻。

date -s '2026-07-12 10:30:00' 可以设置系统时间,但需要 root 权限。云服务器通常由 systemd-timesyncd、Chrony 等服务自动同步,手工修改可能影响日志排序、证书校验和定时任务,因此日常只查看,不随意设置。

cal 显示日历,Ubuntu 可能需要先安装 ncal 包:

1moss@ubuntu:~$ sudo apt install ncal
2moss@ubuntu:~$ cal           # 当前月
3moss@ubuntu:~$ cal -3        # 上月、当前月、下月
4moss@ubuntu:~$ cal -y        # 全年
5moss@ubuntu:~$ cal -j        # 显示一年中的第几天
6

直接执行 cal 会显示当前月并突出当天;cal -3 并排显示前一个月、当前月和下一个月;cal -y 展示全年;cal -j 将日期改为一年中的序号,例如平年的 2 月 1 日是第 32 天。也可以使用 cal 7 2026 查看指定年月。

6.2 zip、unzip、tar 与文件传输

ZIP 格式跨平台方便,压缩目录时使用 -runzip -d 指定解压目录:

1moss@ubuntu:~$ zip -r project.zip project/
2  adding: project/ (stored 0%)
3  adding: project/README.md (deflated 28%)
4
5moss@ubuntu:~$ unzip -l project.zip
6Archive:  project.zip
7  Length      Date    Time    Name
8---------  ---------- -----   ----
9       80  2026-07-12 10:30   project/README.md
10
11moss@ubuntu:~$ unzip project.zip -d /tmp/project
12Archive:  project.zip
13  inflating: /tmp/project/project/README.md
14

zip -r 递归进入 project/,把目录结构和文件写入 project.zip;输出中的 adding 表示条目已加入归档。unzip -l 只列出内容,不真正解压,适合先核对路径;unzip -d /tmp/project 才会把内容释放到指定目录。若系统没有这两个命令,可执行 sudo apt install zip unzip

tar 的核心职责是把多个文件归档为一个文件,再按需配合 gzip 或 bzip2 压缩。参数可以连写,但 -f 后必须紧跟归档文件名。

参数含义
-c、-x、-t创建、解包、查看归档内容,三者择一
-f指定归档文件名
-v显示处理过程,后台任务不建议大量输出
-z、-j使用 gzip、bzip2
-C先切换到指定目录再执行
-p解包时尽量保留权限
-N只归档比指定日期新的文件
--exclude排除匹配路径
1# 仅归档,以及使用 gzip 压缩
2sudo tar -cvf /tmp/etc.tar /etc
3sudo tar -zcvf /tmp/etc.tar.gz /etc
4
5# 查看、解压到指定目录、只解出单个文件
6tar -ztvf /tmp/etc.tar.gz
7sudo tar -zxvf /tmp/etc.tar.gz -C /usr/local/src
8tar -zxvf /tmp/etc.tar.gz -C /tmp etc/passwd
9
10# 保留权限、按日期增量筛选、排除目录
11mkdir -p /tmp/etc-restore
12sudo tar -zxvpf /tmp/etc.tar.gz -C /tmp/etc-restore
13tar -N '2026-07-01' -zcvf home-new.tar.gz /home
14tar --exclude='/home/moss/cache' -zcvf backup.tar.gz /home/moss /etc
15

tar -cvf 只打包,不压缩,得到 /tmp/etc.tar;增加 -z 后会使用 gzip,通常体积更小,扩展名写作 .tar.gz.tgztar -ztvf 只查看归档目录,tar -zxvf ... -C 目录 解压到指定位置,命令末尾再写 etc/passwd 时只解出这个条目。-p 尽量恢复原权限,-N 只选择指定日期后更新的文件,--exclude 排除不需要备份的路径。

归档绝对路径时,tar 通常会提示移除开头的 /,归档内的 /etc/passwd 会保存成 etc/passwd,这是为了避免解包时直接覆盖系统绝对路径。第一次检查未知压缩包时,应先用 tar -tfunzip -l 查看内部路径,再解压到新建的临时目录。

资料传输方面,rzsz 来自 lrzsz,适合支持 ZMODEM 的终端;Ubuntu 可用 sudo apt install lrzsz 安装。更通用、安全的方案是 SSH 体系中的 scp

1# 在本地电脑执行:上传到服务器
2scp project.zip moss@服务器IP:/home/moss/
3
4# 在本地电脑执行:从服务器下载
5scp moss@服务器IP:/home/moss/project.zip ./
6

冒号左侧是远程主机,右侧是远程路径。第一条上传后,文件会出现在服务器的 /home/moss/;第二条把服务器文件下载到本地当前目录。两端复制都通过 SSH 加密传输。

6.3 top、uname、版本信息与关机

top 动态显示系统负载和进程。-d 设置刷新间隔,-n 设置刷新次数,交互界面按 q 退出:

1moss@ubuntu:~$ top -d 1 -n 5
2top - 11:20:01 up 3 days,  1 user,  load average: 0.08, 0.04, 0.01
3Tasks: 112 total,   1 running, 111 sleeping
4%Cpu(s):  1.0 us,  0.5 sy, 98.5 id
5MiB Mem :   1970.0 total,   620.0 free,   540.0 used,   810.0 buff/cache
6
7moss@ubuntu:~$ uname -r
86.8.0-60-generic
9
10moss@ubuntu:~$ uname -a
11Linux ubuntu 6.8.0-60-generic #63-Ubuntu SMP x86_64 GNU/Linux
12
13moss@ubuntu:~$ lsb_release -a
14Description:    Ubuntu 24.04.2 LTS
15
16moss@ubuntu:~$ cat /etc/os-release
17PRETTY_NAME="Ubuntu 24.04.2 LTS"
18

top 顶部的 load average 是最近 1、5、15 分钟的平均负载,id 表示 CPU 空闲比例,MiB Mem 展示内存使用情况;下方进程表中的 %CPU%MEM 可用于定位资源占用者。top -d 1 -n 5 每秒刷新一次,共输出 5 次后自动退出。

uname -r 查看正在运行的内核发行版本,uname -a 进一步输出内核名、主机名、架构等信息。lsb_release -a/etc/os-release 查看 Ubuntu 发行版信息,两类“版本”不要混淆:升级 Ubuntu 不一定立即改变当前正在运行的内核,安装新内核后通常还需要重启。

bc 是命令行计算器,特别适合 Shell 中的浮点运算:

1moss@ubuntu:~$ echo '10/3' | bc
23
3
4moss@ubuntu:~$ echo 'scale=2; 10/3' | bc
53.33
6

默认除法按整数处理,所以第一条得到 3scale=2 指定保留两位小数,第二条得到 3.33。如未安装,可执行 sudo apt install bc

关机和重启会影响所有在线用户与服务,必须确认业务状态并使用 sudo

1sudo shutdown -h now       # 立即关机
2sudo shutdown -r now       # 立即重启
3sudo shutdown -h +10       # 10 分钟后关机
4sudo shutdown -c           # 取消已安排的关机
5sudo reboot                # 重启
6sudo halt                  # 停止系统,具体断电行为取决于系统配置
7

shutdown -h now 停止服务并关机,shutdown -r now 停止服务后重启,+10 表示安排在 10 分钟后执行,shutdown -c 用于取消尚未发生的计划。远程云服务器关机后 SSH 会立即断开,是否能够再次开机取决于云平台控制台,因此练习时不要随意执行关机命令。

6.4 常见扩展命令地图

基础命令之外,还会遇到以下工具。现阶段不必一次记住,先建立“遇到问题该找哪一类命令”的索引:

场景常见命令
登录与会话login、exit、last、chsh
磁盘与挂载df、mount、umount、dd
文件比较与链接diff、ln
进程与任务ps、top、kill、at、crontab
用户与组adduser、groupadd、passwd、who
资源与配额free、quota
网络诊断ip、ping、ss、route、nslookup
远程与传输ssh、scp、sftp、ftp、mail
安全与属性sudo、su、chmod、chown、chgrp、umask、chattr
压缩与编码gzip、gunzip、zip、unzip、tar、uuencode、uudecode

这些扩展命令不需要一次全部记忆,先掌握最常见的调用方式和输出目标:

1df -h                       # 查看各文件系统容量和剩余空间
2free -h                     # 查看内存与交换空间使用量
3ps aux                      # 列出当前系统进程
4kill 进程PID                # 请求指定进程退出
5ip addr                     # 查看网卡和 IP 地址
6ping -c 4 服务器IP          # 发送 4 次测试包,检查网络连通性
7ss -tulpn                   # 查看监听中的 TCP、UDP 端口和相关进程
8sudo adduser linuxstudy     # 创建用户及其家目录
9passwd                      # 修改当前用户密码
10crontab -e                  # 编辑当前用户的定时任务
11ln -s 原路径 链接名         # 创建符号链接
12diff -u old.conf new.conf   # 以统一格式比较两个文本文件
13

例如 df -h 回答“哪个磁盘分区快满了”,free -h 回答“内存使用情况如何”,ps aux 配合 kill PID 用于定位并终止进程,ip addrping 分别检查本机网络配置与远端连通性。mount 把文件系统接入某个目录,umount 在设备不再使用时卸载;这类操作影响系统资源,应先查阅 man mount 并使用 sudo

其中 ifconfignetstattelnetrloginrcp 等传统工具仍可能在旧环境出现;Ubuntu 新环境通常优先使用 ipss 和 SSH 系列工具,安全性与维护状态更好。

7. 深入理解 Shell 的命令执行过程

7.1 从输入到内核的完整链路

在终端输入一条命令后,并不是内核直接理解了这段文字。简化后的执行链路如下:

  1. Shell 读取一行输入并进行语法解析。
  2. Shell 展开变量、~、通配符和命令替换,处理引号与转义。
  3. Shell 根据别名、内建命令、函数和 PATH 查找执行目标。
  4. Shell 建立重定向、管道,创建子进程并启动程序。
  5. 程序通过系统调用向内核申请读写文件、网络、内存和设备。
  6. 程序退出并返回状态码,Shell 再显示提示符。

Shell 的价值不只是“运行命令”,而是提供了一门可以组合程序、控制数据流和自动化任务的语言。内核管理资源,Shell 负责把人的意图组织成内核和程序能够执行的操作。

可以使用 type 观察 Shell 最终如何解释一个名称:

1moss@ubuntu:~$ type cd
2cd is a shell builtin
3
4moss@ubuntu:~$ type ls
5ls is aliased to `ls --color=auto'
6
7moss@ubuntu:~$ type -a printf
8printf is a shell builtin
9printf is /usr/bin/printf
10

输出说明 cd 是内建命令,ls 当前先命中别名,printf 同时存在内建版和外部程序。cd 必须修改当前 Shell 自身的工作目录,所以不能只让一个执行后立即结束的子进程完成。type -a 会列出同名命令的所有候选来源,适合排查“为什么运行的不是预期程序”。

7.2 快捷键与退出状态

Ctrl+C 会向前台进程组发送中断信号,程序通常据此停止;Ctrl+D 不是信号,而是在终端输入为空时表示 EOF。命令执行完成后,可以通过 $? 查看上一条命令的退出状态,通常 0 表示成功,非 0 表示不同类型的失败。

1moss@ubuntu:~$ ls /path/not-exist
2ls: cannot access '/path/not-exist': No such file or directory
3moss@ubuntu:~$ echo $?
42
5

在脚本和自动化任务中,退出状态比肉眼看到的文字更可靠。可以使用 && 让后续命令只在前一条成功时执行,使用 || 只在前一条失败时执行。

1moss@ubuntu:~$ mkdir -p demo && cd demo
2moss@ubuntu:~/demo$ pwd
3/home/moss/demo
4
5moss@ubuntu:~$ cd /not-exist || echo "目录切换失败"
6-bash: cd: /not-exist: No such file or directory
7目录切换失败
8

第一组中,只有 mkdir demo 成功,Shell 才会执行 cd demo;第二组中 cd 返回非零状态,所以 || 右侧的提示被执行。这种连接方式适合简单的成功或失败处理,但复杂流程应写成结构清晰的 Shell 脚本。

8. Linux 权限模型与实战

8.1 用户、组、文件类型与 rwx

Linux 权限判断围绕三类访问者展开:所有者 u(user)、所属组 g(group)和其他用户 o(others)。root 是超级用户,权限极高;普通用户只能在授权范围内操作。su - 用户名 切换登录身份,sudo 命令 则按授权临时以其他身份执行单条命令,Ubuntu 日常管理更推荐后者。

1moss@ubuntu:~$ id
2uid=1000(moss) gid=1000(moss) groups=1000(moss),27(sudo)
3
4moss@ubuntu:~$ su - linuxstudy
5Password:
6linuxstudy@ubuntu:~$ whoami
7linuxstudy
8

id 显示当前用户的 UID、主组 GID 和附加组,输出中有 sudo 表示该用户属于 sudo 组。su - linuxstudy 中的 - 会同时加载目标用户的登录环境并进入其家目录;执行 exit 可返回原用户。sudo 通常验证当前用户自己的密码,并且只有 sudoers 已授权的用户才能使用。

ls -l 第一列的首字符表示文件类型:

字符类型
-普通文件
d目录
l符号链接
b块设备,如磁盘
c字符设备,如终端
p命名管道 FIFO
s套接字

后九位每三位一组,例如 -rwxr-xr-- 可拆成 rwxr-xr--。权限既可以用字符表示,也可以用八进制表示:r=4w=2x=1,每组相加得到一位数字。

1moss@ubuntu:~$ ls -l run.sh
2-rwxr-xr-- 1 moss developers 85 Jul 12 13:00 run.sh
3

第一个 - 表示普通文件;所有者 moss 拥有 rwx,组 developers 拥有 r-x,其他用户只有 r--。因此 moss 可以读取、修改和执行,组成员可以读取和执行但不能修改,其他用户只能读取。

权限对普通文件对目录
r读取文件内容列出目录项名称
w修改文件内容创建、删除、重命名目录项,通常还需要 x
x将文件作为程序执行进入目录,并按已知名称访问其中对象

8.2 chmod、chown 与 chgrp

chmod 修改权限,只有文件所有者或 root 能够执行。符号模式使用 u/g/o/a 指定对象,用 +/-/= 增加、移除或精确设置权限;数字模式一次写出三组权限。

1moss@ubuntu:~$ ls -l notes.txt
2-rw-r--r-- 1 moss moss 20 Jul 12 13:10 notes.txt
3
4moss@ubuntu:~$ chmod u+w notes.txt
5moss@ubuntu:~$ chmod g+w notes.txt
6moss@ubuntu:~$ chmod o-r notes.txt
7moss@ubuntu:~$ ls -l notes.txt
8-rw-rw---- 1 moss moss 20 Jul 12 13:10 notes.txt
9
10moss@ubuntu:~$ chmod 640 secret.conf
11moss@ubuntu:~$ chmod -R u=rwX,go=rX public/
12

示例先为组增加写权限,再移除其他用户的读权限,最终变为 rw-rw----。数字模式 640 表示所有者 rw-、组 r--、其他用户 ---664 则表示 rw-rw-r--。递归修改目录时要谨慎:小写 x 会让所有普通文件也获得执行权限,而大写 X 只对目录或原本已有执行位的文件生效,通常更符合预期。

chown 修改所有者,也可同时修改组;chgrp 只修改所属组。改变所有者通常需要 root 权限。

1sudo chown user1 file.txt
2sudo chown -R user1:developers project/
3sudo chgrp developers file.txt
4
5moss@ubuntu:~$ ls -l file.txt
6-rw-r----- 1 user1 developers 20 Jul 12 13:20 file.txt
7

chown user1 file.txt 把所有者改为 user1chown -R user1:developers project/ 递归修改整个目录树的所有者和组;chgrp developers file.txt 只改变所属组。最后的 ls -l 用于验证结果。递归变更所有权影响范围很大,执行前应确认目录路径。

8.3 umask 如何决定默认权限

新建普通文件的基础权限通常从 0666 开始,因为普通数据文件默认不应可执行;新建目录从 0777 开始。系统再通过按位规则清除 umask 指定的权限:

1实际权限 = 基础权限 & ~umask
2

例如常见的 umask 0022

对象基础权限umask最终权限
普通文件066600220644,即 rw-r--r--
目录077700220755,即 rwxr-xr-x
1moss@ubuntu:~$ umask
20022
3moss@ubuntu:~$ umask 0027
4moss@ubuntu:~$ touch private.txt
5moss@ubuntu:~$ mkdir private-dir
6moss@ubuntu:~$ ls -ld private.txt private-dir
7drwxr-x--- 2 moss moss 4096 Jul 12 13:30 private-dir
8-rw-r----- 1 moss moss    0 Jul 12 13:30 private.txt
9

设置 umask 0027 后,新目录由 0777 清除对应权限,得到 0750,即 rwxr-x---;新文件由 0666 得到 0640,即 rw-r-----。不要把 umask 理解成普通减法,也不要把 755 这类目标权限直接当作掩码。命令只影响当前 Shell 及其后代进程;退出重新登录后可能恢复默认值,永久修改需要结合 Shell 初始化文件或系统服务配置。

8.4 sudo、目录权限与粘滞位

sudo -u 用户 命令 可以按 sudoers 授权以指定用户身份执行命令:

1moss@ubuntu:~$ sudo -u root /usr/sbin/useradd user2
2moss@ubuntu:~$ sudo -u user2 whoami
3user2
4

第一条 useradd user2 创建用户账号,但底层的 useradd 默认不一定创建家目录;Ubuntu 日常更推荐使用 sudo adduser user2,它会交互式设置密码并创建家目录。第二条 sudo -u user2 whoamiuser2 身份运行 whoami,因此结果是 user2;不写 -u 时默认以 root 身份执行。sudo 只提升这一条命令的权限,不会永久把当前 Shell 变成 root。

不要直接随意 chmod 或普通编辑 /etc/sudoers。应使用 sudo visudo,它会在保存前做语法检查;也可以在 /etc/sudoers.d/ 中创建独立规则。sudoers 规则的基本结构可理解为“哪些用户能在哪些主机上,以谁的身份执行哪些命令”,但生产环境应坚持最小权限原则。

目录权限尤其容易误解。目录的 r 允许读取名称列表,x 允许穿越和按名称访问,w 允许改变目录项。删除文件本质上是修改父目录中的目录项,因此能否删除主要取决于父目录的 w+x,并不取决于文件自身是否可写。

1moss@ubuntu:~$ mkdir permission-demo
2moss@ubuntu:~$ touch permission-demo/read-only.txt
3moss@ubuntu:~$ chmod 444 permission-demo/read-only.txt
4moss@ubuntu:~$ chmod 700 permission-demo
5moss@ubuntu:~$ rm permission-demo/read-only.txt
6rm: remove write-protected regular empty file 'permission-demo/read-only.txt'? y
7

虽然文件自身是只读的,目录所有者仍然可以删除它,因为删除动作修改的是 permission-demo 中的目录项。部分 rm 配置可能会询问确认,但权限判断的核心仍是父目录是否允许写入和穿越。

这会带来共享目录问题:如果多人都对同一目录有写权限,用户可能删除其他人的文件。粘滞位 t 用于限制这种行为:

1sudo mkdir -p /srv/shared
2sudo chmod 0777 /srv/shared
3sudo chmod +t /srv/shared
4ls -ld /srv/shared
5drwxrwxrwt 2 root root 4096 Jul 12 11:00 /srv/shared
6

数字模式中的首位 1 就是粘滞位,所以 chmod 1777 等价于先给所有人目录读写执行权限,再添加 t。长格式最后一位显示为小写 t,说明其他用户同时拥有执行权限且粘滞位生效;如果显示大写 T,表示设置了粘滞位但其他用户没有执行权限。

设置粘滞位后,即使目录可写,目录中的文件通常也只能由以下主体删除或重命名:

  • root;
  • 目录所有者;
  • 文件所有者。

系统的 /tmp 通常就是 drwxrwxrwt,既允许所有用户创建临时文件,又避免用户任意删除别人的文件。

总结

Linux 基础命令并不是一张孤立的参数表。pwdcdls 建立路径感;touchmkdircpmvrm 完成文件生命周期管理;catlessgrepfind 负责读取和定位;重定向与管道把这些小工具组合成完整工作流;chmodchownumasksudo 和粘滞位则共同维护系统边界。

真正可靠的学习方式,是在自己的家目录创建实验区,用 man 查参数、用 statls -l 观察变化、用 $? 验证结果。对于 rm -rf、递归权限修改、关机和 sudoers 配置等高风险操作,始终先确认路径、对象与影响范围。


Linux 基础指令从入门到精通:基础指令、重定向、管道与权限完全指南》 是转载文章,点击查看原文


相关推荐


Rust 开发环境安装(Windows|macOS|Linux)
程序员爱钓鱼2026/7/7

《Rust 编程实战》系列第 2 篇 上一篇我们介绍了为什么要学习 Rust,以及 Rust 的应用场景。 从这一篇开始,我们正式进入 Rust 的学习之旅。 在开始编写 Rust 程序之前,首先需要搭建开发环境。Rust 官方提供了统一的安装工具,无论是 Windows、macOS 还是 Linux,安装方式都非常简单。 本文将带你一步一步完成 Rust 开发环境的安装,并验证是否安装成功。 Rust 官方推荐安装方式 Rust 官方推荐使用 rustup 来安装和管理 Rust。 rus


使用 C# 将 HTML 转 Word 或者 Word 转 HTML
秋天的落叶铺满小路2026/6/29

HTML作为Web内容的标准格式,与Word这种通用的办公文档格式之间的相互转换,是许多企业级应用中的常见需求。无论是将数据库中的动态内容生成为Word报告,还是将现有的Word文档发布为网页,掌握高效的转换方法都能显著提升工作效率。 本文将介绍如何使用 Spire.Doc for .NET 这个专业的文档处理组件,通过 C# 代码轻松实现 HTML 与 Word 之间的相互转换。 为什么选择 Spire.Doc for .NET? .NET 框架本身并不原生支持 Word 或 HTM


Agent 记忆管理
copyer_xyf2026/6/20

模型本身是无状态的。 这一次调用和下一次调用之间,模型不会自动记住你之前说过什么。它看起来“有记忆”,通常是因为 Agent 在每次调用模型前,把历史消息重新组织成上下文发给了模型。 图里的关键点是:Agent 一直在收集用户消息、模型回复、工具结果,然后把这些消息组成队列。模型每次回答时,看到的是这次传进去的完整上下文,而不是它自己真的保存了记忆。 先记住一句话:Agent 的 Memory 本质上是消息管理,不是模型真的拥有记忆。 为什么需要 Memory 如果你连续问两句话: 用户:我叫


Kotlin run 详解:把对象操作收进作用域,再把结果带出来
唐青枫2026/6/12

简介 run 是 Kotlin 标准库里的作用域函数。 作用域函数常见有 5 个: let run with apply also run 的特点比较鲜明: 在对象作用域里执行一段逻辑,然后返回 Lambda 最后一行的结果。 常见写法: val result = user.run { "$name-$age" } 这里的 name、age 来自 user 对象,result 是 Lambda 最后一行的字符串。 run 适合这类场景: 在一个对象里连续读取多个属性 对对象做


为什么 Clean Architecture 能让 ViewModel 保持轻量?
潜龙勿用之化骨龙2026/6/5

在 Android 开发中,MVVM 是非常常见的 UI 架构模式。它通过 ViewModel 承接 UI 状态和用户交互,让界面层变得更加清晰。 但在真实项目里,随着业务不断增加,很多团队都会遇到同一个问题: ViewModel 越写越胖,业务判断、网络请求、数据保存、异常处理全都堆在里面。 一开始这样写可能很方便,但当业务规则越来越复杂时,ViewModel 就会逐渐变成一个“业务大杂烩”:难维护、难复用、难扩展。 Clean Architecture 的价值,正是在于帮助我们把这些职责


Git & Linux 速查表
love8888_cnsd2026/5/29

📋 Git & Linux 速查表 — Java 后端向 一、Git 操作速查 🔥 最高频(日常必用) 命令说明git status查看工作区状态(最常用,肌肉记忆)git add .添加所有改动到暂存区git add <file>添加指定文件到暂存区git commit -m "type: 描述"提交到本地仓库(推荐语义化 message)git push推送到远程仓库git pull拉取并合并远程更新(fetch + merge)git log --oneline -10查看最近 1


重构 AI 思维(一):Prompt Engineering,如何下达不可违抗的指令?
码上实战2026/5/7

嘿,兄弟们好,我是飞哥。 前阵子我发了那篇上岸感悟,很多兄弟私信我:“飞哥,你老说现在要靠 AI 铲子吃饭,可我发现这 AI 经常‘不听话’,给的回答不是太虚就是格式乱掉,这铲子不好使啊。” 确实,很多兄弟还把 AI 当成**“搜索引擎”在用——随手甩个问题,等着它给标准答案。但对于咱们要搞生产级应用的 Java 佬来说,你得把它当成一个“初级开发”或者“外包伙计”**。 你给外包下需求,如果只是随口一句“帮我实现个抢票逻辑”,他保准给你搞出一堆 Bug。你得有清晰的文档、明确的边界、严苛的格式


LuatOS 课程-011 讲:GNSS应用开发
上海合宙LuatOS2026/4/27

在物联网项目开发中,智能定位系统是一类常见且实用的应用场景,本文将基于 LuatOS,分享一款智能定位系统的开发思路与相关实现要点。 在实际开发过程中,类似学生卡定位器的需求十分普遍,这类需求通常对定位精度、设备续航能力、轨迹显示效果以及多平台适配性均有明确要求,而基于 LuatOS 的智能定位系统,可针对性解决这类开发需求中的核心痛点。 项目特点: 🛰️ 三合一定位:GNSS + 基站 + WiFi🔋 续航:智能功耗管理,运动才定位🛣️ 轨迹优化:减少80%GPS静态漂移以及运动漂移


OpenClaw 七大扩展组件深度技术解析
稚枭天卓2026/4/19

针对 Plugin、Skill、Tool、MCP、Agent、Command、Hook 七大核心组件进行底层实现维度的拆解。 1. Plugin (插件容器) 1.1 模块基础解析 核心定位: Plugin 是 OpenClaw 生态中的物理分发与逻辑隔离单元。它通过 openclaw.plugin.json 清单文件,将 Tool、Skill、Hook 等零散能力打包成一个可独立安装、版本控制和卸载的 NPM 包或本地目录。 使用场景: 开发者封装特定领域能力(如“飞书集成


M3-markconv库找不到wkhtmltopdf问题
郑恩赐2026/4/11

M3-markconv库找不到wkhtmltopdf问题 📝 摘要 在使用 markconv 进行 PDF 转换时,你可能会遇到 OSError: No wkhtmltopdf executable found 错误。这表示系统没有安装 wkhtmltopdf 工具,只需要安装它就能解决 💪 1. 问题描述 📚 1.1 主要报错 当你运行 PDF 转换代码时,会看到以下关键报错: OSError: No wkhtmltopdf executable found: "C:\\Progra

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2026 聚合阅读