目录
1. 认识 Linux
2. 安装
3. Linux 操作
3.1 linux 基础操作
3.2 Shell
4. 文件、进程与权限
4.1 Linux 文件
4.2 进程
4.3 权限
5. 环境管理与软件
5.1 简单的软件安装
5.2 环境管理
5.3 例子:python 环境管理
6. Vi 编辑器
6.1 Vim 基础操作
6.2 Vim 太麻烦了!
1. 认识 Linux
Linux 是一种开源的免费操作系统,或早或晚的,我们会在很多场合遇到它。
可能是复现实验结果,照着README搭建环境时,看到熟悉又陌生的说明:Ubuntu 20.04 + CUDA 11.8;可能是Docker容器跑不起来,默认跑在Linux生态里;实验室的服务器只提供 Linux 系统,嵌入式开发板、ROS、远程计算节点,也几乎清一色是 Linux。
我们绝大多数人使用 Linux,只是为了完成一件具体的事:跑代码、做实验、训练模型、部署服务。很多挫败感也正是从这里开始的:程序跑不起来却不报错,文件明明存在却没有权限,环境配置改了半天反而更乱。于是,它在一开始就被贴上了难用的标签。
严格来说,Linux只是操作系统中最核心的一层:Linux内核。内核负责进程调度、内存管理、文件系统、设备驱动等底层工作,所有程序最终都通过内核与硬件打交道。而我们日常所说Linux 系统,包含了内核、系统库、shell、应用程序等。内核之上的系统库将系统调用封装成应用程序直接使用的接口;Shell是用户与系统交互的入口,让用户以文本方式控制系统;应用程序和工具则完成具体的计算、服务或开发任务
这种意义上的Linux系统就是Linux 发行版。不同组织或社区,围绕同一个Linux 内核,各自选择并打包了一整套工具软件。我们平时听到的 Ubuntu、Debian、CentOS、Arch 等都是不同的发行版。发行版不是不同的Linux系统,它更像一种预配置方案,无论哪一个发行版,它们的基础命令和操作都是一样的,也都可以基于自己的需求深度定制。本文基于较流行的 Ubuntu 展开
在 Windows 环境下有多种成熟稳定的 Linux 使用方式,对应不同的需求场景。WSL 是目前成本最低的方法。它在 Windows 内部运行一个真实的 Linux 内核,且与 Windows 开发工具无缝协作。对于大多数学习和开发场景,WSL 已经足够使用。如果想要一个更完整、与主系统隔离的Linux 环境,可以使用传统虚拟机。它模拟了一整套硬件环境,适合理解系统结构或进行更接近服务器环境的配置。除此之外也可以在电脑上安装双系统,但这样配置安装麻烦,每次切换需要重启电脑。除了本地安装之外,还可以使用线上云服务器访问 Linux 系统,但是这样要花钱
本文使用WSL安装Ubuntu 22.04,介绍从零开始认识Linux、安装环境、基础Linux操作、Shell、Linux文件、进程与权限、环境管理与软件、Vim编辑器等内容。Linux知识浩如烟海,本文所包含的内容有限,仅帮助我们对Linux建立初步的认识
2. 安装
在 Windows 上,我们通过 WSL 来安装 Ubuntu
在开始菜单搜索启用或关闭 Windows 功能,勾选“虚拟机平台”和“适用于 Linux 的 Windows 子系统”
Win + R ,输入 cmd,输入 wsl -v
显示没有安装,提示我们可通过运行 wsl.exe --install 进行安装
wsl.exe –install
输入该命令安装
安装完成,再次输入wsl -v 可看到安装信息
在PowerShell中输入:
wsl --install -d Ubuntu-22.04
等待安装,直到提示我们输入用户名
输入用户名并设置密码,输入密码时,屏幕上不会显示任何字符,这是 Linux 的正常机制,放心输入
看到这个提示符表示安装成功
在当前这个终端里直接执行以下命令,对系统和软件进行升级
sudo apt updatesudo apt upgrade -y
3. Linux 操作
3.1 linux 基础操作
安装好 Ubuntu 之后,你会发现它与我们印象中的操作系统不同,没有桌面图形界面。这是 WSL 的特性,它只提供一个轻量的 Linux 运行环境。在实际使用中可将 Windows 的图形界面与 WSL 的 Linux 环境结合起来。编辑代码使用 Windows 的 VS Code,查资料文档使用 Windows 的浏览器,文件管理依然通过 Windows 资源管理器,而代码的编译、运行和脚本执行交给 WSL 的 Ubuntu 完成。
甚至可以直接让 VS Code 连接到 WSL
打开 VsCode,在扩展中搜索 WSL 并安装
点击左下角的远程连接按钮,选择连接到 WSL
选择相应的发行版
这样便进入了 VsCode 的远程开发模式
此时打开终端即可执行命令
默认情况下 WSL 会直接进入当前用户的主目录。运行
Pwd
终端输出用户的主目录位置 /home/username
在命令提示符终端中,需运行
wsl ~
进入Ubuntu 的Home目录
回到 VsCode,创建一个用于练习的目录,并使用cd命令进入其中:
mkdir testcd test
再次使用pwd,确认已进入新目录
返回上一级目录
Cd ..
使用ls命令列出当前目录下的文件
ls
我们可以先创建一个最简单的文件:
echo "hello linux" > a.txt
echo 会产生一段输出,> 意思是把原本应该显示在屏幕上的内容,改为写入到文件 a.txt 中。如果文件不存在,就创建;如果存在,就覆盖。
可以检查一下:
lscat a.txt
cat 命令将文件内容直接打印出来。
如果不想覆盖原内容,而是希望在文件末尾追加一行,可以这样写:
echo "second line" >> a.txtcat a.txt
双箭头 >> 表示追加
最后,我们再熟悉一下几个最常用的文件操作命令
复制文件:
cp a.txt b.txt
重命名或者移动文件
mv b.txt c.txt
删除文件
rm a.txt
3.2 Shell
在完成这些基础操作后,一个重要的概念是 Shell。Shell并不是某个具体的软件,用户在终端中输入的每一行文字,都会首先由 Shell 解析,然后再决定执行哪个程序、如何传递参数。在Ubuntu中,默认使用的是 Bash。可以简单为用于控制系统的脚本语言,终端只是它的输入输出窗口。
正因为 Shell 的存在,Linux的使用方式呈现出通过组合简单命令完成复杂任务的特点。我们刚刚使用的 pwd、ls、cd、mkdir,本质上都是独立的小工具,而 Shell 负责将它们组织成一个连贯的工作流。
【大学生基本功】你可能需要的 Shell 知识-1
关于 Shell 的更多认识,在这一链接中有所提及,此处不做赘述。
4. 文件、进程与权限
我们已经学习了不少 Linux 命令,在继续进入环境配置和软件安装之前,有必要了解一下 Linux 是如何组织和管理这些操作的。
4.1 Linux 文件
在 Linux 中,一个贯穿始终的概念是文件。系统把几乎所有资源都统一抽象成文件:目录是文件、磁盘是文件、设备是文件、很多系统状态也以文件显示。这样做的好处是,系统不需要为不同对象设计不同的操作方式。
Linux 中的文件由两部分组成:inode 存放文件的元数据,包括权限、所有者、时间戳、大小,以及数据块的指针;目录项则把文件名映射到 inode。真正的数据存储在硬盘上,通过 inode 获取其位置并操作。也就是说,文件名只是一个指向 inode 的标签,真正代表这个文件的是 inode 号。
这里创建一个文件
echo "hello inode" > a.txt
看一下 inode 号
ls -li a.txt
输出如下,最左边的300就是inode号
300 -rw-r--r-- 1 hao hao 12 Jan 13 16:05 a.txt
接下来改个名字:
mv a.txt b.txtls -li b.txtcat b.txt
发现内容和 inode 号没有变,说明改文件名只是改目录项,inode文件本体不变
目录在 Linux 里也是文件,它的内容不是文本,而是一张从名字到 inode 号的映射表:
看目录自身的 inode,在当前目录运行:
ls -li
读取目录文件,输出目录中文件的信息
total 4300 -rw-r--r-- 1 hao hao 12 Jan 13 16:05 b.txt
既然文件名只是标签,那就可以有多个标签指向同一个inode。这就是 硬链接。
创建一个文件,并通过 ln 命令硬链接到第二个文件
echo "data" > 1.txtln 1.txt 2.txt
查看 inode 和链接
ls -li 1.txt 2.txt
两个文件的 inode 号完全相同,且第二列链接数会变成 2
向其中一个文件添加内容,
echo "add" >> 1.txtcat 2.txt
2.txt 也变了。因为它们根本不是复制,而是两个名字指向同一个 inode,也即指向了同一数据块
这也是为什么复制一个大文件会很慢但链接几乎瞬间完成,因为不搬数据。
更常见的是软链接,它像 Windows 的快捷方式
ln -s 1.txt soft.txtls -li 1.txt soft.txtls -l soft.txtcat soft.txt
soft.txt 是一个新文件,它的 inode 号不同,ls -l会显示 soft.txt -> 1.txt,我们读取 soft.txt 时,系统会跟随它指向的路径去找目标
此时把目标文件删了,软链接会断;而硬链接仍然能正常读,因为 inode 还在
rm 1.txtcat soft.txt
这时我们回头来看 rm 到底删了什么,删的是目录项,是文件名到inode的映射,直到inode 的硬连接数 link count 变为0,并且没有进程打开这个 inode,系统才会真正回收数据块。这解释了一个现象,为什么文件被 rm 了,但磁盘空间没释放
比如开一个终端 A,生成一个200MB文件。在终端A里持续占用
dd if=/dev/zero of=big.log bs=1M count=200 status=progresstail -f big.log > /dev/null
开另一个终端 B,查看空间,删除这个文件并再次查看
df -h ~rm big.logdf -h ~
空间没有立刻回来,因为 tail 进程仍然打开着 inode,数据块还不能释放。执行:
lsof | grep big.log
(deleted)说明文件名已经没了,但 inode 还在,被进程持有
回到 终端 A,按 Ctrl C,或者在终端B:kill 79600,结束tail进程
这样空间才会释放,在服务器日志、训练输出、临时文件上出现“明明删了,空间怎么还满”的问题,原因就是仍有进程占用
4.2 进程
在 Shell 里输入一条命令让终端等一会儿,
sleep 1
此时系统创建了一个新的进程。进程可以看作程序的一次运行实例,不仅包含代码,还包含运行所需的内存、打开的文件、环境变量、权限身份等运行状态。
可以通过&使命令后台运行
sleep 1000 &
此时输出[1] 82717,1是进程的编号,数字就是PID进程号。Linux 用 PID 唯一标识一个进程运行
jobs
查看当前终端的后台任务,通过fg %1、bg %1分别恢复到前、后台kill 82717 杀掉进程,也可以使用快捷键按 Ctrl+C 终止,按 Ctrl+Z 暂停
Linux 中进程不是孤立的,而是有父子关系,形成进程树。运行 ps 命令查看进程状态
ps -ef | grep sleep(进程关键字)
可以看到进程的父进程 PID(PPID):
ps -o pid,ppid,cmd -p $$
这里 $$ 是当前 Shell 的 PID。在这个 Shell 里启动的程序,往往是它的子进程
Linux 能同时跑很多程序,核心在于调度器:它把CPU时间切成很小的片段,在不同进程间快速切换。我们看到的同时,实际是高速轮流。
我们运行一个CPU 压力测试的命令,只允许用 1 个核心
taskset -c 0 yes > /dev/null &
再次运行启动第二个:
现在有两个进程在抢CPU。运行top查看,两个 yes 的 CPU 占用差不多
使用 renice 命令改变优先级,nice 值范围是:-20~+19,数字越大优先级越低
renice +10 [PID]
再回到 top 看,它的 CPU 占用往往会下降,另一个会上升。最后结束进程
pkill yes
进程运行时不仅要抢 CPU,也要占用内存。
运行 free -h 查看系统整体内存状态
在 Linux 里:free 代表什么都没用的内存;buff/cache 是被用作缓存的内存;available 则是内核估算的还能给进程用的内存。我们判断内存是否紧张,主要看available;Linux 会主动占用空闲内存作为缓存,当有进程需要内存时,这些缓存会被回收
输入以下指令,按进程 RSS对进程排序,可以看到是谁在吃内存。RSS是进程当前实际占用的物理内存
ps -eo pid,rss,cmd --sort=-rss | head
4.3 权限
在 ls -l 命令的输出中
第一位表示类型,- 是普通文件;d 是目录 ,l 是链接;后面的9个字符就是文件的权限,可以把他们按照三个一组来看,分别表示文件所有者(user)、所属组(group)、其他(others)的权限,每一组的三个字符分别表示读r、写w、执行x权限,如果没有权限,就显示 -
比如这里第一行的文件表示所有者有读写权限,其他只有读权限
Chmod 命令用于修改文件的权限,如给 user加上执行权限,使用 u+x 关键字,删除是 - 号
chmod u+x a.txt
还有一种方法是用数字表示权限,r=4,w=2,x=1,不同的组合对应唯一数字
我们看到的脚本文件几乎总是755,755=rwx r-x r-x,所有者全权限、组用户读+执行、其他人读+执行
这是文件级别的权限,Linux 中更高一层的是用户权限
输入以下命令
whoamiid
会看到自己的 uid、gid,以及属于哪些组。Linux靠UID、GID做权限判断。执行
rmdir usr
显示Permission denied,加上前缀 sudo 能成功,这是因为sudo 临时把用户身份切换成 root,这时允许我们碰系统目录,因此很多命令带有前缀 sudo
sudo apt update //更新软件包 sudo -s //进入管理员 Shell
用户自己的程序和环境变量通常位于主目录下,而系统级的软件、库和配置文件则集中在 /usr、/etc、/lib 等目录中。下一章在讲环境配置时,会频繁出现这些路径,而它们之所以不可随意修改,正是权限在起作用。