Linux 基础
Linux 是什么
Linux(/ˈlɪnəks/ lin-əks)是由 Linus Torvalds 开发的一款类 Unix 操作系统内核。
广义的 Linux 指的是各种基于 Linux Kernel 和 GNU Project 的操作系统发行版。
Linux 系统包括 Linux Kernel, GNU Software, X Window System, Package Manager 等。
GNU/Linux 命名争议
GNU 开发者们主张以 GNU/Linux 来称呼各种 Linux 操作系统。
Linux Torvalds 认为 GNU/Linux 这个称呼是合理的,但用 GNU/Linux 来称呼所有的 Linux 发行版 (Debian, Red Hat Linux, SuSE Linux 等) 是不合理的。
Linux 的应用
- 服务器领域
随着 Linux 容器的发展,服务器领域的 Linux 相对 Windows 和 Unix 会持续增长。
- 超算领域
2017 年 Top 500 的超算几乎全都是 Linux 系统,表明 Linux 的性能、稳定性、扩展性非常强大。
- 嵌入式领域
- Openwrt 路由器
- Android 手机操作系统
- Raspberry Pi 树莓派
- 桌面领域
简直少得可怜,主要原因还是软件生态不够强大,学习门槛高等。
Linux Kernel
Linux Kernel 是操作系统的核心,功能包括
- 进程管理 (fork, exec)
- 内存管理 (malloc, free)
- 文件系统 (ext4, btrfs, xfs, vfat)
- 网络协议 (tcp/ip stack)
- 硬件驱动 (linux 是支持硬件驱动最多的操作系统)
GNU Project
- coreutils (chmod, ls, cp, mv, mkdir) 所有用户都会用到且离不开的命令集
- grub
- Hurd
- binutils (as, ld, objdump)
- gcc, glibc, gdb
- autoconf, automake
- gtk+
- gnome
- bash
- emacs
X Window System
X11 定义了一个 C/S 架构的设备独立的框架/协议,用于构建 GUI 环境。
X Server
- 运行在本地的一个程序(通常会监听一个 socket )
- 处理窗口绘制请求(交给显卡渲染,输出到显示器上)
- 处理输入事件 (鼠标、键盘事件)
X Server 的实现
实现 | 描述 |
---|---|
XFree86 | 较早的实现 |
X.Org Server | fork of XFree86, 当前主流的实现 |
Xnest, Xephyr | 嵌套的 xserver,实现了 xserver 功能的X客户端 |
Xvnc | 对于图形程序来说它是 xserver,对于 vnc 客户端来说它是 vncserver |
使用 sudo apt list xserver-*
查看自己电脑上的 X Server.
X Client
- Xlib
- QT, GTK
- 基于 QT, GTK 的所有程序
X Session Manager
一个 session 表示一系列窗口程序的状态,SM 用于保存和恢复这些程序的状态。
Display Manager
DM 是一个系统的登录界面,登录之后唤起 Window Manager。
- XDM
- GDM
- KDM
- LightDM
Window Manager
WM 用于处理窗口的焦点、位置、移动、缩放和样式。
高玩可以不用DE,只用WM。
Desktop Environment
DE 是一系列软件的集合,包括 SM, DM, WM 和一些实用的图形化应用程序,给用户提供一致性的图形化用户体验。
- XFCE
- LXDE
- KDE
- GNOME
- MATE
- Unity
- DDE
Linux 发行版
一个典型的 Linux 桌面发行版包括 Linux Kernel, GNU toolchains, Desktop Environment, Package Manager.
DPKG/APT 系
- Debian (第二老的发行版,最大的社区发行版,祖师爷级别)
- Ubuntu (用户最多)
- Kubuntu, Lubuntu, *ubuntu (Ubuntu 换了桌面)
- Deepin
- Mint (和 Ubuntu 类似)
- Kali (渗透攻防)
- Raspbian (树莓派)
RPM/YUM 系
- Red Hat Enterprise Linux (业界老大)
- Mandriva (公司维护)
- Fedora (社区维护,用于测试新特性)
- CentOS (社区维护,主打稳定、免费)
pacman 系
- Arch Linux (滚动更新, Wiki 完善)
- Manjaro (不滚了、稳定、美观)
Snap 包管理
Snappy 是一个软件部署和包管理系统,最早由 Canonical 公司设计和构建,包称为 snap。snap 包内包含了应用程序运行所需要的所有依赖,因此可以在各种发行版上运行。
其它
- Slackware 最早的发行版
- SUSE 商业发行版,zapper 包管理
- gentoo 所有软件需自行编译
- coreos 容器化发行版,只能安装 Docker 容器
- Apline 主打轻量和安全的发行版,使用 apk 包管理
Console, Terminal, Shell
console: 早期的电脑上对电脑进行操作的控制台
terminal: 支持多用户同时连接的主机上,每个用户所使用的操作设备
shell: 命令行的解释器软件
tty: 电传打字机 Teletypewriter 的缩写,是当时最流行的终端设备
现代 Linux 上
- /dev/console 控制台终端,与显示器连接
- /dev/tty* 虚拟控制台终端设备,与 /dev/console 相关联,通过
ctrl+alt+fn
来切换,tty0 表示当前激活的 tty,tty0 和 console 是同一个概念 - /dev/pty 伪终端 (xterm, gnome-terminal)
- /dev/ptmx 伪终端的 master 部分
- /dev/pts/* 伪终端的 slave 部分(每打开一个终端模拟器的页面就会创建一个 pts 设备)
- shell 命令行解释器 (sh, bash, csh, zsh, fish)
常用命令
命令 | 作用 |
---|---|
ls |
列出当前目录内容 |
pwd |
打印当前目录 |
cd <dir> |
切换目录 |
rm [-rf] <filename> |
删除文件 |
cp [-rf] <filename> |
复制文件 |
mv <src> <dst> |
移动文件 |
cat [file] ... |
合并文件内容打印到标准输出 |
tail -n filename |
查看文件最后 n 行内容 |
less <filename> |
分页显示文件内容,按 n 下一页,按 b 上一页 |
grep <pattern> [FILE] |
在给定的文件中搜索指定的字符串 |
find [path...] [expression] |
查找路径中满足匹配条件的文件 |
tar zvxf filename.tar.gz |
解压提取 .tar.gz 格式的文件 |
unzip filename.zip -d dir |
解压 filename.zip 到 dir 目录 |
man command |
查看帮助 |
ping <destination> |
向远程主机发送 ICMP 数据包 |
who |
列出当前登录的用户名 |
sudo command |
以 root 身份执行命令 |
su [user] |
切换用户 |
uname -a |
查看系统内核、架构、主机信息 |
screenfetch |
显示系统发行版信息 |
df -h |
查看磁盘使用情况 |
ps -aux |
查看进程信息 |
top 和 htop |
命令行版的 “任务管理器” |
shutdown -h now |
关机 |
管道和重定向
Linux 中,每个进程启动时会打开三个文件描述符,分别为 stdin, stdout, stderr.
重定向的作用是,改变这几个文件描述符关联的文件,从而改变输入输出的位置。
管道的作用是,将前一个命令的标准输出作为后一个命令的标准输入。
重定向符号 n>
和 n>>
,前者表示写入,后者表示追加。n 表示文件描述符,stdin = 0, stdout = 1, stderr = 2, n 默认为 1.
# 向 hello.txt 中写入 hello
echo "hello" > hello.txt
# 查看文件内容
cat hello.txt
# 向 hello.txt 中写入 world
echo "world" > hello.txt
# 查看文件内容
cat hello.txt
# 向 hello.txt 中追加 hello
echo "hello" >> hello.txt
# 查看文件内容
cat hello.txt
管道符号 |
。
# 查看所有已安装的名字含有 xserver 的包
sudo apt list | grep xserver | grep installed
xargs 将标准输入的内容作为一条命令的命令行参数。
# 删除所有 .pyc 文件
find . -name "*.pyc" | xargs rm -rf
# 统计 .py 文件的代码行数
find . -name "*.py" | xargs wc -l
目录结构
根目录
/
├── bin # 所有用户可执行的文件
├── boot # 引导器和内核
├── dev # 设备文件
├── etc # 配置文件
├── home # 用户主目录
├── libxx # 动态库 .so
├── media # 可移出设备的挂载点
├── mnt # 临时挂载点
├── opt # 自带依赖的软件
├── proc # 包含内核和进程信息的虚拟文件系统
├── root # root 用户的主目录
├── run # 运行时文件目录,如进程 pid 文件,套接字文件
├── sbin # 只有 root 用户可执行的文件
├── sys # 包含内核和系统信息的虚拟文件系统
├── tmp # 临时文件系统
├── usr # Unix System Resources 的缩写,存放软件
└── var # 存放经常变化的文件,如日志
一切皆文件(重要的Linux哲学)
/proc
文件系统,是一个虚拟文件系统,包含进程运行的所有信息。子目录全以进程 pid 命名,/proc/<pid>/cmdline
里可以看到进程的命令行。
/sys
文件系统,是一个虚拟文件系统,包含内核中非进程信息的所有信息。
/dev
目录,包含所有设备文件。
存放软件的目录
/bin
,/sbin
,libxx
系统启动所必须的命令。/usr/bin
,/usr/sbin
,/usr/libxx
系统自带的非必需命令。/usr/local/bin/
,/usr/local/sbin
,/usr/local/libxx
用户安装的命令。/opt
存放那些自带所有依赖,不需要安装到上面那些目录的软件,如 Pycharm IDE, JDK 等。
以上说法并不严谨,因为现在系统启动需要的依赖越来越多,所以都是通过 initramfs
启动的,因此本地系统上 /bin
与 /usr/bin
的区别已经不明显,有很多要把这两层目录合并的呼声。挺有意思的一件事,具体内容请阅读 https://askubuntu.com/questions/130186/what-is-the-rationale-for-the-usr-directory
.
文件类型,ls -al
第一列的第一个字符表示文件类型。
符号 | 类型 |
---|---|
c | 字符设备,/dev/zero , /dev/null , /dev/ttyx |
b | 块设备,/dev/sdx , /dev/loopx` |
p | FIFO 设备,有名管道 |
s | socket 文件 |
d | 目录 |
l | 符号链接 |
文件系统
Linux 是支持文件系统最多的操作系统
文件系统 | 描述 |
---|---|
ext4 | 扩展文件系统,具有日志功能 |
btrfs | 支持写时复制、压缩、子卷的现代文件系统 |
vfat | FAT 文件系统 |
ntfs | Windows NT 文件系统 |
exfat | 微软开发的适合闪存设备的文件系统 |
hfs | 苹果的文件系统 |
iso9660 | 光盘和镜像文件系统 |
tmpfs | 内存文件系统,/dev/shm |
squashfs | 只读压缩文件系统,用于initramfs |
overlayfs | 支持联合挂载的文件系统,用于 Docker 容器 |
Linux 中使用 mkfs.xxfs
来创建文件系统(这个概念等同于 Windows 上的格式化磁盘分区)。
创建好的文件系统需要 mount
挂载到一个目录下才能访问,此时访问挂载的目录即访问该文件系统的根目录。
Linux 开机启动的时候会读取 /etc/fstab
文件,该文件包含分区挂载的信息,用于启动时自动挂载分区。
# 创建一个 200M 的文件
dd if=/dev/zero of=/tmp/test.img bs=1M count=200
# 创建 ext4 文件系统
sudo mkfs.ext4 /tmp/test.img
# 挂载镜像
sudo mount /tmp/test.img /mnt
# 修改权限
sudo chown wqy /mnt
# 测试文件系统,接下来的操作就和一个普通分区没有区别了
cd /mnt
echo hello > hello.txt
注:在这个镜像上测试各种文件系统的创建吧,记得要先 umount
才能格式化哦。
用户管理
Linux 是一个多用户的操作系统,同一时刻可以有多个用户同时登陆。
/etc/passwd
保存账户和密码信息/etc/shadow
保存加密过的用户密码/etc/group
保存用户组信息/etc/gshadow
保存加密过的用户组密码
创建一个用户并登录
# 添加用户组 test
sudo groupadd test
# 添加用户 test,创建主目录 /home/test
sudo useradd -m -d /home/test test -g test
# 修改用户默认 shell 为 bash
sudo usermod -s /bin/bash test
# 为用户设置密码
sudo passwd test
# 按 ctrl+alt+f2 切换 tty,登录用户
# 登录后查看当前目录
pwd
ls -al
# 启动桌面环境,按 ctrl+alt+fx 在两个桌面环境间切换
startx
通过以上的操作,可以看出 Linux 是真正的多用户操作系统,新用户登录并没有使老用户下线。
但是 /dev/console
只有一个,只有处于激活状态的 tty 才能向显示器输出图像、处理用户输入、播放音频等(可以试一下哦)。
切换回老用户,尝试删除新用户主目录下的文件,并没有写权限。
cd /home/test
rm -f .bashrc
# 输出
# rm: 无法删除'.bashrc': 权限不够
# root 用户可以删除
sudo rm .bashrc
删除刚刚创建的用户
# 先注销刚刚登录的用户
# 删除用户和其主目录,和同名的用户组
sudo userdel -r test
文件系统权限
执行 ls -al
命令时,第 1, 3, 4 列显示了文件的权限信息,示例如下。
-rw-r--r-- 1 wqy wqy 4867 3月 26 13:34 .bashrc
第三列 wqy
表示这个文件的所有者 (owner) 是 wqy。
第四列 wqy
表示这个文件所属的用户组 (group) 是 wqy。
第一列 -rw-r--r--
共有10个字符
- 第一个字符表示文件类型,其值可为
d
目录,-
普通文件,l
链接文件,b
块设备文件,c
字符设备文件 - 后9个字符,每三个一组,每组分别表示,所有者权限,用户组权限,其它用户权限,一组的三个字符为
r
可读权限,w
可写权限,x
可执行权限。
权限还可以使用八进制编码来表示
类型 | 读 | 写 | 执行 |
---|---|---|---|
- | r | w | x |
0 | 4 | 2 | 1 |
0644 -rw-r--r--
0755 -rwxr-xr-x
0666 -rw-rw-rw-
对于之前的 .bashrc
文件 :所有者为 wqy,用户组为 wqy,类型为普通文件,所有者可读写,同用户组用户可读,其它用户可读。
回想之前创建 test
用户后,其主目录下满足什么条件的文件可以不以 root 权限删除?
- 所有者或用户组为
wqy
- 权限为
-rw-r--rw
# 修改所有者
sudo chown wqy .bashrc
# 修改用户
sudo chgrp wqy .bashrc
# 修改文件权限
sudo chmod 0646 .bashrc
# 也可以用 chmod [ugoa]+[rwx] 来修改权限,ugoa 依次表示所有者、用户组、其他用户、全部用户
sudo chmod o+w .bashrc
服务管理
服务 (service) 是一个(在后台)长期运行的程序。例如 Web 服务,数据库服务,shadowsocks 等。
以 systemd 为例
systemctl status [service] # 查看服务状态
systemctl start <service> # 启动服务
systemctl stop <service> # 停止服务
systemctl enable <service> # 开机启动服务
systemctl disable <service> # 开机不启动服务
信号/软中断
中断是由硬件产生中断信号,CPU暂停当前进程,执行中断处理程序的过程。中断的存在为操作系统提供了抢占式进程调度的支持。
信号是在软件层面上对中断的一种模拟,所以也叫软中断。信号可视为进程间进行异步通信的一种方式。信号由硬件(键盘)和软件(kill, raise 命令) 产生,内核将信号加入信号队列,在接收信号的进程执行时将执行信号处理函数。
信号名称 | 值 | 默认动作 | 触发 |
---|---|---|---|
SIGHUP | 1 | 终止进程 | 用户退出Shell时,由该shell启动的所有进程都会收到这个信号。 |
SIGINT | 2 | 终止进程 | ctrl+c |
SIGQUIT | 3 | 终止进程 | ctrl+\ |
SIGKILL | 9 | 无条件终止进程 | kill -9 |
SIGTERM | 15 | 终止进程,可以被阻塞或终止,以便在退出时回收资源 | kill -s SIGTERM |
SIGSTP | 18,20,24 | 挂起进程,可以用 fg/bg 恢复执行前台或后台的进程 | ctrl+z |
注:ctrl+d
表示 EOF
,它不是一个信号,但是可以表示标准输入结束。
向指定 pid 的进程发送信号
kill -s SIGXXX <pid>
kill -n $SIGNUM <pid>
kill -$SIGNUM <pid>
使用 kill -l
查看所有支持的所有信号
wqy@wqy-PC:~$ kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
使用 stty -a
查看信号快捷键
wqy@wqy-PC:~$ stty -a
speed 38400 baud; rows 34; columns 91; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>;
swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V;
discard = ^O; min = 1; time = 0;
-parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany
-imaxbel iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke
-flusho -extproc
Linux 的安装和启动
Linux 安装程序做了什么?
- 复制根文件系统到目的分区
- 设置语言、时区
- 创建用户
- 安装内核和
initramfs
- 安装引导器
GRUB
/syslinux
Linux 的启动过程
- BIOS/UEFI 启动引导器
- 引导器装载内核和
initramfs
- 内核将
initramfs
挂载为根目录 - 内核执行
/sbin/init
来初始化系统、设置硬件驱动 /sbin/init
在加载完驱动后,挂载真正的根目录,切换根文件系统- 执行根文件系统中的
/sbin/init
- 移除
initramfs
, 系统启动完成
本地文件系统中的 /sbin/init
是第一个用户进程,所有进程都是它的子进程,它不能被杀死。
系统启动时,它负责启动各种开机启动的服务,包括sshd
, 桌面环境等。
常见的 /sbin/init
有
SysV Init
已过时,同步阻塞Upstart
Ubuntu 15.04 之前默认使用,支持异步任务Systemd
主流发行版默认,支持异步任务
特性 | 命令 | 配置 | |
---|---|---|---|
SysV Init | 基于运行级别 | service | /etc/init.d |
Upstart | 事件驱动 | initctl | /etc/init |
Systemd | 事件驱动 | system-ctl | /usr/lib/systemd |
有趣的命令
fortune
打印一条随机的有正能量的谚语。
cowsay
打印一头牛说话的 ASCII 字符画。
它俩组合起来可以产生奇妙的化学反应。
fortune | cowsay
____________________________________
/ They have been at a great feast of \
| languages, and stolen the scraps. |
| |
| -- William Shakespeare, "Love's |
\ Labour's Lost" /
------------------------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
License
作者:王淇营
本作品采用知识共享 署名-非商业性使用-相同方式共享 2.5 中国大陆 许可协议进行许可。要查看该许可协议,可访问 http://creativecommons.org/licenses/by-nc-sa/2.5/cn/ 或者写信到 Creative Commons, PO Box 1866, Mountain View, CA 94042, USA。