Linux-Part.1
Linux 总是无处不在的,或许我对他并不陌生,但从未系统学习过,这篇文章将记录我系统学习 Linux 的过程经历,遇到的问题,总结的笔记,便于我留存记录,也供大家参考学习
学习路线可参考:https://labex.io/zh/linuxjourney
什么是 Linux ?
回溯到 1969 年,当时贝尔实验室的 Ken Thompson 和 Dennis Ritchie 开发了 UNIX 操作系统,十多年后,Richard Stallman 发起了 GNU 项目,目标是创建一个完全自由和开源的类 UNIX 操作系统,但统一的内核始终未能完成
内核是操作系统的核心,它充当桥梁,使硬件能够与软件通信。内核管理系统资源,例如 CPU、内存和外围设备
到 1991 年,Linus 发明了 Linux 内核,填补了 GNU 操作系统缺失的那一块拼图
尽管我们通常说 Linux 操作系统,但从技术层面来讲,Linux 指的是 Linux 内核,而使用 Linux 作为内核的操作系统,确切来说成为 Linux 的发行版
比较流行的发行版有很多,本篇文章笔者采用的是 Ubuntu 24.04.3 LTS
关于如何在 MacOS 安装 Ubuntu 虚拟机,可以参考我之前的博客:https://kirito.cloud/2025/2.%E5%88%9D%E5%A7%8B%E5%8C%96multipass%E8%99%9A%E6%8B%9F%E6%9C%BA/
命令行操作
什么是 Shell ?
Shell 是一个强大的应用程序,它可以接受你输入的命令,传递给操作系统执行
或许你也听过“终端”这样的词汇,终端只是一个普通的应用程序,他的作用是为你打开一个 Shell 会话
Shell 有很多,大部分发行版的默认 Shell 是 bash ,其他常见的 Shell 还有 zsh,fish 等
常用命令
echo输出命令行参数1
echo Hello World
pwd打印当前工作目录的绝对路径Linux 中,整个文件目录以根目录(用
/表示)作为顶级目录,每个子目录分支成多个子目录,形成目录树1
pwd
cd切换工作目录支持绝对路径和相对路径
.:当前目录..:当前目录的上一级目录~:用户目录,通常是/home/xxx-:上一次你所在的目录
1
cd ~
ls列出当前工作目录的目录和文件Linux 命令都可以在后面加上选项参数,
--后跟选项全名,-后跟选项简写例如
ls --all和ls -a效果是一样的ls -a:列出所有目录和文件(包括隐藏文件,隐藏文件以.开头)ls -l:以长格式显示权限 | 链接数 | 所有者名称 | 所有者组 | 文件大小 | 修改时间 | 名称
1
2
3
4
5
6
7 ~ ❯ ls -l
总计 95840
drwxrwxr-x 3 ubuntu ubuntu 4096 12月 2 12:18 go
-rw-rw-r-- 1 ubuntu ubuntu 58130616 9月 25 11:11 kubectl
-rw-rw-r-- 1 ubuntu ubuntu 64 9月 25 11:11 kubectl.sha256
-rw-rw-r-- 1 ubuntu ubuntu 39991324 9月 24 20:25 minikube_latest_arm64.deb
drwxrwxr-x 12 ubuntu ubuntu 4096 12月 4 10:26 mysrc
不同选项也可以组合搭配使用 例如
ls -alls后面跟的参数可以是目录,这样会列出该目录下的内容,也可以是文件,这样会列出这个文件本身,因此常用ls -l myfile.txt来查看文件的相关信息ls -d:把目录当成普通文件列出,而不是列出目录内容,常用ls -ld mydir查看目录信息
touch更改时间戳 / 创建新文件1
touch newFile
在当前目录下创建名为
newFile的空文件,如果newFile已经存在,则会更新文件的时间戳touch -r file1 file2:把file2的时间戳更新为file1的时间戳touch -d "2024-01-01 12:12" file:把file的时间戳更新为指定值(日期字符串格式可以是任意格式)
file查看文件类型与 Windows 等其他操作系统不同,Linux 并不认识文件的后缀名,文件的类型不由后缀名决定,而由文件的内容本身决定,例如:
1
2
3
4 ~/mysrc ❯ touch file1.png
~/mysrc ❯ echo "hello" > file1.png
~/mysrc ❯ file file1.png
file1.png: ASCII text这里
file1.png并不是图片文件,而是普通的文本文件但通常,为文件加上约定俗成的后缀名,可以便于编辑器和其他操作系统识别文件类型
cat查看文件内容1
cat myfile
会将
myfile的内容输出到屏幕上也可以跟多个参数
1
cat file1 file2
less文件查看器当文件内容过多,使用
cat查看文件内容不太便利,less允许你分页查看文件的内容键入
less后,你会进入文件导航模式- 使用上下箭头逐行翻页,使用
page up/down整页翻页 - 使用
g和G跳转到文件开头 / 结尾 - 使用
q来退出 - 输入
/Linux,则会高亮文件中所有的Linux关键字,用n跳转到下一次出现,N跳转到上一次出现
- 使用上下箭头逐行翻页,使用
history输出使用过的历史命令列表- 使用方向键 向上箭头 来切换你的历史命令记录,使用
!!来切换到上次使用的命令,再次按下enter即可执行 ctrl + r是最强大的历史命令查询器,按下ctrl + r会出现搜索框,在框内输入”Linux”则会显示最近一次使用过的带有“Linux”关键字的命令,此时不断按下ctrl + r则可以切换到更早的匹配项history -c:清空所有历史命令记录history -d 101:删除第101条历史记录
- 使用方向键 向上箭头 来切换你的历史命令记录,使用
clear清空屏幕cp复制文件到指定目录下1
cp myfile /home/ubuntu/mysrc
也可以在复制的时候指定复制后的文件名
1
cp myfile /home/ubuntu/mysrc/file2
这会创建
file2,并且复制myfile的内容cp -r:递归复制,通常用于复制目录*:通配符,例如cp -r ~/mysrc/* ~/target/会把/mysrc下的所有内容复制到/target下,注意,如果是``cp -r ~/mysrc ~/target/,则会复制整个mysrc目录,包括mysrc`这一层级cp -f:强制覆盖同名文件cp -i:交互式,会在覆盖同名文件前向你确认cp -p:保留元数据,通常复制时会出现文件时间戳和文件所有权变化的情况,-p可以确保这些元数据不发生变化
mv移动文件和目录 / 重命名文件和目录1
2
3mv file1 file2 ~/mysrc/target
mv file1 file2
mv dir1 dir2mv -i:交互式,会在覆盖同名文件前向你确认mv -b:覆盖同名文件的同时,会自动创建被覆盖旧文件的备份,并命名为原文件名 + ~mv -v:会输出mv命令正在执行的操作,显示正在移动或者重命名的文件
mkdir创建目录mkdir:创建多级目录
rm删除文件rm -f:强制删除rm -r:递归删除,常用于删除目录及其所有内容,rm无法直接删除目录rm -i:交互式删除,每个文件删除前都会提醒你确认rmdir:删除空目录
find查找文件 / 目录find -name:根据名称查找文件 / 目录1
find -name file1
find -type:限制查找类型1
2find -type d -name mysrc
find -type f -name file1.txt与
find不同,grep也用于查找,但常用于在文本中查找匹配内容
find默认会递归查找给出目录及其所有的子目录man查看命令手册1
man ls
大部分命令带有选项
--help,也可查看使用说明1
2ls --help
ls -h这里推荐一个浏览器端的速查链接:https://tldr.sh/,方便使用翻译插件,英语weaker有救了(bushi)
除此之外,
whatis可以快速返回一个简短的命令描述1
2 ~/mysrc ❯ whatis man
man (1) - 系统参考手册的接口alias创建别名1
2alias back='cd ..'
unalias back # 删除别名键入
back即可返回上级目录,这样的别名只在当前会话生效,退出终端便会清除,unalias也是如此想要使别名永久生效,需要写入配置文件
~/.bashrc(根据不同 shell 决定)1
2写入...
source ~/.bashrc # 使配置生效 也可以关闭会话重新登录exit退出会话
文本操作
标准输出 / 输入
stdout/stdin1
echo "hello world" > file1
这会在当前目录下创建一个新文件
file1,内容是hello world默认情况下,
echo会把命令行参数发送到stdout,在你的屏幕上显示,看起来像回显一样>是一个重定向符号,默认发送到stdout的数据,可以通过>来拦截,发送到一个新的目的地然而,
>重定向的内容会覆盖文件中原有的所有内容,如果你想要追加而不是覆盖,可以使用>>1
echo "hello linux" >> file1 # 会自动在file1的内容结尾加上换行符
既然标准输出会显示在你的屏幕,那么标准输入就是你键入的内容
当我们使用
cat命令,不加任何参数时,会打开一个交互式的场景,此时你输入hello,屏幕会再次回显一个hello,这里你输入的hello就时标准输入,回显的hello就是标准输出这里
cat的作用就是接受标准输入,传递给标准输出配合重定向符号,我们可以实现:
1
2把 file1 的内容添加到 file2 的结尾
cat < file1 >> file2cat也可以直接读取文件内容,而不是从标准输入读取,所以下面这样也有同样的效果1
cat file1 >> file2
标准错误
stderr1
2 ~/mysrc ❯ ls bbb > file1
ls: 无法访问 'bbb': 没有那个文件或目录这里的报错信息,如果是标准输出,按理来说会重定向到
file1中,然而却打印到了屏幕上,这是由于另一个 I / O 流在起作用,标准错误stderr默认情况下,
stderr和stdout都会输出到屏幕上,这里的>只重定向了标准输出,而没有重定向标准错误,因此错误信息仍然会打印到屏幕上,要控制标准错误,先要简单理解一下文件描述符fd文件描述符是一个非负整数,内核通过它来识别打开的文件或流,默认的文件描述符是:
0:标准输入1:标准输出2:标准错误
而重定向符号
>实际上是1>的缩写,<实际上是<0的缩写如果想要重定向标准错误,应该这样:
1
2ls bbb 2> file1
ls bbb 2>> file1如果我希望标准输出和标准错误都能定向到file1,可以将两者合并
1
2ls bbb > file1 2>&1
ls bbb >> file1 2>&1意思是先重定向标准输出,然后在结尾再把标准错误重定向到标准输出所在的位置,即
2>&1Shell 还为我们提供了一种更简单的缩写方法
1
2ls bbb &> file1
ls bbb &>> file1如果我们希望把错误信息完全丢弃,既不输出到屏幕上,也不保存到文件中,这时有一个特殊的文件
/dev/null,有些人称之为“黑洞”,因为任何输出到该文件的数据都会被丢弃1
ls bbb >> file1 2>/dev/null
管道和
tee1
ls -a | less
|是管道,它可以获取左侧命令的标准输出,放入管道内,将其作为右侧命令的标准输入1
ls -a | tee file.txt
tee可以将输出流分为两个方向输出,此时ls的内容会同时输出到标准输出和file.txt中使用管道和
tee过滤的数据流可以继续进入下一级管道,例如我要实现功能:列出当前目录的所有内容,保存到
file1中,同时在屏幕上打印名字中带有file的文件1
ls -a | tee file1 | grep "file"
tee和|的一个常见组合用法是提升权限,例如:1
sudo echo "hello" > /root/demofile
这里的
sudo只对echo生效,而重定向符号没办法使用sudo来提升权限,因此需要:1
2echo "hello" | sudo tee /root/demofile
这里的 echo 不需要sudoenv环境变量使用
env命令可以查看当前会话的所有环境变量,环境变量和其他编程语言中的变量一样,有变量名和值,可以使用$查看变量的值1
echo $HOME
普通的变量与环境变量的区别在于,是否被其他进程可见,Linux 的进程管理中,子进程只会继承父进程的环境变量,而不会继承父进程的普通变量,我们可以通过
export来声明环境变量1
2TEST=1 # 子进程不可见
export TEST=2 # 子进程可见这样声明的环境变量只在当前 Shell 会话中生效,一旦关闭终端,变量将不再存在
如果你需要让环境变量一直生效,只需要将其添加到 Shell 的启动文件中即可,例如
~/.bashrc(或是.zprofile .zshrc .bash_profile等 由 Shell 决定),这样每次打开终端,Linux 会自动加载这些文件中的环境变量在这些环境变量中,有一个特殊的环境变量
PATHecho &PATH会返回一个以:冒号作为分隔符的列表当你输入一个命令时,系统会先从内置库寻找命令,如果没有找到,就会从
PATH变量中开始找例如直接键入
java --version,可能会出现command not found的错误提示,当你把 java 添加到PATH环境变量中,就可以执行java的相关命令了cut输出切取的字符1
echo "Hello! Linux is so interestring." > greeting.txt
cut -c 8 greeting.txt:输出第8个字符L(空格也算一个字符)cut -f 1 -d '!':按!进行分割,输出第一部分(若不加-d,默认以tab作为分隔符)值得注意的是,
!在 Linux 中有特殊含义,用于引用历史记录,这种引用在双引号内仍然会生效,如果想要输出字符!,需要在感叹号前添加转义或者使用单引号,"\!"或'!'
paste输出合并的字符1
2
3
4
5用 vim 编辑 greeting.txt 为以下内容
Linux
is
so
interestingpaste -s greeting.txt:输出Linux is so interesting,默认以tab作为分隔符paste -s -d ' ' greeting.txt:-d指定分隔符
head查看文件开头head /var/log/syslog:默认会输出文件的前10行head -n 15 /var/log/syslog:使用-n指定行数
tail查看文件末尾tail /var/log/syslog:默认输出末尾10行tail -n 15 /var/log/syslog:使用-n指定行数tail -f /var/log/syslog:使用-f实时监控文件
expand与unexpandexpand hello.txt:把文本中的tab转化为空格输出unexpand -a hello.txt:把文本中的空格转化为tab输出(默认情况下,unexpand只转换每行开头的空格。-a选项告诉unexpand command将所有 8 个空格的实例转换为制表符)
如果要将转化后到结果保存到文件,需要
expand hello.txt > result.txtsort对行排序
以行为分隔符,对元素进行排序
sort hello.txt:默认是字典排序sort -r hello.txt:反向排序sort -n hello.txt:数值排序,先比较行首的数字大小(非数字算作0),数字后的部分按字典排序
tr转换文本echo "hello linux" | tr a-z A-Z:输出HELLO LINUXecho "hello 123 linux" | tr -d 0-9:-d删除内容,输出hello linuxecho "hhhelo linuxxx" | tr -s 'h':把多个连续的h压缩成一个h如果有两个参数,会把前者压缩为后者,例如
echo "hhhelo linuxxx" | tr -s 'h' 'H'如果要输出
hello linux,如下:1
2
3echo "hhhello linuxxx" | tr -s 'h' \
| tr -s ' ' \
| tr -s 'x'这里的
\是 Linux 中的换行符,表示命令还没输完,输入\按下回车后不会执行命令,而是会继续输入未完成的命令实际上,Linux 中的
|管道符号同时兼备换行的作用,因此上面的命令也可以写成这样:1
2
3
4echo "hhhello linuxxx" |
tr -s 'h' |
tr -s ' ' |
tr -s 'x'
uniq重复行处理新建一个
reading.txt,内容如下:1
2
3
4
5
6
7book
book
paper
paper
article
article
magazineuniq reading.txt:输出删除相邻的重复行后的结果(处理后的结果不会修改原文件)只会删除相邻的重复行,如果要删除所有的重复行,需要
sort reading.txt | uniquniq -c reading.txt:统计相邻行重复出现的次数uniq -u reading.txt:仅输出重复的行uniq -u reading.txt:仅输出不重复的行
wc数据统计1
2
3 ~/mysrc ❯ wc reading.txt
9 8 53 reading.txt
行数 单词数 字节数wc -l:仅显示行数wc -w:仅显示单词数wc -c:仅显示字节数
nl对行编号输出编号后的结果
1
nl reading.txt
grep内容搜索1
grep book reading.txt
搜索
reading.txt中含有book的内容如果我们要搜索
reading.txt中含有关键字-v的文本,grep "-v" reading.txt是无效的,此时的-v会被识别成grep的选项,即便你加了双引号,grep提供了-e选项,明确表示后面是你要匹配的内容,而不是选项1
grep -e "-v" reading.txt
除此之外还有一种更通用的方法
--,Linux 中的--是一个万能分界符,它明确表示,--之后的内容都将作为参数,不会被命令误当成选项解析1
2
3grep -- -v reading.txt
删除一个名为 -f 的文件
rm -- -fgrep -i:搜索时不区分大小写grep -o:仅提取匹配项(默认会输出含有匹配项的整行内容),常与正则表达式结合用于提取符合格式的内容grep -f pattern.txt log.txt: 当你有多个模版时,把他们放在pattern.txt,搜索log.txt中符合模版的内容1
2
3
4
5
6
7
8
9
10pattern.txt
info
warn
error
log.txt
[info]message...
[warn]message...
[error]message...
[info]message...
正则表达式
参考https://labex.io/zh/lesson/regular-expressions-regex
(我一般都让 AI 写正则?)
文本编辑器
Vim 应该是命令行环境中最常用的文本编辑器,这里只简单介绍 Vim 的使用方法
有关 vim 的配置信息,通常在~/.vimrc文件中,这里留存一份我个人使用的配置文件:
1 | " 启用语法高亮 |
vim hello.txt使用 vim 编辑器打开 / 新建hello.txt文件vim有四种模式,普通模式,尾行模式,编辑模式,视图模式在普通模式下,使用
i切换到编辑模式,:切换到尾行模式,v切换到视图模式,esc切换回普通模式由于我在配置文件中加了
set mouse=a,当你用鼠标选中一段文本时,此时 vim 会自动为你切换到视图模式使用小技巧:
gg跳转到文件开头,G跳转到文件结尾0跳转到当前所在行行首,$跳转到当前所在行行尾键入
/来进入搜索模式,输入搜索内容后回车,vim 会高亮出所有匹配项,使用n和N跳转到下一个 / 上一个匹配项(还有一个?也用于搜索,区别是/用于从当前光标开始向后搜索,?是向前搜索,并且n / N的方向也会根据/和?来发生改变):1,20d后回车,可以删除[1, 20]行的内容鼠标模式很好用,用鼠标选中文本后,按下
d删除,按下y复制,按下p粘贴(注意 vim 的剪切板与你的系统剪切板不同步)
保存与退出:
:w:保存更改的内容:q:退出,如果你有未保存的改动时,使用:q会退出失败,如果你想放弃更改并退出,使用:q!:wq:保存并退出,你也可以在普通模式下按下ZZ,快速执行保存并退出的操作
撤销更改
类似 windows 里的
ctrl + z,vim 使用u来撤销更改,类似ctrl + shift + z,vim 使用ctrl + r来撤销撤销的更改
用户管理
Linux 中的进程会以启动该进程的用户的身份运行,每个用户都有自己的个人主目录/home/xxx,在这些普通用户之外,root是 Linux 中的超级用户,拥有最高的权限。当出现Permission denied时,普通用户可以通过sudo来以 root 权限执行命令
su命令1
su <username>
这会为你打开一个新的 shell 会话,只要你知道目标用户的密码,可以使用
su来切换到 Linux 上的任意用户如果只输入
su,默认会尝试登录 root 用户不建议长期在 root shell 下执行命令,因为你在此 shell 中的操作不会记录到你个人用户的日志中,尽量使用
sudosudo都有哪些用户可以使用
sudo呢?实际上,允许使用sudo的用户由配置文件/etc/sudoers决定,编辑此配置文件,Linux 提供了一个专门的命令visudo你应该总是通过
visudo而不是sudo vim /etc/sudoers来编辑这个文件,前者会进行语法检查确保安全性,以免你把自己锁在sudo权限之外,导致不能再编辑此文件/etc/passwdLinux 识别用户和组,是通过
UID和GID,每个用户和组都有独特的UID和GID,用户的相关信息存储在/etc/passwd这个文件中,当使用cat查看该文件时,可能会出现很多条目,其中有很多是系统为了隔离权限而创建的用户,例如mysql,并不能直接登录,目前我们暂时只关注人类用户,也就是可以登录的用户1
2root:x:0:0:root:/root:/bin/bash
ubuntu:x:1000:1000:Ubuntu:/home/ubuntu:/usr/bin/zsh每个条目被用
:分隔成了七个字段,分别代表:用户名
密码:但为了安全考虑,用
x来占位,真实的密码会被加密存储在/etc/shadow中,每个条目仍然以:分隔,第一个字段代表用户名,第二个字段代表加密密码,后面是密码更改日期…有效期…之类的,可以不用在意用户id(
UID):用户的唯一标识符,root 用户的 UID 永远是 0组id(
GID):主组id,每个用户至少需要在一个主组内实际上,每个用户在创建之初,系统会自动创建一个组作为该用户的主组,并且组名=用户名,
GID=UID用户可以退出默认的主组,加入其他主组,除了一个必须的主组外,用户可以自由的加入任意多个附属组
GECOS 字段,用于添加备注信息,可以不太关注
用户目录的绝对路径
用户的默认 shell
不建议手动编辑
/etc/passwd,Linux 通常会提供其他专用命令来修改用户信息/etc/group1
2root:x:0:
docker:x:988:ubuntu与
/etc/passwd类似,/etc/group的每一行代表一个组,字段用:分隔,分别代表:- 组名
- 组密码:这是一个历史遗留项,现在的 Linux 版本已经很少使用组密码了,常见
x占位符 - 组id(
GID) - 附加成员:显示这个组的附加成员有哪些,主成员不会显示在这里
用户管理命令
创建用户和组:核心命令是
useradd,下面以创建用户sakura为例说明整个过程:先确保系统中没有名为
sakura的用户,可以使用id sakura查看先创建组,名为 sakura(默认主组名和用户名相同)
1
sudo groupadd sakura
此时,系统会自动为组 sakura 分配 GID,并写入
/etc/group,可以看到,这里我的 GID 是 1001
创建用户 sakura
1
2
3
4
5sudo useradd \
-m \
-g sakura \
-s /bin/shell \
sakura-m表示自动创建用户家目录,相当于:1
2
3mkdir /home/sakura
cp -a /etc/skel/. /home/sakura/
chown -R sakura:sakura /home/sakura值得注意的是,
/etc/skel/目录下的内容是用户的家目录模版,因此每个用户在创建家目录时都会拷贝其中的内容,里面通常包含.profile .bashrc等文件,这意味着我们可以编辑/etc/skel/中的内容来使新建的用户自动继承某些配置,这是一种很常见的做法-g指定主组,系统会确保 UID = GID-s指定默认 shell,通常为 bashsakura用户名
此时,系统会自动把 sakura 用户的信息写入
/etc/passwd
为 sakura 设置密码
此时
/etc/shadow中显示 sakura 用户的密码栏目为!,表示我们还没有给用户设置密码,该用户暂时无法用于登录1
sudo passwd sakura # 给 sakura 用户设置密码
设置之后,再次查看
/etc/shadow,sakura 加密后的密码已经正常显示
至此,sakura 用户已经创建成功,其实在 Debian 系等发行版,内置了
adduser命令,看起来和useradd很像,但它涵盖了上述 1 ~ 3 的完整步骤,可以方便地直接使用sudo adduser sakura来快速创建用户。然而,在 Arch 系等其他发行版则不提供该内置命令,因此在写脚本的时候需要注意跨平台的问题,useradd仍是更普遍更底层的方式。
修改用户 / 组信息
sudo passwd sakura:修改 sakura 的密码sudo usermod -g 新组 sakura:修改 sakura 的主组为 新组sudo usermod -aG 附加组 sakura:添加附加组,可以把附加组设置为 sudo,赋予 sakurasudo的权限sudo gpasswd -d sakura 组名:把 sakura 从附加组移除
删除用户 / 组
1
sudo userdel sakura
这样仅能删除 sakura 用户本身,如果还要删除家目录,加上
-r1
sudo userdel -r sakura
在某些 Linux 的发行版中,如 Debian 系,若用户的主组内只有这一个用户,当用户被删除时,组也会被自动清理。如果你想手动删除一个组,可以用以下命令:
1
sudo groupdel sakura
权限
文件权限
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 ~/mysrc ❯ ll
总计 55M
drwxrwxr-x 3 ubuntu ubuntu 4.0K 10月 19 23:28 boss
drwxrwxr-x 7 ubuntu ubuntu 4.0K 1月 5 18:03 doki
-rw-r--r-- 1 ubuntu ubuntu 55M 12月 2 12:10 go1.25.1.linux-arm64.tar.gz
-rw-rw-r-- 1 ubuntu ubuntu 21K 2月 24 15:23 hello2.txt
-rw-rw-r-- 1 ubuntu ubuntu 20K 2月 24 15:20 hello.txt
drwxrwxr-x 8 ubuntu ubuntu 4.0K 11月 14 16:00 jenkins-demo
drwxrwxr-x 2 ubuntu ubuntu 4.0K 10月 20 12:22 k8s-wordpress
drwxrwxr-x 3 ubuntu ubuntu 4.0K 12月 4 10:26 learn-go
drwxrwxr-x 2 ubuntu ubuntu 4.0K 10月 10 20:45 myk8s
drwxrwxr-x 2 ubuntu ubuntu 4.0K 10月 20 01:17 mynginx
drwxrwxr-x 2 ubuntu ubuntu 4.0K 10月 10 15:43 nu
drwxrwxr-x 3 ubuntu ubuntu 4.0K 12月 4 10:25 project
drwxrwxr-x 4 ubuntu ubuntu 4.0K 10月 13 16:46 tvsos第一列代表文件类型和权限
1
d | rwx | rwx | r-x
d:目录,-:文件,l:符号链接r:读取权限,w:写入权限,x:执行权限,-:无权限三组
rwx分别代表不同级别的访问权限:所有者,默认情况下是创建这个文件 / 目录的用户
所有组,默认情况下是创建这个文件 / 目录的用户所在的主组
其他人,指既不是所有者也不在所有组内的用户
更改权限
最常用的命令是
chmod符号模式
u:所有者,g:所有组,o:其他,a:全部1
2
3
4
5
6
7
8为用户添加执行权限
chmod u+x myfile
同时为组和其他人添加执行和写入权限
chmod go+rx myfile
这样也是合法的
chmod g-x,o-xw myfile # 注意 , 后面不要多加空格
不指定 who,会给 ugo 同时加上权限
chmod +x myfile八进制模式
4 - r,2 - w,1 - x,这样任意几个数字的和都是唯一的1
2chmod 664 myfile
chmod 775 mydir新建的文件的默认权限是
664,由于目录需要x权限才能进入,所以一般新建目录的默认权限是775
更改所有权
更改用户所有权
1
2把 myfile 的所有权更改为 sakura
sudo chown sakura myfile更改所有组
1
2把 myfile 的所有组改为 staff
sudo chgrp staff myfile同时更改所有用户和组
1
sudo chown sakura:staff myfile
umask前面说过,Linux 中默认创建的文件权限是
664,目录权限是775,实际上,造成这样的原因是umask的存在,Linux 系统默认把文件的最大权限值当作666(系统默认文件是不可执行的),把目录的最大权限值当作777,当新建文件 / 目录时,权限值会被设定为 最大权限值 -umask在终端输入
umask,可以看到,大部分系统的默认umask是002,因此新建文件:
666 - 002 = 664新建目录:
777 - 002 = 775换句话说,
umask的作用是移除某些权限,你可以在终端中输入umask 021来设置umask的值为 021,但这种更改不是永久的,如果想要永久更改 umask,需要修改.profile 或 .bashrc 等文件,加入以下内容1
umask 021 # 修改 umask 为 021
一般来说使用默认的 002 就好
SUID与SGID之前我们说过,可以用
passwd更改用户密码,此时系统会更改/etc/shadow中的内容1
2 ~/mysrc ❯ ls -l /etc/shadow
-rw-r----- 1 root shadow 1010 2月 24 22:20 /etc/shadow然而,查看这个文件,发现他的所有者是 root,且只有 root 才有写入权限,为什么我们能通过
passwd来更改这个文件的内容呢?1
2 ~/mysrc ❯ ls -l /bin/passwd
-rwsr-xr-x 1 root root 72056 5月 30 2024 /bin/passwd这里发现了一个新的权限位
s,这个权限位称为SUID(Set User ID),当其他用户执行这个文件时,SUID将赋予此用户该文件所有者的权限,在这里也就是 root,所以当用户允许passwd时,是以 root 的身份执行的你也可以用
chmod来给自己的文件设置SUID1
2
3sudo chmod u+s myfile
等价写法
sudo chmod 4755 myfileSUID可以用4表示,加在权限集的前面,你可能会见到SUID出现大写S的情况,这是无效的写法,表示虽然加了SUID,但是没有给予文件执行权限类似
SUID,SGID(Set Group ID)允许其他用户执行文件时,赋予此用户该文件所有组的成员权限1
2
3sudo chmod g+s myfile
等价写法
sudo chmod 2755 myfileSGID的数字表示是2进程权限
可以读一下这个大致了解 https://labex.io/zh/lesson/process-permissions
粘滞位
在 Linux 中,有这样一个目录
/tmp,任何用户都可以访问该目录,并且在该目录下存放 / 修改自己的临时文件1
2 ~/mysrc ❯ ls -ld /tmp
drwxrwxrwt 17 root root 4096 2月 25 15:25 /tmp注意到这里其他用户有一个新的权限位
t,表示设置了粘滞位。它的作用是即使所有用户都可以在这个目录自由的读写,但是他们无法对其他用户的文件进行rm操作,这可以防止一个用户干扰另一个用户的工作1
2
3
4设置粘滞位(只能对目录设置)
sudo chmod +t mydir # 不能写成 o+s
等价写法
sudo chmod 1755 mydir粘滞位的数字表示是
1
进程
进程是指在系统上正在运行的程序,由 Linux 内核管理,每个进程会被分配一个唯一的 id,即PID,通常在创建新进程时 PID 会按顺序分配。
ps输出与当前终端会话相关的进程列表快照1
2
3
4
5
6
7
8 ~/mysrc ❯ ps
PID TTY TIME CMD
68227 pts/0 00:00:03 zsh
68231 pts/0 00:00:00 zsh
68260 pts/0 00:00:00 zsh
68261 pts/0 00:00:00 zsh
68263 pts/0 00:00:00 gitstatusd-linu
69183 pts/0 00:00:00 psPID:进程唯一 idTTY:控制该进程的终端TIME:进程从启动以来,占用 CPU 的总时间,不能代表进程的运行时间,因为大部分时间进程都在睡眠 / 挂起,只有被调度时才会占用 CPUCMD:启动该进程的命令
ps的选项有两种不同的风格,常用的组合分别是ps aux和ps -ef,前者作为日常使用,后者则更常见于脚本中top进程实时监控ps是针对某一时刻的进程快照,而top可以实时监控进程资源,每隔几秒便会刷新一次,常用于排查进程占用资源异常tty在进程列表中,有一个字段
TTY,称为控制终端,在早期的计算机中,人们通过Teletype(电传打字机)来输入命令和计算机进行交互,tty 得名于此。在现代的 Linux 系统中,tty 指为进程提供标准输入和输出的终端。终端有两种类型:终端设备和伪终端
终端设备
在 Linux 中,真正的终端设备通常指 虚拟控制台(Virtual Console)。在物理机上直接安装 Linux 后,可以通过
Ctrl + Alt + F1 ~ F6切换到这些控制台,它们对应/dev/tty1、/dev/tty2等设备。此时你会看到只带有命令提示符的黑框框,这些终端由内核直接管理,不依赖图形界面,即使图形系统崩溃,也可以正常登录和操作。伪终端
伪终端是我们日常最常用的,也称为
pty,当我们在图形化的操作系统下打开终端应用程序时,此时出现的黑框框实际上是pty,输入命令ps检查TTY字段,会看到输出为pts/0,pts/1等
这里 pty 和 pts 不是打错了,详细概念可以看:https://dev.to/napicella/linux-terminals-tty-pty-and-shell-192e
这里我开启两个终端会话,查看进程:
可以看到 TTY 的编号分别是
pts/0,pts/1大多数进程都需要绑定一个控制终端,进程的生命周期与启动该进程的控制终端相关联,终端窗口被关闭时,与之相关联的进程也会被杀死
有一类进程称为守护进程(daemon),他们被设计为在后台运行,管理着某些系统服务,通常只在机器 / 系统关闭时停止,不与控制终端关联,如果你在
ps aux中看到部分进程的 TTY 显示一个问号?,这表示该进程没有关联任何控制终端,独立于用户会话运行进程的创建
Linux 中创建进程的现有机制是
fork - exec模型。首先,现有进程使用fork来克隆自身,创建一个和自己几乎一样的子进程,这个子进程会获得自己的唯一 PID ,原始进程则为该进程的父进程,由 PPID 标识之后,子进程通过
execve系统来调用或加载一个新程序,有效地用新程序的内存空间替换了继承的内存空间,从而执行新的任务在
ps -ef或ps l命令中,PPID 的列代表父进程的 PID
这里可以看到,
ps l的 PPID 就是当前 shell 进程的 PID(68227)如果每个进程都是另一个进程的子进程,那么必然存在一个最初的祖先。这就是
init进程。系统启动时,内核会创建init作为第一个用户空间进程,并为其分配 PID 1。init进程是所有其他进程的最终父进程,并以 root 权限运行以管理系统。在系统关闭之前,它不能被终止,并且负责启动许多维持系统运行的服务进程的终止
进程通常通过调用
_exit系统调用来终止。此操作向内核发出信号,表明进程已完成,其资源(如内存和文件描述符)可以被回收。退出时,进程会向内核提供一个终止状态,这是一个整数值。按照惯例,状态 0 表示成功执行,而非零值表示发生错误然而,调用
_exit并不会立即清除进程。父进程必须使用wait系统调用来确认其子进程的终止。此调用允许父进程检查子进程的终止状态。这种两步机制对于正确的进程清理至关重要另外一种终止进程的方式是信号,后续介绍
孤儿进程
如果父进程在子进程终止之前就终止了,那子进程就变成了孤儿进程。由于其原始父进程没办法调用
wait,内核会介入,孤儿进程会立即被一个特殊的系统进程(通常是init,PID 为 1)收养,该进程被认为是所有进程的祖先。然后init进程承担起父进程的角色,定期调用wait来收集其所有被收养子进程的终止状态,使它们能够干净地终止僵尸进程
当子进程终止,但父进程还尚未调用
wait时,子进程就变成了僵尸进程。内核会释放僵尸进程的大部分资源,但他会在进程表中保留一个条目,包含进程 PID 和终止状态,等待父进程来收集。由于僵尸进程已经死亡,它不会占用 CPU 的资源,你无法使用信号来终止僵尸进程,因为他们根本没在运行。父进程调用wait来清理僵尸进程的过程叫做回收,如果父进程不调用wait来回收僵尸进程,虽然不消耗 CPU 资源,但大量僵尸进程会填满进程表,阻止新进程的创建。在父进程也终止的情况下,init会收养并回收僵尸进程。孤儿进程 vs 僵尸进程
- 孤儿进程是活动的,正在运行的进程,其父进程已经死亡,他被
init收养并继续运行,直到任务完成 - 僵尸进程是死亡的,它已经完成了要执行的任务,但在进程表中仍然存在一个条目,等待父进程读取回收
总之,孤儿进程是活着但没有父进程,僵尸进程是死了但没有被父进程回收
- 孤儿进程是活动的,正在运行的进程,其父进程已经死亡,他被
信号
在 Linux 中,信号是发送给进程的软件中断,用于通知它发生了重要事件,是进程间通信(IPC)的主要方式之一
- 用户可以在终端输入特殊字符(
ctrl + c,ctrl + z)来向前台进程发送停止 / 中断信号 - 内核也可以向进程发送信号,通知发生了软件 / 硬件问题
- 系统管理员和其他进程也可以使用信号管理进程的生命周期
信号生成后,首先传递给目标进程,此时信号处于“待处理”状态,直到内核运行该进程,当进程被调度时,信号被传递。然而,进程具有信号掩码,可以配置掩码来阻止特定信号的传递
当信号被传递时,进程可以采取以下操作:
- 忽略信号:简单地丢弃信号,继续执行任务
- 捕获信号:执行信号处理程序(自定义函数)来响应该事件
- 执行默认操作:当信号没有被忽略或捕获时,则执行默认操作,对于许多信号来说,这意味着终止进程
- 阻塞信号:如果信号在进程的信号掩码中,则信号保持“待处理”状态,直到解除阻塞
常见的信号如下:(都以
SIG开头)SIGHUP (1):挂断。通常用于告诉守护进程重新加载配置SIGINT (2):中断。ctrl + c,它是终止进程的请求SIGKILL (9):杀死。这是一种立即、强制的终止,该信号无法被忽略、捕获、阻塞SIGSEGV (11):段错误。通知进程进行了无效的内存引用SIGTERM (15):终止。这是一种标准且礼貌的请求进程终止的方式,kill命令默认发送此信号,进程可以捕获此信号,在退出前执行清理工作SIGSTOP (19):停止。立即停止进程,该信号无法被忽略、捕获、阻塞SIGTSTP (20):暂停。礼貌地暂停进程,该信号可以被忽略、捕获、阻塞,暂停后的进程可以恢复
- 用户可以在终端输入特殊字符(
killkill命令尽管名称如此,但他不仅仅能向进程发送终止信号,还能发送许多各种信号1
2
3kill 12345
等价写法
kill -15 12345这将会终止 PID 为 12345 的进程,他会发送
SIGTERM信号,这是标准、优雅地终止进程的方式,用于请求进程干净地关闭,给了进程清理和释放资源的机会有时进程出现无响应,不会对
SIGTERM信号做出反应,在这种情况下可以使用SIGKILL信号强制杀死1
kill -9 12345
这会立即杀死进程,不给它清理的机会
kill命令后加上数字选项,可以发出各种类型的信号,比如kill -1通知守护进程重新加载配置文件等,你也可以使用信号名称代替数字编号,例如kill -SIGHUP,效果是一样的一个特殊的用法是
kill -01
kill -0 12345
这个命令实际上没有发送任何信号,但是可以用来检查 PID 为 12345 的进程是否存在,以及你是否有权限对该进程发送信号
进程优先级
多个进程同时运行时,实际上,CPU 会在不同的进程之间快速切换,为每段进程分配一小段处理时间,称为“时间片”,时间片结束后,进程会被暂停,CPU 会转而执行下一个进程(以单核 CPU 为例)
内核的调度决策可以由进程的
niceness决定,niceness决定了一个进程的“友好性”,它用一个数字表示,范围是-20 ~ 19- 一个进程的
nicenee比较高,表示该进程十分“友好”,他会先把 CPU 时间让给其他进程,因此该进程的优先级就比较低。换句话说,niceness与进程的优先级是负相关的,niceness较小的进程拥有较高的优先级
使用
top命令实时查看进程状况,其中NI列就代表进程的niceness。大部分进程在创建时,niceness的值默认为0,我们也可以手动更改和设定进程的niceness值以
niceness为 5 启动apt update1
nice -n 5 apt update
把 PID 为 12345 的进程的
niceness改为 101
renice 10 -p 12345
- 一个进程的
进程状态
使用 ps aux 查看进程快照,你会看到 STAT 列,表示当前的进程状态
R:运行中或可运行。要么正在 CPU 核心上运行,要么在运行队列中,一旦有可用 CPU 核心立刻运行S:可中断睡眠。最常见的进程状态之一,进程正在等待某个事件的完成,可以被信号唤醒D:不可中断睡眠。无法被信号唤醒,通常用于 I / O 操作期间,此时中断进程可能导致状态损坏。如果某个进程长期处于该状态,可能表示硬件和驱动存在问题Z:僵尸进程。T:停止。如按下ctrl + z挂起的进程或者调试器跟踪的进程,可以用SIGCONT信号恢复它
/proc文件系统Linux 系统中有一个独特的目录
/proc,这个目录不是硬盘上的真实文件系统,它由内核在内存中创建1
ls /proc
可以看到,
/proc中有很多带有编号的目录,这些编号代表进程的 PID。还有一些文件例如cpuinfo和meminfo,他们提供系统的硬件信息如果你知道某个进程的 PID
1
cat /proc/12345/status
此命令将显示有关该进程的详细信息,提供了比其他工具多得多的数据。实际上,像
top、ps等这样的应用程序都会从/proc读取数据,并以用户友好的形式展现出来,因此/proc目录可能会显示这些工具没有的大量额外细节你也可以通过读取
/proc目录来构建你的自定义脚本或监控面板作业控制
在 Linux 中,你可能会遇到需要等待很长时间才能完成的命令,你不必傻傻等待,让命令占用终端前台而无法使用
要在后台启动一个进程,只需要在命令后面加上一个
&1
2
3sleep 1000 &
sleep 1001 &
sleep 1002 &你在后台启动了三个进程,可以使用
jobs查看后台正在运行的作业1
2
3
4
5 ~/m/p/linux-lab/lab-01 main +3 !3 ?2 ❯ jobs
[1] running sleep 1000
[2] - running sleep 1001
[3] + running sleep 1002第一列显示了后台作业的 ID,
+表示最后一个启动的作业,-表示倒数第二个启动的作业后台作业,一般只用于跑一个较为耗时的脚本 / 命令时使用,为了不影响前台正常输入命令而用的,通常不适合用于跑长期服务
如果你将一个命令跑在了前台,运行一半的过程中,你想把他转移到后台作业,但又不想重新启动该命令,可以搭配使用
SIGTSTP (ctrl + z)和bg命令1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18前台启动进程
sleep 1003
暂停进程
ctrl + z
前台启动进程
sleep 1004
暂停进程
ctrl + z
ctrl + z 在暂停进程的同时,还会把这些进程登记到后台作业,使用 jobs 查看
jobs
[1] - suspended sleep 1003
[2] + suspended sleep 1004
使用 bg 来启动后台作业
bg %1 # 启动作业 id 为 1 的后台作业
bg # 不指定则会启动最后一个后台作业如果你想要把后台作业调回前台,使用
fg命令,用法与bg相同1
fg %2
后台作业和前台进程一样,都可以用
kill来传递信号,如果要终止一个后台作业进程1
2
3
4kill %2
其他各种信号也都可以传递
kill -9 %2
kill -20 %2
软件包
软件发行
你可能知道像
chrome和firefox这样的软件名称,在技术层面上,他们实际上是软件包。软件包是一个文件存档,包含应用程序的可执行文件、配置文件、文档等。软件包的供应链中存在两个角色:- 上游提供者:软件的开发者,他们编译源代码,创建安装说明和发布更新版本
- 软件包维护者:新版本准备好之后,上游提供者会将他们发送给软件包维护者。软件包维护者会审查之后将软件以特定 Linux 发行版的软件包形式分发给用户
虽然你可以直接通过源码编译安装软件,但使用软件包更为高效,如
.deb、.rpm等是 常见的软件包形式软件包存储库
我们可以在官方网站获取软件包,但更为高效的解决方案是使用包管理器,从软件包存储库下载软件包
每个 Linux 发行版有个字不同的包管理器,他们通常会预先配置一组默认的软件包存储库,用于下载系统上的所有基础软件包。
以 Ubuntu 系统为例,旧版本的 Ubuntu 会把软件包的源配置在文件
/etc/apt/sources.list中,当你使用apt install下载软件包时,会读取该文件配置的软件源。但通常会出现 Linux 发行版提供的默认软件包源的软件版本落后的情况,例如安装docker时,官方文档建议你手动配置软件源,手动配置的软件源位于/etc/apt/sources.list.d目录中。在新版本的 Ubuntu 中甚至默认使用/etc/apt/sources.list.d目录作为所有软件源的配置目录,默认的软件源的配置信息被迁移到了/etc/apt/sources.list.d/ubuntu.source中1
2
3 ~/mysrc ❯ ls /etc/apt/sources.list.d
docker.list jenkins.list ubuntu.sources使用
apt安装软件包时,会先读取*.list的软件源,如果没有,再从默认源下载在 Linux 中,软件包很少是独立存在的,他们通常必须依赖其他组件才能正常运行,也就是依赖项。这些依赖项可以是其他包,或者更常见的是共享库,共享库是多个程序可以同时使用的预编译代码集合,可以节省开发人员为每个新应用程序写通用函数。如果软件在安装过程中缺乏所需的依赖项,这些软件包就是损坏的,Linux 包管理器旨在自动处理 Linux 包依赖项,获取并安装他们,防止损坏包的出现
压缩与归档
在 Linux 中,归档与压缩是两步操作
- 归档:把多个文件 / 目录 打包成一个文件
- 压缩:减小一个文件的大小以节省磁盘空间和加快传输过程
由此可见,归档可以对多个文件 / 目录使用,而压缩是针对一个文件使用的
1
2
3
4
5
6
7
8
9 ~/mysrc/demodir ❯ tree ubuntu@vmubuntu 09:08:20 上午
.
├── content # 目录
│ └── file3
├── file1
├── file2
└── target # 目录
3 directories, 3 files压缩
gzip用于压缩文件,生成一个.gz结尾的压缩文件代替原文件1
2
3
4
5 ~/mysrc/demodir ❯ ls -a
. .. content file1 file2 target
~/mysrc/demodir ❯ gzip file1
~/mysrc/demodir ❯ ls -a
. .. content file1.gz file2 target如果要解压,使用
gunzip1
2
3 ~/mysrc/demodir ❯ gunzip file1.gz
~/mysrc/demodir ❯ ls -a
. .. content file1 file2 target归档
tar用于将多个文件 / 目录打包成一个归档文件,通常以.tar结尾1
2
3
4
5
6
7
8
9
10 ~/mysrc/demodir ❯ ls -a
. .. content file1 file2 target
~/mysrc/demodir ❯ tar -cvf myarchieve.tar file1 file2 content
file1
file2
content/
content/file3
~/mysrc/demodir ❯ ls -a
. .. content file1 file2 myarchieve.tar target选项解释:
-c表示创建归档-v表示归档过程中输出详细信息,打印被归档的目录和文件-f表示指定目标归档文件(这里的myarchieve.tar)
如果要提取归档文件,使用
-x代替-c1
2
3
4
5
6
7 ~/mysrc/demodir ❯ tar -xvf myarchieve.tar -C target
file1
file2
content/
content/file3
~/mysrc/demodir ❯ ls target
content file1 file2提取归档文件通常配合
-C选项使用,用于指定提取到目标位置归档与压缩结合使用
最常见的用法是归档与压缩一起使用,先归档再压缩,创建
.tar.gz文件,Linux 也为我们提供了快捷的命令1
2
3
4
5
6
7
8
9 ~/mysrc/demodir ❯ ls -a
. .. content file1 file2 target
~/mysrc/demodir ❯ tar -czvf myfile.tar.gz file1 file2 ./content
file1
file2
./content/
./content/file3
~/mysrc/demodir ❯ ls -a
. .. content file1 file2 myfile.tar.gz target这里的
-z选项表示在创建归档之后使用gzip压缩1
2
3
4
5
6
7 ~/mysrc/demodir ❯ tar -xzvf myfile.tar.gz -C target
file1
file2
./content/
./content/file3
~/mysrc/demodir ❯ ls target
content file1 file2这里的
-x选项表示提取归档之前使用gzip解压,同样这里可以用-C指定解压到目标路径
dpkg与rpm如果要直接安装软件包,而不是通过包管理器安装,你可以在软件官网上找到
.deb或.rpm文件,下载后通过以下命令安装:1
2Debian 系统
dpkg -i nginx.deb-i选项表示下载,你也可以用长选项--install代替如果要移除下载的软件
1
2
3
4删除软件
dpkg -r nginx
删除软件及其相关的配置文件(更彻底)
dpkg -P nginx实际上,不管是通过包管理器还是手动从
.deb文件下载的软件,都可由包管理器进行管理,使用dpkg -l列出所有已安装的包,他们都可以通过包管理器删除,更为干净彻底,自动处理依赖1
2
3
4删除软件
sudo apt remove nginx
彻底删除
sudo apt purge nginx包管理器
以 Debian 系操作系统为例,使用
apt包管理器安装与删除
1
2sudo apt install nginx
sudo apt remove nginx值得注意的是,使用
apt包管理器下载 / 更新软件之前更新软件源索引是个好习惯1
2
3
4更新软件源索引
sudo apt update
更新软件
sudo apt upgradeupdate只是更新了仓库源,真正更新软件的是upgrade,upgrade是保守更新,在不影响正常服务 / 不改变依赖的情况下对软件升级,不会出现跨大版本更新导致服务 / 配置失效的情况,只会更新向后兼容的小版本(尽管如此在开发中尽量不要全局使用apt upgrade)从源码编译下载
某些软件可能只提供从源码编译的下载方式,掌握如何编译源码来下载软件是必要的,这里以下载
GNU Hello为例演示从源码编译的步骤。GNU Hello是一个非常轻量的软件,它的作用仅仅是输出Hello World,为教学编译使用,大部分 Linux 的发行软件的编译过程都与此类似(不过查看 README 总是好的)下载工具
build-essential(如果你没有的话)1
2sudo apt update
sudo apt install build-essential这个软件包括了一套软件开发工具,有
gcc编译器make应用程序等,对编译代码至关重要下载源码并解压
1
2
3wget https://ftp.gnu.org/gnu/hello/hello-2.12.tar.gz
tar -xzvf hello-2.12.tar.gz
cd ./hello-2.12 # 后续操作在软件项目根目录下执行执行
./configure脚本1
./configure
开发者会提供
./configure脚本,他会运行一小段简单的程序,来检查你的机器上是否有该软件运行所必须的依赖,如果缺少依赖项,你需要在继续安装之前补全他们(不用看 yes / no,如果缺失依赖会报错 error 的),然后生成Makefile,其中包含了关于如何将源代码编译成可执行程序的规则执行
make1
make
读取
Makefile,确认编译内容和顺序,然后执行编译,生成各种可执行文件和目标程序安装软件
软件编译成功后,还需要安装到系统上,有两种安装方式,传统的安装方式是继续输入
sudo make install,系统会把编译后的文件复制到合适的目录下,但他有一个明显的缺点:这样安装的软件不会被注册到包管理器中,难以管理。因此,更好的方法是使用checkinstallcheckinstall是一个第三方工具,你得先在你的系统上安装它1
sudo apt install checkinstall
执行安装
1
sudo checkinstall
它的原理是利用编译后到文件创建一个
.deb包,然后安装这个应用执行命令后,会输出一系列类似安装引导的文字,交互后即可成功安装
检查是否安装成功

说些什么吧!