想必大家都不乐意阅读冗长而没什么用的介绍。因此本文将尽可能精简,更多的资料将以
的形式附在每节正文的末尾。其中标有*的内容为英文资料。
与常见的 Windows、MacOS 相同,Linux 也是一个操作系统,一般用于开发和服务器领域。
Linux 的内核非常小,功能也不多。为了便于人们使用,有许多组织在它的基础上修改和新增了大量软件包并重新发布。这些版本仍属于 Linux,称为 Linux 发行版(Distribution)。
亦有些发行版是基于其它发行版进一步修改得到的。
类比安卓手机,谷歌推出了基础的 Android 系统,而各大手机厂家为了满足本地化的用户需求对它进行了修改。产生了诸如小米 MIUI,华为 EMUI,OPPO ColorOS等衍生版本。
常见的发行版有 Debian、Ubuntu、Arch、Mint、RedHat 等
图源:菜鸟教程
而在我们UCAS的课程中,最常使用的发行版为 Ubuntu,因此本指南将以它作为基础。
不同发行版之间可能存在差异,例如 Debian/Ubuntu 采用apt
作为软件包管理器,而 RedHat 采用rpm
。因此在使用别人的代码时应留意发行版是否一致,在向他人求助时也请主动提供您的发行版信息。
- *Distrowatch:发行版列表及榜单
- *Debian is the rock on which Ubuntu is built:Ubuntu 官网对 Ubuntu 和 Debian 关系的介绍
Ubuntu 是由 Canonical Ltd. 构建的 Linux 发行版,拥有桌面版、服务器版、物联网版等分支。
Ubuntu 每六个月(每年的4月和10月)发布一个新版本,每两年发布一个长期支持(LTS)版,版本号标识为
Ubuntu yy.mm.x
例如Ubuntu 20.04.3 LTS
表示为2020年04月发布的 LTS 版本的第三次小更新
不同版本间的 Ubuntu 亦可能存在差异,请留意。
Linux 系统下常见的编程环境,例如 c / python3 / go / docker 等,基本都可以直接(或添加附加软件源后)通过包管理器安装,系统会自动对它们及依赖项、冲突项进行管理,同时自动对环境变量进行配置。
卸载不需要的环境时通常也只需使用包管理器(例如apt remove xx
),系统会自动清理配置文件和自动安装的依赖项。
与之相比,Windows 下要找到各个环境的官方网站、下载安装包、手动进行安装和配置,非常麻烦且容易造成混乱。
此外,在 Windows 下,有些环境依赖于其它环境(例如在 vscode 中进行 c 语言编程需要 MinGW 编译器),需要手动配置;有些环境与其它环境冲突(例如 docker 与 windows 自带的 Hyper-V),也需要手动解决。这个过程需要额外查询大量教程,且与电脑型号、Windows 版本、厂商预设等大量复杂因素相关,非常不友好。
更不要提软件的卸载,Windows 的卸载文件残留、注册表残留和环境变量残留都是老大难问题了。而这些残留就可能导致未来配置其它环境时出现问题。
这并不是指系统漏洞少、黑客攻击难那个意义上的安全。而是说课程使用及本文推荐的 Linux 使用方式通常基于某种虚拟化技术,因此:
只要做好工程文件(源代码、配置文件等)的备份,即使出现了环境配置混乱、不当操作造成系统故障等“难以直接恢复”的情况,可以毫不心疼地销毁整个开发环境重新配置。
而随着对 Linux 系统的熟悉,重新配置环境所需的时间和精力会远小于尝试修复。
与之相比,直接在 Windows 下开发,由于不当配置造成注册表、环境变量、程序安装路径等混乱和错误,难以直接恢复。同时由于 Windows 作为主力机有许多日常使用的软件和文件,重装系统所需的时间和精力、承担的风险更大。
在大二下的《数据结构》为例的课程中,有部分作业是要在在线评测系统(oj)上完成的。这类在线评测系统的后端通常是 Linux 服务器,在本地也是用 Linux 环境可以避免环境不统一导致的错误。
例如,在部分 Windows 环境下编写 C 语言代码,为了使程序输出结果以后停止而非直接退出,通常要使用 system("pause");
语句,而该语句会在 Linux 环境下产生Runtime Error: pause: not found
错误,原因是pause
为 Windows 特有,不是一个合法的 Linux 指令。
注:本节中提到“图形化”是指 Linux 系统的图形化界面,使用 Windows 图形化界面配合 Linux 命令行是一个推荐的使用方式。
尽管大部分 Linux 发行版都可以像 Windows 一样使用支持鼠标的图形化界面,主流的在 Linux 上进行开发的方式还是使用纯键盘的命令行模式。主要理由如下:
- 图形化界面比较占用资源
- 做开发时大部分时间只需要打开编辑器、使用键盘输入代码,没有必要使用鼠标和图形化界面(即使使用 vscode 等图形化编辑器,也可以用远程连接的方式代替直接在 Linux 中运行图形化界面)
- 有些软件的图形化界面支持并不稳定,会产生预期以外的错误
- 有时开发是在远程服务器上进行的,传输图形化界面对网络要求高
我校课程对于 Linux 的使用也通常只需要命令行即可完成,例如程序设计基础与实验(C 语言)课程的武成岗老师班,要在 Linux 中完成的操作有:
- 编辑代码
- 使用
gcc
编译 - 运行并查看结果
后两步都是纯命令行操作,第一步大家的做法不尽相同,有使用gedit
/vscode
这类图形化界面的,亦有使用vi
/nano
的,关于这些编辑器更详细的介绍和对比请看编辑器页面。
特别的,vscode
虽然是一个图形化程序,但可以使用 Windows 下的 vscode
通过插件和ssh
连接到 Linux 系统,从而避免使用 Linux 的图形化界面。个人也是强烈推荐这个方式,详见vscode页面。
综上,本指南涉及 Linux 系统的使用时,一般只会使用命令行(终端)的部分,希望大家能适应这种模式。
虽然我们使用的所谓命令行事实上是由终端(terminal)和 shell 组成的,但简单起见,可以先忽略这其中的细节
打开终端后,您可能会见到类似下面这样的字符:
ubuntu@server-7anw4ytc:~$
其格式为
用户名@主机名:工作目录$
下面逐项解释:
- 用户名:当前登录到系统使用的用户名称
@
:和邮箱中的[email protected]
作用相似,某个主机下的某个用户- 主机名:当前系统的主机名(hostname)
- 工作目录:当前所处的目录,记法请见目录与路径一节
$
/#
:前者表示当前用户不是 root,后者则表示是 root- 注:可能根据终端不同有所变化,Ubuntu 默认的 bash 环境及推荐的 zsh 环境下通常是这两个符号
出现上面的user@host:/dir$
时意味着可以向终端输入指令
一个指令通常由一个命令和若干个参数组成
有些参数没有参数名,有些参数既有参数名又有参数值,还有些参数仅有参数名(起开关作用)
例如
$ ls // 无参数
$ ls -l // 有一个开关型参数 -l
$ tail -n 10 // 有一个名为 -n,值为 10 的参数
$ ls some-dir // 有一个参数 some-dir
$ cp src dst // 有两个参数 src 和 dst
$ gcc -o output -lm test.c // 有三个参数:第一个名为 -o,值为 output;第二个为开关型 -lm,第三个为 test.c
参数的具体含义、类型、是否有序等,与具体的命令(软件包)有关。请查阅文档
必选参数表示必须提供的参数;可选参数表示可有可无的参数,通常具有一个默认值
例如gcc
命令中,待编译的.c
文件是一个必选参数,而输出是一个可选参数,其默认值为a.out
$ gcc -o output
gcc: fatal error: no input files
compilation terminated.
// 错误:没有提供待编译的 .c 文件
$ gcc test.c
// 等价于 gcc test.c -o output 或 gcc -o output test.c
在本指南中,将以<>
标识参数名,[]
标识可选参数
例如列出路径下的文件,文档中会像下面这样描述用法:
$ ls [-l] [<path>]
-l
开关表示是否输出详细信息,缺省为否path
参数表示路径,缺省为.
(当前目录)
当您想要使用该命令列出/some-dir
下的文件时,应该输入
$ ls /some-dir
$ ls -l /some-dir // 输出详细信息
而不是
$ ls [</some-dir>]
$ ls [-l] [</some-dir>]
关于使用终端的其它注意事项和需了解的信息,请继续浏览本文档
一般情况下,Linux 系统对大小写敏感,例如./cod-lab
与./COD-Lab
对 Linux 来说是两个不同的目录,切换目录时要用cd
而非CD
等
Linux 终端使用空格来分割指令参数,当某一个参数中需要包含空格时,用引号包裹
例如用touch
指令创建一个叫this is a file
的文件,如果不加引号
$ touch this is a file
$ ls
a file is this
可见他把this
, is
, a
, file
理解成了4个独立的参数,从而分别创建了这4个文件
$ touch "this is a file"
$ ls
'this is a file'
注意,除非使用转义符(通常为反斜杠),引号自身不会被当作字符串的一部分,因此创建的文件名中不会包括引号。ls
的结果看似是包含了单引号,实际上那只是为了人能准确理解,在显示时自动添加的
除了空格外,换行符、大中小括号等特殊字符在命令行中也有特殊含义,因此需要使用时,也需用引号包裹或使用转义符
不要使用中文引号
单双引号有区别,但一般涉及不到,请自行搜索
在 Windows 环境的很多 IDE 下,按下 Tab 即意味着输入2~4个空格(取决于具体设置)
而在 Linux 环境下,按下 Tab 通常意味着输入一个制表符\t
对于 Python / yaml 等依赖于缩进的语言格式,混用制表符和空格会造成错误。在不确定 Tab 键具体行为的情况下,请使用空格。
简单来说,Linux 下有两类权限机制:
- root 权限(超级用户权限):系统最高权限,甚至可以把系统本身删掉。当做出某些敏感操作(安装软件,修改系统配置等)时需要 root 权限。有时也称 sudo 权限
- root 用户(超级用户):任何 Linux 系统中都有且仅有一个 root 用户,具有 root 权限,处于安全考虑,请避免直接使用该用户
- 普通用户:平时不具有 root 权限,需要使用时可通过
sudo
临时获取,详见常用指令 - 用户组:为方便管理,把需要相同权限的多个用户加入一个组,用户组可以具有一些独立的权限
文件有3类权限:读、写、执行,一般以1位8进制数或者包含{w, r, x, -}的字符串表示
Note:这三个权限彼此独立,可以做到一个用户能写入和执行而不能读取
一个文件针对用户、用户组、任何人可以有不同的权限,因此总共需要3位8进制数或者三组{w, r, x, -}表示权限
此外还需要标注文件是否为目录,用1位2进制表示
例如,通过ls -al
查看详细文件列表时:
$ ls -al
total 12
drwxrwxr-x 3 user group 4096 3月 5 15:16 ./
drwxr-xr-x 3 user group 4096 3月 5 14:45 ../
drwxrwxr-x 2 user group 4096 3月 5 15:15 some-dir/
-rw-rw-r-- 1 user group 0 3月 5 15:16 some-file.txt
-rwxrwxr-x 1 user group 0 3月 5 15:16 some-script.sh*
-rw------- 1 user group 0 3月 5 15:16 some-secret-file.txt
可以看到每行开头有一串字符串:
- 第三行开头的
drwxrwxr-x
中- 第一个字母
d
表示这是一个目录 - 第一组
rwx
表示本用户具有读、写、执行权限 - 第二组
rwx
表示本用户组也具有这三个权限 - 第三组
r-x
表示任何人只具有读、执行权限而不具有写权限 user
和group
分别表示文件所属的用户名和用户组名
- 第一个字母
- 最后一行
-rw-------
开头的-
表示这不是目录,随后的rw-
表示本用户具有读、写权限,后面的两组---
表示本用户组和任何人不具有任何权限
再比如,通过chmod
变更文件权限:
$ ls -al
-rw-rw-r-- 1 user group 0 3月 5 15:16 some-script.sh
$ chmod +x some-script.sh
$ ls -al
-rwxrwxr-x 1 user group 0 3月 5 15:16 some-script.sh*
$ chmod 750 some-script.sh
-rwxr-x--- 1 user group 0 3月 5 15:16 some-script.sh*
chmod +x
表示为该文件增加可执行权限,类似的有+r
、+w
表示增加读、写权限,也有-r
、-w
、-x
表示撤销这三个权限chmod 750
则是使用了3位8进制数表达,写成二进制111 101 000
后与三组rwx
的记法一一对应:本用户111=rwx
,本用户组101=r-x
,任何人000=---
- *Filesystem Hierarchy Standard | Wikipedia(可能需要魔法上网手段)
以根目录/
开始的路径
Note:/
有两种含义,一是根目录(必须是最开头的字符),二是表示层级关系,例如
/home/user/some-file.txt
中的第一个/
表示根目录,后面的两个/
则表示“目录user
在目录home
中”、“文件some-file.txt
在目录user
中”的层级关系
假设当前工作目录的绝对路径为/home/user
some-file.txt
为当前目录下叫some-file.txt
的文件,其绝对路径为/home/user/some-file.txt
.
表示当前目录,因此./some-file.txt
同上..
表示当前目录的上级目录,因此../user/some-file.txt
同上- 没有
.../
的表示方法!如果要表示上级的上级,应该使用../../
Linux 下有些命令与目录无关,如apt update
,但大部分命令均与目录有关,因此请务必留心您所处的工作目录。
查看当前工作目录有两个方法:
- 直接从终端信息中得到,参考读懂终端一节
- 使用
pwd
指令获得
每个用户有一个默认的登录目录,称为用户目录,一般是/home/<用户名>
,例如user
用户的用户目录为/home/user
用户目录用~
表示,因此在上例中~/some-file.txt
和/home/user/some-file.txt
是同一个文件
当我们进行输入时,通常屏幕上会即时显示出我们输入的内容,称为回显
即使是输入密码等敏感字段,也会有诸如***
和···
的回显证明确实输入进去了
而在 Linux 终端中输入密码等敏感字段时,通常屏幕上不会有任何回显,按下回车后才能看到相应的结果(成功执行或密码错误等)
请放心大胆地完成输入
有时在执行一条命令时会出现下面这样的提示
Are you sure you want to continue connecting (yes/no)?
Do you want to continue? [Y/n]
如果您确认命令输入正确且目前没有非预期的输出,则按提示输入y
,yes
等即可继续执行,否则输入n
,no
取消执行
值得注意的是,大部分时候:
- 该步骤不区分大小写
- 可以使用首字母简写法,即
y
和n
分别代表确认和取消 - 在可选项中有一个默认选项,以大写表示。例如上例中的
[Y/n]
默认为确认,这意味着您不输入任何字符直接按下回车时将确认该操作。同理[y/N]
默认为取消。- Note: 默认为取消的操作可能意味着该操作有一定风险,例如覆盖已有的配置文件、产生安全漏洞等。
“阅读模式”不是官方称呼
当使用man
查看帮助文档、systemctl status
查看服务状态、git log
查看 git 提交记录时,将进入阅读模式
左下角将会出现下面这样的提示,一般包含帮助信息、行号、文档名等,也有可能只是单独的冒号。
Manual page <cmd> line <linenum> (press h for help or q to quit)
lines 1-19/19 (END)
:
使用上下箭头按键进行换行,使用 Page Up / Page Down 按键进行翻页
按下q
退出该模式
需要留心的是,Windows 下的快捷键大多数在 Linux 终端中不起作用:
- 在
vi
中Ctrl + S
不能保存文件,:w
才可以 - 在
nano
中Ctrl + S
也不能保存文件,Ctrl + O
才可以
有些甚至会造成事故:
- 复制的快捷键
Ctrl + C
在终端中表示发送一个SIGINT
信号,简单来说代表“强制终止当前执行的命令”。
此外,Linux 下的快捷键与终端软件、发行版等很多因素有关,因此请自行查找您使用的 Linux 环境下快捷键的说明。
建议您在熟悉 Linux 环境前适当减少快捷键的使用。