抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

Linux 是一种开放源码 (open-source) 的类 UNIX 作业系统。虽然原先 Linux 只是由 Linus Torvalds 出于个人爱好而编写,但目前,Linux 已逐渐成为人们生活中不可或缺的一部分。从嵌入式设备到超级计算机,各处都有 Linux 的身影,在移动设备上广泛使用的 Android 系统正是建立在 Linux 内核之上。得益于其优雅的权限控制及优美的学习曲线,越来越多的服务器使用 Linux 以部署服务。

通常,我们安装使用的 Linux 是指经打包后的 Linux 发行版,其中包括 Debian(包括衍生版本 Ubuntu、Linux Mint)、Fedora(包括相关版本 Red Hat Enterprise Linux、CentOS)、openSUSE、Arch Linux(包括衍生版本 Manjaro)、Gentoo,不一而足。目前,Linux 发行版基本配备了各自的图形界面,使用与 Windows 系统相仿,容易入门。

但在一些服务器系统上,如 Ubuntu Server、CentOS 等,安装图形界面(GUI)导致系统正常运行的性能需求飙升,因此通常服务器仅安装命令行界面(CLI)。同时,即使在带有图形界面的 Linux 发行版,也 不是所有 的操作都能通过图形界面完成,命令行的学习有很大的 必要性

本文希望使用 浅显易懂 的语言带读者入门 Linux。教程主要针对初学者在实际使用中 最常用 的内容展开,加入了作者自己的理解与认识,希望读者能在很短的时间内学会 Linux 的基本操作。如有更好的展开思路,欢迎各位朋友在评论区批评指正。

写在前面

本教程遵守署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议,您可以自由地共享、演绎,但需遵守署名、非商业使用、相同方式共享条件,并且保证没有附加限制。更详细的说明可参见关于页面

教程中提到的部分内容可能因为更新而不再适用,请您自行检查位于文章尾部的教程最后更新时间加以判断。如果教程内有过时内容,欢迎在评论中指出,作者会 尽快 修改。

学习本教程的前提是有一台可以正常工作的 Linux 计算机。虽然安装 Linux 系统并不是一件困难的事情,但却是一件复杂的事情,Linux 的发行版数量众多,安装过程并不能很容易地归纳为几个简单的步骤,因此本教程 并不涉及 Linux 安装方面的内容。如果您手边不幸没有 Linux 电脑,可以考虑购置一台 Linux 云服务器,或自行在实体机或虚拟机上安装 Linux 系统,相关教程很多。如果您想要和作者安装一样的工作环境,可以参考作者的另一篇文章 我的 Linux 深度学习工作环境丨环境搭建教程 的前半部分,其介绍了 Ubuntu Server 22.04 LTS 的安装过程。

本教程中涉及的命令较多且很常用,推荐大家在阅读时能 实际运行一下 这些命令,查看它们的效果。对于较短的命令,建议初学者使用键盘输入以增强记忆;对于较长的命令,鼠标移入代码块后,右上角有 COPY 按钮,可以复制,粘贴后运行,查看结果。

样式说明

本教程正文部分以正常方式书写。

对于较为重要的附加说明或建议阅读的可选内容以 默认打开的折叠框展示

这是一个默认打开的折叠框(点击可以折叠)

里面是较为重要的附加说明,建议阅读。

对于非重要的附加说明或引申内容以 默认关闭的折叠框展示

这是一个默认关闭的折叠框(点击可以展开)

里面是非重要的附加说明,或一些延伸,可以略过。

第〇章 什么是 Linux 命令

本章仅对 Linux 命令做一个初步的介绍,主要是给读者一个感性的认识,介绍一些命令的基本语法以及 Linux 自带的帮助文档如何查阅。如果读者暂时还不能连接上 Linux 终端,可以在大致浏览第〇章后,仔细阅读第一章的内容,确保连接上 Linux 终端后,再阅读第〇章的内容。第〇章的内容是 Linux 的 基础之基础,还请 务必仔细 阅读。

通常,第一次进入 Linux 命令行后,你可能会不知所措。因为你目力所及只有一个黑框框,里面有一些奇怪的英文字符,它通常是这样的:

你的命令行大概长这样
1
[xiao@server ~]$ 

其实,光标前面的这一串字符叫做 shell prompt,中文可称为“命令行提示符”。默认状态下是 用户名@主机名 的格式,在上面例子中,用户名为 xiao,主机名为 server,后面跟的 ~ 是命令行的当前目录,这将在后面介绍。美元符号($)后面就是你的光标,你输入的字符将显示在后面。

试着输入 echo "Hello World" 然后回车,你会看到命令行输出了 Hello World

恭喜你运行了你的第一个 Linux 命令!

让我们乘胜追击,理解一下 Linux 命令的基本结构:

Linux 命令基本结构
1
[xiao@server ~]$ command [-options] [arguments]
  • command 命令:表示命令的名称,例如 ls, chmod, git 等等

  • options 选项:表示命令的选项,中括号只是一个标记作用,表示这个选项是可选的,在实际书写时并不需要。通常,选项可以分为短选项与长选项。

    • 短选项:通常使用 - 引导,通常后面跟单个字符,例如 -l, -h 等。多个短选项可以直接组合,例如命令 ls -l -h 可以直接表示为 ls -lh
    • 长选项:通常使用 -- 引导,后面跟完整的单词,例如 --human-readable。例如上面的命令 ls -lh 还可写成 ls -l --human-readable
  • arguments 参数:表示命令的作用对象,有些命令可能有多个参数,也可以没有参数

Linux 中命令、选项、参数之间使用空格来区分;

Linux 中命令严格区分大小写,对 Linux 而言 lsLS 完全不同!

分析一下刚刚使用的命令 echo "Hello World" 的结构,echo 是这个命令(command)的名称,echo 有回声之意,所以其效果就是把参数字符串回显到命令行上;"Hello World" 就是命令的参数(arguments),在这里就是被回显的字符串。

如果要尝试一下选项(options)对命令的影响,试着输入 echo -n "Hello World",你大概会看到以下输出:

echo 不换行示例
1
2
[xiao@server ~]$ echo -n "Hello World"
Hello World[xiao@server ~]$

-n 选项的含义是不输出最后一个换行,所以你看到 Hello World 直接连在了 shell prompt 之后。

此后为了 方便起见,在代码说明时不再添加 shell prompt,读者清楚即可。即不再使用:

弃用的写法
1
[xiao@server ~]$ echo -n "Hello World"

转而使用:

后续 Linux 命令使用的写法
1
echo -n "Hello World"

折行

在 Linux 如果输入命令很长,可以使用反斜杠 (\) 折行,使指令续行,例如:

折行示例
1
2
3
echo "Hello world. \
I think that Xiao Space is a fascinating website. \
What you think?"

其实等价于:

原始命令
1
echo "Hello world. I think that Xiao Space is a fascinating website. What you think?"

显然,使用反斜杠折行后,代码的可读性更好了一些。一般来说,为了终端的兼容性,一行不应超过 79 个字符,如果多于 79 个字符,需要考虑折行,当然,这个规则也适用于其他编程语言。

需要注意反斜杠后必须立刻接换行符,否则可能会产生转义字符而失去续行效果。

帮助命令

如果在 Linux 中突然遇到有些记得名字的命令的选项或参数遗忘,可以查看 Linux 自带的帮助。通常,帮助命令可以归纳为 whatis, --help, man, info

whatis 命令

whatis 会显示命令简短的功能描述,命令语法:

whatis 命令语法
1
whatis command

例如:

whatis 命令示例
1
2
3
whatis echo
# output:
# echo (1) - display a line of text

--help 选项

在命令后加上 --help 通常可以显示使用方法和参数列表,有些时候,这个选项可以简写为 -h,但要注意并不是所有命令都能如此简写,例如后面将要介绍的 ls -h 就是代表以人类可读的方式显示结果,这里 -h--human-readable 的简写。因此,使用 --help 更具兼容性,命令语法:

--help 选项语法
1
command --help

例如:

--help 选项示例
1
ls --help

就会显示 ls 命令的帮助。

man 命令

man 命令可以查看命令描述或帮助手册(man 是 manual 的简称,是帮助文档的意思),命令语法:

man 命令语法
1
man [section] command

例如:

man 命令示例
1
man echo

就会进入 echo 命令的帮助手册。按 q 键可以退出。

如果出现 No manual entry for command (点击可以折叠)

通常情况,Linux 发行版会自带帮助手册。但对于一些精简的系统,可能并未安装 man,如果出现此提示,可以学习本教程第四章如何在 Linux 上安装软件,然后安装 man-pages 包及 man-db 包。

关于 section 参数(点击可以展开)

man 命令的语法中,可以看到 section 参数,section 表示帮助手册的章节数,对应关系可以通过 man man-pages 查看

man sections description
1
2
3
4
5
6
7
8
9
10
11
12
13
14
MANUAL SECTIONS
The standard sections of the manual include:

1 User Commands
2 System Calls
3 C Library Functions
4 Devices and Special Files
5 File Formats and Conventions
6 Games et. al.
7 Miscellanea
8 System Administration tools and Daemons

Distributions customize the manual section to their specifics,
which often include additional sections.

因为有些命令可能在不同的章节有重复,例如 printf 既在第 1 节,又在第 3 节,如果是要查看用户命令的 printf,使用 man 1 printf,如果是要查看 C 库中的 printf,应使用 man 3 printf

info 命令

info 命令可以查看比 man 更详细的说明,命令语法:

info 命令语法
1
info command

例如:

info 命令示例
1
info echo

就会进入 echo 命令的说明,按 Q 键可以退出。

命令帮助的特殊符号 (点击可以折叠)

在查看命令帮助时,会出现 [], <>, | 等符号,它们的含义如下:
[] 表示是可选的;
<> 表示是可变化的;
x|y|z 表示只能选择一个;
-abc 表示三个参数(或任何二个)的混合使用

查看历史命令

在 Linux 下,我们有时希望知道最近执行的命令,history 会帮上大忙:

history 示例
1
2
history 5         # 显示最近使用的5个命令
history | more # 显示使用过的所有命令

在 Linux 下,我们有时还希望直接运行历史执行过的命令,! 会帮上大忙:

! 的用法
1
2
3
!5   # 执行历史编号为 5 的命令,注意感叹号与数字间没有空格
!ls # 执行最后一次以 ls 开头的命令
!! # 执行上一次命令

一些便利的功能与快捷键

在 Linux 命令行中,你可能想中断一些耗时很长的命令的运行,亦或者是修改一些命令,或者是快速调出上一次的命令,实际上,这些操作都有快捷键可以完成,当然 Linux 命令行中的快捷键众多,这里只列出常用的部分。如对其他快捷键有兴趣,可以自行查阅 man bash

快捷键 CTRL + A:将光标移到行首

快捷键 CTRL + C:停止正在运行的任务

快捷键 CTRL + L:清屏

快捷键 TAB:命令补全

快捷键 :历史命令,可以不断向上翻阅

小结

至此,恭喜你完成了第〇章的学习!第〇章主要带读者了解了 Linux 命令的基本结构、 Linux 的一些帮助命令及一些好用的快捷键。有了这些前置知识后,现在,让我们正式开始学习 Linux 吧!

第一章 连接到 Linux 终端

要想熟练使用 Linux 终端,头等要事当然是打开 Linux 终端。但可能,这件事可能有些时候并没有想象中那么容易。

图形界面 Linux 发行版

如果你在计算机上安装了带图形界面的 Linux 发行版,通常当你进入桌面系统后,可以在所有程序中找到“终端”软件,然后打开。

如果你使用 GNOME 或 KDE 桌面,你通常可以使用快捷键 CTRL + ALT + T 打开终端。这里的 T 是 Terminal(终端)的首字母。

不带图形界面的 Linux 发行版

如果你使用了不带图形界面的 Linux 发行版,那么你启动计算机后,就会自动进入终端,你只需输入账户名及密码即可。

远程连接上 Linux 终端

如果你的服务器安装了 Linux,但你希望通过远程方式访问,那么通常会使用 ssh (Secure SHell, 安全外壳协议) 命令连接到 Linux 服务器。这时,服务端与客户端都需要进行一些配置。虽然配置 ssh 服务端(简称 sshd)很明显超出了本章的内容,但好在,通常 Linux 服务器版本都自带 sshd 服务,因此本章中我们默认认为其是开启的。即服务端的配置是完美的。

如果你一定要检查 ssh 服务端是否开启 (点击可以展开)

如果你想确认自己的 Linux 服务器是否开启了 ssh 服务,那么可以分为以下两种情况:

如果你的服务器是使用的 service 作为守护进程服务,那么可以运行以下命令:

使用 service 检查 sshd 是否开启
1
service sshd status

如果看到 Active: active (running) 字样,说明 sshd 正在运行。

如果你的服务器使用 init.d 作为守护进程服务,那么可以运行以下命令:

直接使用 status 检查 sshd 是否开启
1
/etc/init.d/sshd status

当然如果你不清楚具体的使用,你可以尝试运行上述两种命令,如果有一种提示正常,那么说明服务器已经开启了 ssh 服务。

如果你的 ssh 未做特殊配置,那通常开放在 22 端口,所以若你没有更改端口,你还可以通过以下命令检查:

使用 lsof 命令检查 sshd 是否开启
1
lsof -i :22

如果你没有安装 lsof 命令,那么可以使用相应的包管理器安装后再进行检查,具体可以参见第四章内容。

下面就要进行客户端的配置了,其实这一部分并不复杂,如果你的个人电脑就是 Linux 系统或是 macOS 系统,那么默认是安装了 ssh 客户端的,这里并不需要多做配置;如果你是 Windows 电脑,并且是 Windows 8 或更高的系统,那么 ssh 客户端也已经安装;如果是 Windows XP 或 Windows 7,那么需要自行安装 OpenSSH 程序。由于安装程序较为简单,因此这一部分不再赘述。下面分系统介绍如何打开客户端电脑的终端(命令提示符)。

Linux, macOS 系统打开终端

如果使用 Linux 或 macOS 系统,可以打开系统内置的终端(在 macOS 上,这通常被称为终端模拟器)。

Windows 系统打开命令提示符

在 Windows 系统下,你要先打开命令提示符(cmd)或 PowerShell 才能输入命令。

打开命令提示符,你可以使用 Win + R 快捷键打开运行,在里面输入 cmd 后回车(或点击确定),即可打开命令提示符。当然也可以使用 Windows 搜索,搜索命令提示符或 PowerShell 后打开。

命令提示符界面
命令提示符界面

运行 ssh 命令

打开终端后,可以输入以下命令:

ssh 命令示例
1
2
3
4
ssh username@IP [-p port]
# e.g.
ssh [email protected]
ssh [email protected] -p 1000

ssh 是命令的名称,username 是你想登录的远程账号的用户名,后面接 @ 符号,然后紧跟远程主机的 IP 地址。如果你的服务器的 ssh 服务监听的端口不是 22 端口,那么可以使用 -p 选项指定端口,后面跟端口号即可。如果你不确定远程主机的 IP 地址,通常可以在远程主机上运行 ifconfig 命令查看,当然,对于初学者,往往直接询问网管或服务器相关人员更佳。

运行后,大概率会提示以下内容:

ssh 第一次连接显示的警告
1
2
3
The authenticity of host '192.168.1.100 (92.168.1.100)' cant be established.
ECDSA key fingerprint is SHA256:ZNfwzV12wqfsO0iYpIywNsBPYhta5TTaKBfzEl5TBos.
Are you sure you want to continue connecting (yes/no/[fingerprint])?

这是因为第一次连接到这个服务器,这个服务器的 IP 和对应的指纹还没有被客户端记录为可信的,所以弹出了一个警告,这时输入 yes 然后回车即可。当你同意后,你会发现提示了以下内容:

永久添加指纹后显示的警告
1
Warning: Permanently added '192.168.1.100' (ECDSA) to the list of known hosts.

这个警告提醒你已经将这个 IP 和对应的指纹加入了信任的列表,以后将不再提示。

恭喜你已经连接上终端了!

不输入密码连接 ssh(点击可以折叠)

当你使用 ssh 连接服务器时,每次都要输入密码,如果密码简单还好,但通常,服务器密码为了安全,都有大小写字母、数字、特殊字符构成,每次登录都要输入未免太过麻烦,那么,有没有一种方法可以不输入密码连接 ssh 呢?

当然有!而且还使用广泛!并且还更加安全!那就是使用密钥的方式登录。

密钥形式登录的原理是:利用密钥生成器制作一对密钥 —— 一只公钥和一只私钥。将公钥添加到服务器的某个账户上,然后在客户端利用私钥即可完成认证并登录。这样一来,没有私钥,任何人都无法通过 ssh 暴力破解你的密码来远程登录到系统。此外,如果将公钥复制到其他账户甚至主机,利用私钥也可以登录。

下面来讲解如何制作密钥对,将公钥添加给账户,设置 ssh,最后通过客户端登录。

如果你的客户端使用的是 Windows 系统,那么作者这里建议你安装 Git for Windows,这会为后面的安装带来很多的便利。你可以点击上面的连接,下载最新的 64 位版本,然后安装。Git 其实是一个非常好用的版本控制工具,作者也会在后面的章节进行介绍。在安装完成后,可以在开始菜单找到刚刚安装的 Git,并且会生成几个快捷方式,双击打开 Git Bash。如果你使用的是 Linux 系统或 macOS系统,直接打开终端即可。

为了与后面的 github 更好地兼容,我们运行以下命令生成一对密钥:

ssh-keygen 使用个人邮箱生成密钥对
1
ssh-keygen -t rsa -b 4096 -C "[email protected]"

注意将 [email protected] 改为你的邮箱,如果你有 github 的账号,请改为你的 github 账号的注册邮箱。按回车后,会提示密钥的存储位置,这里保持默认即可。确认后,提示输入密钥的密码,通常情况下,这里可以留空,所以直接回车即可。按回车后,需要重复一遍密码,由于上次留空,这里再按一次回车即可。这样就生成好了公钥、私钥对。通常默认命名下,公钥是 id_rsa.pub 后缀是 public 的前三个字母,私钥是 id_rsa 无后缀。

私钥可以认为就是你的电脑的指纹,请务必妥善保存,否则别人就可以任意登录你的服务器,这是非常危险的!请注意,任何网站或服务器都不会索要你的私钥,因此请记住,私钥不上网!

第二步,就是在服务器上安装公钥。这一步只需运行命令:

使用 ssh-copy-id 将公钥安装到服务器
1
ssh-copy-id -i ~/.ssh/id_rsa.pub username@IP

需要注意,要将 -i 选项后的路径替换为你的 id_rsa.pub 的路径,username 为服务器端的用户名,IP 为服务器的地址。实际上 ssh-copy-id 命令就是将公钥写入服务器的 ~/.ssh/authorized_key 文件中,只不过帮我们自动完成了上传公钥、写入文件、修改权限的操作。

最后,测试一下是否可以无密码登入:

测试 ssh 免密登录
1
ssh username@IP

如果你没有输入密码就已经登录了终端,恭喜你完成了无密码登录。实际上这一生成的密钥对中的公钥可以用于多个服务器,如果想要免密登陆第二台服务器时,只需要运行第二步即可。

终端与 shell 的争论(点击可以展开)

其实,在上面的叙述中,作者将终端与 shell 混为一谈,但严谨来看,它们是完全的不同的事物。通常意义下,可以认为终端负责输入命令,而 shell 负责解释命令并传递给内核。终端一词其实诞生在上世纪,诞生在那个计算机计算中心化,人们使用的通常是一套输入设备来操作计算机的时代(这套输入设备被称为终端)。因此,终端一词发展至今已然日渐式微,目前已经很难明晰终端与 shell 的界限。

当然,本文将终端与 shell 不做区分,并不是认为这两者区分并无必要,只是方便初学者的理解考量。因为初学者更在意与他交互的这个黑色窗口好不好用,而并不是这个窗口的名字到底是什么!

终端的介绍

通常情况下,当你使用 Linux 终端时,默认使用的 shell 是 bash(Bourne-Again SHell),它是 sh 的后继兼容版本。对初学者而言,这个 shell 功能已经足够强大。但如果你还有其他追求,例如代码补全、自动目录跳转等等,在后续使用中也可以使用其他 shell,例如 zsh、fish 等。需要注意的是,不同的 shell 的语法有微妙的区别,有时一种 shell 的脚本并不能在另一种 shell 中运行。本教程默认使用 bash 教学。

我不想在命令提示符中敲命令

如果你使用的是 Windows 系统,那你大概会觉得命令提示符实在是太丑陋了,实际上,正常的 Linux 使用者也不会将命令提示符作为自己的主要工作环境。目前已经有相当多好用、易用的终端工具,例如 PuTTY、MobaXterm 等等,这些工具或多或少方便了 Linux 终端使用,有些还自带了文件传输的功能,推荐初学者尝试。作者的工作流主要使用 Windows Terminal + Visual Studio Code 两款软件。限于篇幅,作者将自用的 Linux 环境搭建以及一些终端的美化技巧放在了 我的 Linux 深度学习工作环境丨环境搭建教程 中,欢迎读者查看。

至此,恭喜你完成了第一章的学习!第一章主要带读者了解了如何连接到 Linux 终端。并且还讲解了一些关于免密登录终端的技巧及一些关于终端的小知识。后者仅是一些拓展,并不需要完全掌握。阅读完本章后,你只需要连接上一个可以正常运行 Linux 命令的终端即可,不论这是本地的终端,还是通过 ssh 远程连接的终端,并不会影响后续章节的学习。

第二章 了解 Linux 文件操作

了解了 Linux 命令的基本结构并且连接上终端之后,我们就要正式开始学习 Linux 命令了。但是在学习之前,还请允许作者介绍一下 Linux 的文件系统,不同于 Windows 系统,Linux 万物皆文件。正确理解 Linux 文件系统是后续学习 Linux 的基石。

Linux 文件系统

不同于 Windows 系统的盘符,Linux 系统只有一个根目录,不同的分区可以使用 挂载的方式 挂载到指定的挂载点上。Linux 所有的文件和目录都被组织成一个以根节点开始的树状结构。根目录使用 / 表示。当你在终端中输入:ls / 后会看到以下输出:

ls / 命令的输出
1
2
bin  boot  dev  etc  home  lib  lib32  lib64  libx32  lost+found  media
mnt opt proc root run sbin snap srv sys tmp usr var

下面对其中的重要目录进行一些解释:

  • /bin 目录
    bin 是 binaries (二进制文件) 的缩写,这个目录存放着最经常使用的命令。

  • /boot 目录
    这里存放的是 启动 Linux 时使用的一些核心文件,包括一些连接文件以及镜像文件。

  • /dev 目录
    dev 是 device (设备) 的缩写,该目录下存放的是 Linux 的外部设备,在 Linux 中访问设备的方式和访问文件的方式是相同的。

  • /etc 目录
    etc 是 etcetera (等等) 的缩写,这个目录用来存放所有的系统管理所需要的 配置文件 和子目录。

  • /home 目录
    用户的 主目录,在 Linux 中,每个用户都有一个自己的目录,一般该目录名是以用户的账号命名的,例如,如果你的用户名是 xiao,那么你的主目录就是 /home/xiao

  • /lib 目录
    lib 是 library (库) 的缩写,这个目录里存放着系统最基本的动态连接共享库,其作用类似于 Windows 里的 DLL 文件。几乎所有的应用程序都需要用到这些共享库。

  • /lost+found 目录
    这个目录一般情况下是空的,当系统非法关机后,这里就存放了一些文件。

  • /media 目录
    Linux 系统会自动识别一些设备,例如U盘、光驱等等,当识别后,Linux 会把识别的设备挂载到这个目录下。

  • /mnt 目录
    mnt 是 mount (挂载) 的缩写,系统提供该目录是为了让用户临时挂载别的文件系统的,我们可以将光驱挂载在 /mnt/ 上,然后进入该目录就可以查看光驱里的内容了。

  • /opt 目录
    opt 是 optional (可选) 的缩写,这是给主机额外安装软件所摆放的目录。比如你安装一个ORACLE数据库则就可以放到这个目录下。默认是空的。

  • /proc 目录
    proc 是 processes (进程) 的缩写,/proc 是一种伪文件系统(也即虚拟文件系统),存储的是当前内核运行状态的一系列特殊文件,这个目录是一个虚拟的目录,它是系统内存的映射,我们可以通过直接访问这个目录来获取系统信息。

  • /root 目录
    该目录为系统管理员,也称作超级权限者的用户主目录。

  • /sbin 目录
    s 就是 super user 的意思,sbin 是 superuser binaries (超级用户的二进制文件) 的缩写,这里存放的是系统管理员使用的系统管理程序。

  • /srv 目录
    src 是 service (服务) 的缩写,该目录存放一些服务启动之后需要提取的数据。

  • /sys 目录
    sys 是 system (系统) 的缩写,具体的内容这里并不介绍。

  • /tmp 目录
    tmp 是 temporary (临时) 的缩写,这个目录是用来存放一些临时文件的。

  • /usr 目录
    usr 是 unix shared resources (共享资源) 的缩写,注意不是 user 的缩写,这是一个 非常重要 的目录,用户的很多应用程序和文件都放在这个目录下,类似于 Windows 下的 Program Files 目录。

  • /usr/bin 目录
    系统用户使用的应用程序。

  • /usr/sbin 目录
    超级用户使用的比较高级的管理程序和系统守护程序。

  • /usr/src 目录
    src 是 source (源代码) 的缩写,该目录是内核源代码默认的放置目录。

  • /var 目录
    var 是 variable (变量) 的缩写,这个目录中存放着在不断扩充着的东西,我们习惯将那些经常被修改的目录放在这个目录下。包括各种日志文件。

  • /run 目录
    是一个临时文件系统,存储系统启动以来的信息。当系统重启时,这个目录下的文件应该被删掉或清除。

在实际使用过程中,系统管理员操作最多的当属 /etc, /usr, /root 目录,普通用户访问最多的是自己的用户目录,即 /home/username 目录。

在 Linux 文件系统中,还有几个特殊的目录,一个是用户所在的工作目录(working directory),也被称为当前目录,可以使用一个点 . 表示。还有一个是当前目录的上一级目录,也称为父目录,可以使用两个点 .. 表示。还有一个是用户的用户目录,也被称为家目录,可以使用一个波浪号 ~ 表示,对普通用户来说,就是代表 /home/username 目录,对超级用户来说,就是代表 /root 目录。

另外,如果一个目录或文件名以一个点 . 开始,表示这个目录或文件是一个隐藏目录或文件 (如:.bashrc)。即以默认方式查找时,不显示该目录或文件。

注意,如果你的 Linux 系统还有 /swap 目录,这说明你的系统启用了交换分区,交换分区是可以使用硬盘的一部分空间当作内容使用,对于小内存的机器非常有用,如果你的机器有很大的内存,也 并不意味着 你可以不使用交换分区。Linux 系统会在交换分区中存储一些重要运行时,请 务必不要 将交换分区关闭。当然,目前已经不再推荐使用交换分区,因为分区后交换空间的大小难以更改,目前更推荐的是使用 swapfile(交换文件),即使用一个文件代替分区。

使用命令创建交换文件并启用 (点击可以展开)

通常,这是系统管理员需要做的事情,这里做一些介绍,并不推荐初学者运行,除非你清楚每个命令的作用及后果。

创建交换文件并启用
1
2
3
4
5
6
sudo dd if=/dev/zero of=/swapfile bs=1M count=2048  # 创建一个 2GB 的位于根目录下的
# 交换文件
sudo mkswap /swapfile # 将文件格式化为交换文件
sudo chmod 600 /swapfile # 修改权限为仅 root 可读写
sudo swapon /swapfile # 启用交换文件
free -m # 查看 Linux 的内存情况

如果你看到 Swap 一项增加了 2GB ,那么恭喜你已经开启交换文件成功了。但是现在每次启动后都要手动输入 swapon 命令才能开启,所以我们还需要写入开机启动项。

将交换文件设为开机启动
1
echo "/swapfile swap swap defaults 0 0" >> /etc/fstab

这样重启后,系统会自动挂载交换文件。当然,在实际使用中,你会发现内存占用少的时候,交换空间基本不起作用,如果你想在有充裕的内存的情况下也使用交换空间,可以使用以下命令查看交换空间的使用倾向:

查看交换空间的偏好值
1
cat /proc/sys/vm/swappiness

这个值越接近 100,意味着越偏向于使用交换空间而非物理内存,需要注意,将这个值增大会显著影响 Linux 系统的运行效率。你可以这样修改交换空间的偏好值:

修改交换空间偏好值
1
echo "vm.swappiness=90" >> /etc/sysctl.conf

修改完成后重启即可看到更改。

Linux 的文件和目录严格区分大小写,./me/./Me/ 是完全不同的两个目录,./me.py./Me.py 是完全不同的两个文件,这一点与 Windows 系统的默认行为大不相同,Windows 下目录和文件是不区分大小写的,这意味着同一文件夹下不可能同时出现 ./me.py./Me.py 文件,因为 Windows 认为这两个是同一个文件!请初学者务必注意其差别。

Linux 文件系统相关命令

在了解了 Linux 文件系统后,我们就可以正式开始 Linux 文件系统相关命令的学习了。Linux 中和文件操作相关的命令很多,这里只列举初学者最常用的一些命令,主要有 pwd, cd, ls, cp, mv, touch, rm, mkdir, rmdir, cat, head, tail, grep, find, zip, tar, nano, vi, ln

你很有可能会觉得这些命令都难以理解,但这是为了输入效率而做出的 妥协。因为毕竟所有命令都需要手动输入,如果命令本身能短一些,那么输入的效率就会高很多。实际上,这些命令大多是其功能的缩写,如果理解了,还是很好记忆的!

另外,由于 Linux 中万物皆文件,其实上 目录也是一种特殊的文件,后文我们在讲解命令语法时,不再区分文件路径和目录路径这两个名词,都统一使用 FILE 指代。

目录相关

  • pwd
    pwd 可以显示当前工作目录,是 Print Working Directory 的缩写。

  • cd
    cd 可以更改当前的工作目录,是 Change Directory 的缩写。

cd 命令示例
1
2
3
4
5
6
cd [FILE]
# e.g.
cd # 回到家目录
cd ~ # 回到家目录,与 cd 等价
cd .. # 进入上级目录
cd / # 进入根目录
  • ls
    ls 可以查看目录或文件信息,是 list 的缩写。
ls 命令示例
1
2
3
4
5
6
7
8
ls [OPTION]... [FILE]...
# e.g.
ls # 列出当前目录下的文件
ls / # 列出根目录下的文件
ls -a # -a (--all) 列出当前目录下的所有文件,含隐藏文件
ls -l # 这里的 -l 是 long 的意思,列出当前目录下文件的详细信息,包含权限、
# 修改信息等
ls -lh # -h (--human-readable) 使用人类可读的方式列出,空间占用会使用 K、G 等单位

复制、移动、创建、删除文件或目录

  • cp
    cp 可以复制文件或目录,是 copy 的缩写。
cp 命令示例
1
2
3
4
5
6
7
8
cp [OPTION]... [-T] SOURCE DEST
cp [OPTION]... SOURCE... DIRECTORY
cp [OPTION]... -t DIRECTORY SOURCE...
# e.g.
cp a.txt b.txt # 复制 a.txt 并另存为 b.txt
cp a.txt ../ # 复制 a.txt 到父目录
cp -r ./a ../ # -r (--recursive) 可以递归复制文件夹,这个命令是将文件夹 a 及其所有
# 内容复制到父目录
  • mv
    mv 可以移动或重命名文件,是 move 的缩写。
mv 命令示例
1
2
3
4
5
6
7
8
mv [OPTION]... [-T] SOURCE DEST
mv [OPTION]... SOURCE... DIRECTORY
mv [OPTION]... -t DIRECTORY SOURCE...
# e.g.
mv a.txt b.txt # 将 a.txt 重命名为 b.txt
mv a.txt ../ # 移动 a.txt 到父目录
mv ./a ../ # 移动文件夹 a 到父目录,注意 mv 可以直接移动文件夹所有内容,不需要
# 加上递归选项
  • touch
    touch 可以创建一个空白文件,如果当前目录有同样的文件,则会更新文件的修改时间
touch 命令示例
1
2
3
touch [OPTION]... FILE...
# e.g.
touch a.txt # 在当前目录下创建 a.txt
  • rm
    rm 可以删除文件或文件夹,是 remove 的缩写。
rm 命令示例
1
2
3
4
5
rm [OPTION]... [FILE]...
# e.g.
rm ./a.txt # 删除文件 a.txt
rm -r ./a # -r (--recursive) 递归删除文件夹 a
rm -f [FILE] # -f (--force) 强制删除

rm 命令是一个非常危险的命令,不像 Windows 系统,Linux 系统没有回收站,因此删除后就无法找回。因此,一般的 shell 会将 rm 作为 rm -i 的别名,具体的别名方式会在第三章介绍,这里只需要知道在 bash 中,rm 其实是 rm -i,而 -i 选项会在每次移除时提示你,并要求你做确认。

!!!如果不是特殊需求,慎用 -f 选项强制删除!!!

  • mkdir
    mkdir 可以创建一个文件夹,是 make directory 的缩写,有的 shell 还可以进一步简写为 md
mkdir 命令示例
1
2
3
4
5
6
7
mkdir [OPTION]... DIRECTORY...
# e.g.
mkdir a # 在当前目录下新建 a 文件夹
mkdir -p ./a/b # -p (--parents) 递归地创建文件夹,如果 a 不存在,则会先创建 a
# 文件夹,再在 a 下创建 b 文件夹
# 等价于 mkdir ./a ./a/b
mkdir -v ./a # -v (--verbose) 显示创建文件夹的详细信息
  • rmdir
    rmdir 可以删除一个空文件夹,是 remove directory 的缩写,有的 shell 可以进一步简写为 rd
rmdir 命令示例
1
2
3
4
5
rmdir [OPTION]... DIRECTORY...
# e.g.
rmdir a # 删除当前目录下的空文件夹 a
rmdir -p ./a/b # -p (--parents) 递归地删除文件夹
# 等价于 rmkdir ./a/b ./a

rmdir 一般用于删除空文件夹,如果文件夹中有文件,建议使用 rm 命令。

查看文件

  • cat
    cat 命令可以查看文件的内容,是 concatenate 的缩写。cat 命令常和输入输出重定向运算共同使用,以完成拼接文件等操作。
cat 命令示例
1
2
3
4
5
6
7
8
9
10
11
12
13
cat [OPTION]... [FILE]...
# e.g.
cat a.txt # 在终端上打印 a.txt 中的内容
cat > a.txt # 创建 a.txt 文件,并且接受终端输入,按 Ctrl + C 停止输入并保存
# 这里第一次出现了重定向运算符,不理解没有关系,这将在后面介绍

# 使用 <<EOF 可以输入大段文字,结束输入时使用 EOF 即可,EOF 不会出现在文件中
# 这种语法被称为 heredoc,初学者只需了解即可
cat > a.txt <<EOF
Hello world.
I think that Xiao Space is a fascinating website.
What you think?
EOF
  • head
    head 命令可以打印文件的开头几行
head 命令示例
1
2
3
4
5
head [OPTION]... [FILE]...
# e.g.
head a.txt # 打印 a.txt 的开头 10 行
head -n 5 a.txt # -n (--lines=) 打印 a.txt 的开头 5 行
head -n -5 a.txt # 从 a.txt 的开头打印到倒数第 5 行,不含倒数第五行
  • tail
    tail 命令可以打印文件的结尾几行
tail 命令示例
1
2
3
4
5
tail [OPTION]... [FILE]...
# e.g.
tail a.txt # 打印 a.txt 的结尾 10 行
tail -n 5 a.txt # -n (--lines=) 打印 a.txt 的结尾 5 行
tail -n -5 a.txt # 从 a.txt 的开头第 5 行打印到文件结尾,不含第五行
  • grep
    grep 命令用于查找文件里符合条件的字符串,属于高级的 Linux 命令,这里仅作介绍,初学者用到的频率很少。

  • find
    find 命令用来在指定目录下查找文件,也是属于高级的 Linux 命令,这里仅作介绍,初学者用到的频率很少。

压缩与解压

在 Windows 上,我们经常会进行文件压缩、解压的操作,在 Linux 中,也有同样的操作。

  • zip
    zip 是文件压缩命令,命令参数很多,这里只介绍常用的内容,如有需求,可以使用 man zip 查看更多帮助。
zip 命令示例
1
2
zip -r test.zip ./test  # 压缩 test 文件夹生成 test.zip
unzip test.zip # 解压 test.zip
  • tar
    tar 可以创建文件归档包,在 Linux 中非常常用,是 tape archive 的缩写。tar 的命令参数很多,这里只介绍常用的内容,如有需求,可以使用 man tar 查看更多帮助。
tar 命令示例
1
2
tar -czvf test.tar.gz ./test  # 压缩 test 文件夹生成 test.tar.gz
tar -xzvf test.tar.gz # 解压 test.tar.gz

这里的选项较多,-c 表示 --create 即创建压缩文件;-z 表示 --gzip 即使用 gzip 压缩;-v 表示 --verbose 即显示命令的详细执行过程;-f 表示 --file 后面跟要创建的归档名,也就是压缩包名;-x 表示 --extract 即提取压缩文件。

当然,如果不使用 gzip 压缩,还可以使用以下的命令:

tar 命令示例,不使用 gzip
1
2
tar -cvf test.tar ./test   # 压缩 test 文件夹生成 test.tar
tar -xvf test.tar # 解压 test.tar

文本编辑器

在 Linux 上,我们常常会有文本编辑的需求,通常,我们使用 nanovi 进行文本编辑。

  • nano
    nano 是一个字符终端的文本编辑器,它比 vi、vim 要简单得多,比较适合 Linux 初学者使用。
nano 使用
1
2
nano test.txt       # 编辑 test.txt
nano -w test.txt # 关闭 nano 的自动换行
nano 编辑器截图
nano 编辑器截图

进入 nano 编辑器后,你会在整个终端的下侧看见快捷键提示,使用其提示的快捷键即可完成文件编辑,保存的操作,其中,^X 表示 CTRL + XM-U 表示 ALT + U,依此类推。

编辑完成后,使用 CTRL + O 写入所做的修改,这时 nano 会询问你写入文件的文件名,如果文件名不改变,直接回车即可,这样就可以保存文件,然后使用 CTRL + X 退出 nano。

  • vi / vim
    所有的 Unix Like 系统都会内置 vi 文书编辑器,其他的编辑器则不一定会存在。但是 vi 有一定的学习成本,目前使用更多的是 vi 的改进版 vimvim 具有程序编辑的能力,可以主动的以字体颜色辨别语法的正确性,方便程序设计。vim 的键盘图如下:
vim 键盘图
vim 键盘图

不要被这些花花绿绿的按键吓住,其实在实际使用中,常用的按键并不多,也很好记忆。如果你想学习 vim 的使用,可以在终端输入 vimtutor,这时会有一个帮助教程教你使用 vim。放心,这个教程非常简单!整个教程的时长大约 20 ~ 40 分钟,学习完成后,多使用几天 vim 就能熟练掌握,这会给编程效率带来很大的提升。如果你对作者使用的 vim 环境感兴趣,可以点击作者的另一篇文章 我的 Linux 深度学习工作环境丨环境搭建教程 查看。

作者的 vim 截图
作者的 vim 截图

由于 vim 非常常用,所以这里也大略介绍一下 vim,旨在让初学者迅速了解如何编辑、保存一个文件,如果想进一步学习,最好还是跟随 vimtutor 学习。

vim 简要教程 (点击可以折叠)

基本上 vi/vim 共分为三种模式,分别是命令模式(Command mode),输入模式(Insert mode)和底线命令模式(Last line mode)。 这三种模式的作用分别是:

命令模式

用户刚刚启动 vi/vim,便进入了命令模式。此状态下敲击键盘动作会被Vim识别为命令,而非输入字符。比如我们此时按下 i,并不会输入一个字符,i 被当作了一个命令。

以下是常用的几个命令:

i 切换到输入模式,以输入字符。
: 切换到底线命令模式,以在最底一行输入命令。
x 删除当前光标所在处的字符.
dd 删除当前光标所在行的所有字符。
gg 将光标定位到文件的开头
G 将光标定位到文件的结尾
^ 将光标定位到一行的开头
$ 将光标定位到一行的结尾

若想要编辑文本:启动 Vim,进入了命令模式,按下 i,切换到输入模式。初学者常犯的错误就是在命令模式下输入字符,必须要切换到输入模式才能输入字符!

当然,命令模式只有一些最基本的命令,因此仍要依靠底线命令模式输入更多命令。

输入模式

在命令模式下按下 i 就进入了输入模式。

在输入模式中,可以使用以下按键:

字符按键以及 Shift 组合键,输入字符;
回车键 Enter,换行;
退格键 Backspace,删除光标前一个字符;
删除键 Delete,删除光标后一个字符;
方向键,在文本中移动光标
退出 ESC,退出输入模式,切换到命令模式

底线命令模式

在命令模式下按下 :(英文冒号)就进入了底线命令模式。底线命令模式可以输入单个或多个字符的命令,可用的命令非常多。

在底线命令模式中,基本的命令有(已经省略了冒号):

q 退出程序
w 保存文件
wq 保存并退出
q! 不保存,强制退出

文件链接 ln 命令

ln 是 Linux 的一个 非常重要 的命令,是 link files 的缩写,它的功能是为某一个文件在另外一个位置建立一个同步的链接。当我们需要在不同的目录,用到相同的文件时,我们不需要在每一个需要的目录下都放一个必须相同的文件,我们只要在某个固定的目录,放上该文件,然后在其它的目录下用 ln 命令链接(link)它就可以,不必重复的占用磁盘空间。

链接分为两种:硬链接 (hard link) 与软链接 (symbolic link),硬链接的意思是一个档案可以有多个名称,而软链接的方式则是产生一个特殊的档案,该档案的内容是指向另一个档案的位置。硬链接是存在同一个文件系统中,而软链接却可以跨越不同的文件系统。通常,我们使用 软链接

ln 命令示例
1
2
3
4
5
6
7
8
9
ln [OPTION]... [-T] TARGET LINK_NAME
ln [OPTION]... TARGET
ln [OPTION]... TARGET... DIRECTORY
ln [OPTION]... -t DIRECTORY TARGET...
# e.g.
ln a.txt b.txt # 给文件创建硬连接,b.txt 和 a.txt 的各项属性均相同
ln -s a.txt b.txt # -s (--symbolic) 给文件创建软链接,b.txt 相当于 a.txt 的
# 快捷方式
ln -s -f a.txt b.txt # -f (--force) 如果 b.txt 存在,也强制链接到 a.txt

硬连接只能链接在同一文件系统下的文件,既不能跨文件系统,也不能链接目录,而软链接皆可链接。

随处可见的链接(点击可以折叠)

在 Linux 中,随处可见链接,例如使用 ls -lh /,你可以看到以下输出:

ls -lh / 命令的输出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
total 8.1G
lrwxrwxrwx 1 root root 7 Apr 21 00:57 bin -> usr/bin
drwxr-xr-x 4 root root 4.0K Jun 17 07:52 boot
drwxr-xr-x 20 root root 4.4K Jun 17 08:47 dev
drwxr-xr-x 125 root root 4.0K Jun 22 05:59 etc
drwxr-xr-x 3 root root 4.0K Jun 11 07:51 home
lrwxrwxrwx 1 root root 7 Apr 21 00:57 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Apr 21 00:57 lib32 -> usr/lib32
lrwxrwxrwx 1 root root 9 Apr 21 00:57 lib64 -> usr/lib64
lrwxrwxrwx 1 root root 10 Apr 21 00:57 libx32 -> usr/libx32
drwx------ 2 root root 16K Jun 11 07:41 lost+found
drwxr-xr-x 2 root root 4.0K Apr 21 00:57 media
drwxr-xr-x 2 root root 4.0K Apr 21 00:57 mnt
drwxr-xr-x 3 root root 4.0K Jun 11 09:09 opt
dr-xr-xr-x 713 root root 0 Jun 17 07:54 proc
drwx------ 6 root root 4.0K Jun 17 06:48 root
drwxr-xr-x 31 root root 1020 Aug 16 13:09 run
lrwxrwxrwx 1 root root 8 Apr 21 00:57 sbin -> usr/sbin
drwxr-xr-x 6 root root 4.0K Apr 21 01:02 snap
drwxr-xr-x 2 root root 4.0K Apr 21 00:57 srv
-rw------- 1 root root 8.0G Jun 11 07:42 swap.img
dr-xr-xr-x 13 root root 0 Jun 17 07:54 sys
drwxrwxrwt 21 root root 12K Aug 16 10:42 tmp
drwxr-xr-x 14 root root 4.0K Apr 21 00:57 usr
drwxr-xr-x 13 root root 4.0K Apr 21 01:01 var

在每行的开头,你会发现有一串奇怪的字符,其中第一个字符就是这个文件的属性,d 表示 directory 即目录,l 表示 link 即链接,- 表示普通文件。观察链接项,后面使用了 -> 符号表示了链接到的内容。说明在根目录下,其实 /bin 目录是 /usr/bin 的一个软链接。如果你运行 ls -lh /bin/ls -lh /usr/bin/,你会发现它们的输出一模一样!当然,如果你使用 ls -lh /binls 命令会告诉你这是一个链接。

使用链接,我们也可以像 Windows 一样创建快捷方式。

终端命令补充

以上介绍了 Linux 常用的文件处理命令,了解这些命令后,基本就可以很愉快地处理 Linux 上的文件了,也恭喜你有耐心看到这里,下面作者打算补充两个小知识点,可以让终端命令使用更加高效。

输入输出重定向

在 Linux 实际使用过程中,我们可能希望将一些命令打印的内容输出到文件,或是将一些命令的输入从文件中读取,shell 也提供了这样的方法,即使用输入输出重定向运算符 >, >>, <

输出重定向示例
1
2
echo "Hello World" > hello.txt
echo "Hello World" >> hello.txt

其中,> 直接把内容生成到指定文件,会 覆盖 源文件中的内容,如果文件不存在会直接生成该文件;>> 则在文件尾部 追加,不会覆盖掉文件中原有的内容,如果文件不存在会直接生成该文件。

重定向深入讲解(点击可以展开)

一般情况下,每个Linux 命令运行时都会打开三个文件

  • 标准输入文件 (stdin):stdin 的文件描述符为0,Linux 程序默认从 stdin 读取数据。
  • 标准输出文件 (stdout):stdout 的文件描述符为1,Linux 程序默认向 stdout 输出数据。
  • 标准错误文件 (stderr):stderr 的文件描述符为2,Linux 程序会向 stderr 流中写入错误信息。

默认情况下,command > file 将 stdout 重定向到 file,command < file 将 stdin 重定向到 file。如果希望 stderr 重定向到 file,可以这样写:

标准错误重定向
1
command 2>file

其中,2 表示标准错误文件 (stderr)。

如果希望将 stdout 和 stderr 合并后重定向到 file,可以这样写:

标准输出与标准错误重定向
1
command > file 2>&1

在 Linux 中,有一个特殊文件,/dev/null,写入它的所有内容都会被直接丢弃,如果尝试从该文件读取内容,那么什么也读不到。所以,如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null

丢弃命令输出
1
command > /dev/null

如果也想同时屏蔽标准错误信息,则可以写为:

丢弃命令所有输出
1
command > /dev/null 2>&1

这里的 2> 之间不可以有空格,2> 是一体的时候才表示错误输出。

在一行执行多条命令

很多情况下,我们需要在同一行输入多条命令,或是根据上一条命令的结果执行一些命令,这时可以使用 &&, || 完成命令的连接,用法如下:

&&, || 使用示例
1
2
command1 && command2
command1 || command2

其中,&& 是如果前一条命令执行成功则执行下一条命令,即如果 command1 执行成功,则执行 command2||&& 命令相反,执行不成功时执行后续命令,即如果 command1 执行失败,则执行 command2

例如我们可以使用

&& 举例
1
mkdir a && cd a

这样就可以先创建文件夹 a,如果文件夹创建成功,则进入文件夹 a。

还有一种不同寻常的命令连接方式,就是通过管道运算符 |,使用如下:

管道运算示例
1
command1 | command2

管道运算可以将前面进程的输出(stdout)直接作为下一个进程的输入(stdin),这在一些命令使用时非常便利。

管道使用示例
1
ps aux | grep bash

其中 ps aux 是显示 Linux 的所有进程,然后使用管道传递到 grep 命令,表示查找其中的 bash 字符串,这样终端就会输出 bash 进程的信息。

至此,恭喜你完成了第二章的学习!第二章主要带读者了解了 Linux 文件系统及其对应的命令,学会后,就可以愉快地操作 Linux 系统的文件了,当然,在使用过程中,你可能会遇到你没有修改某个文件的权限,或是无法进入某个目录。下面,第三章将介绍 Linux 的用户与权限控制的相关内容,让你的普通用户也能在运行一些命令时提权为管理员用户!

第三章 Linux 用户与权限控制

我们都说,Linux 很安全,这与 Linux 的用户权限控制是分不开的。在 Linux 上,没有权限意味着你没有办法读、写、执行一些文件。并且,对 Linux 而言,root 用户(特权用户)几乎能干任何事,甚至可以删除整个系统!

Linux 的权限管理,与两个重要的特性关联紧密:一切皆文件;多用户操作系统。多用户操作系统,意味着用户之间的资源需要隔离,就有了权限存在的必要性;一切皆文件,意味着权限管理的目标只有文件。

本教程主要针对 Linux 原生的权限管理机制(Discretionary Access Control, DAC),不会涉及 SELinux 的内容,如果你的服务器使用的是 SELinux 权限控制,会非常严格,这显然不在本文的讨论范围内。

用户与组

Linux 对账户和组的管理通过 ID 实现,而不是用户名。用户和组的 ID 分别对应 UID (User ID) 和 GID (Group ID)。一个用户可以属于多个组,但只能属于一个基本组,可以属于多个附加组。用户用于精确授权,组用于批量授权。

基本组和附加组的区别(点击可以展开)

基本组:如果没有指定用户组,创建用户的时候系统会默认同时创建一个和这个用户名同名的组,这个组就是基本组,不可以把用户从基本组中删除。在创建文件时,文件的所属组就是用户的基本组。

附加组:除了基本组之外,用户所在的其他组,都是附加组。用户是可以从附加组中被删除的。

sudo 命令

如果你是普通用户,那你如果要进行系统软件安装或是访问系统文件夹,sudo 会是你最常用的命令。sudo 是 superuser do 的简称,意思就是使用特权用户命令后面的命令,使用方式非常简单:

sudo 的使用
1
sudo command

当你使用管理员权限运行命令时,sudo 会要求你输入你的账号密码。如果你的账号没有使用 sudo 的权限,请使用管理员账号登录并使用 sudo

决定用户是否能使用 sudo(点击可以展开)

通过文件 /etc/sudoers 可以控制用户能否使用 sudo

/etc/sudoers 文件内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#
# This file MUST be edited with the 'visudo' command as root.
#
# Please consider adding local content in /etc/sudoers.d/ instead of
# directly modifying this file.
#
# See the man page for details on how to write a sudoers file.
#
Defaults env_reset
Defaults mail_badpass
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin"
Defaults use_pty

# This allows running arbitrary commands, but so does ALL, and it means
# different sudoers have their choice of editor respected.
#Defaults:%sudo env_keep += "EDITOR"

# Completely harmless preservation of a user preference.
#Defaults:%sudo env_keep += "GREP_COLOR"

# While you shouldn't normally run git as root, you need to with etckeeper
#Defaults:%sudo env_keep += "GIT_AUTHOR_* GIT_COMMITTER_*"

# Per-user preferences; root won't have sensible values for them.
#Defaults:%sudo env_keep += "EMAIL DEBEMAIL DEBFULLNAME"

# "sudo scp" or "sudo rsync" should be able to use your SSH agent.
#Defaults:%sudo env_keep += "SSH_AGENT_PID SSH_AUTH_SOCK"

# Ditto for GPG agent
#Defaults:%sudo env_keep += "GPG_AGENT_INFO"

# Host alias specification

# User alias specification

# Cmnd alias specification

# User privilege specification
root ALL=(ALL:ALL) ALL

# Members of the admin group may gain root privileges
%admin ALL=(ALL) ALL

# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) ALL

# See sudoers(5) for more information on "@include" directives:

@includedir /etc/sudoers.d

文件的注释很详尽,从中可以看出,root 用户可以无限制地使用 sudo,sudo 组下的所有用户也能够使用 sudo。所以,让一个用户使用 sudo 的最好方式,就是将其添加入 sudo 组中。

创建、删除、修改用户或组

本节所有的内容都需要使用超级用户权限才能运行,也就是说,你需要可以使用 sudo 命令才能运行。如果你没有使用 sudo 的权限,也不必担心,你不需要在机器上实际运行这些指令,本教程会详细讲解其效果。

useradd 命令

useradd 可以创建一个账号,具体用法如下:

useradd 使用示例
1
sudo useradd xiao

上述命令可以创建一个名为 xiao 的用户,前面的 sudo 说明 useradd 命令需要使用特权用户运行。

创建完成后,可以查看 /etc/passwd 文件下查看刚刚创建的用户:

查看 passwd 文件信息
1
cat /etc/passwd

在最后一行可以看到刚刚添加的用户,当然如果你觉得终端输出了大量的无用信息,你可以使用前面章节提到的管道运算符查找:

利用管道查看指定用户名的信息
1
cat /etc/passwd | grep xiao

终端的输出为:

账号的信息
1
xiao:x:1001:1001::/home/xiao:/bin/sh

在 Linux 系统文件中,通常不同的字段用 : 分隔,所以你可以看到这个文件里面有 7 个字段,分别是 用户名:密码:UID:GID:描述信息:家目录:登录shell 注意密码字段,里面只存储了一个 x,表示有密码,真正的密码出于安全考虑,存储在 /etc/shadow 中。另外这个账号没有描述信息,所以你看到描述信息对应的字段是空的。

如果你想更改登录 shell,可以直接修改 /etc/passwd 文件,将其改为你想要的 shell,例如 /bin/bash,当然,更推荐你使用 chsh 命令更改。chsh 就是 change shell 的缩写,你可以使用 chsh [-s shell] [username] 修改指定用户的登录 shell。

groupadd 命令

groupadd 可以创建一个组,具体用法如下:

groupadd 使用示例
1
sudo groupadd xx

上述命令可以创建一个名为 xx 的组,前面的 sudo 说明 groupadd 命令需要使用特权用户运行。

创建完成后,可以查看 /etc/group 文件下查看刚刚创建的组:

利用管道查看指定组的信息
1
cat /etc/group | grep xx

终端的输出为:

组的信息
1
xx:x:1002:

可以看出,组的文件有 4 个字段,分别是 组名:组密码:GID:组内用户列表 在这里,组密码是指非本组用户切换到本组时的密码。

id 命令

id 可以查看一个用户的详情,会显示 UID,GID,以及所属的组。

id 命令示例
1
2
3
4
id xiao
# output:
# uid=1000(xiao) gid=1000(xiao)
# groups=1000(xiao),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lxd)

这里 xiao 用户就在很多组里面,由于其在 sudo 组中,所以 xiao 用户可以使用 sudo

passwd 命令

passwd 命令用于修改某个用户的密码

passwd 命令示例
1
2
3
4
5
sudo passwd xiao
# output:
# New password:
# Retype new password:
# passwd: password updated successfully

你需要使用 sudo 权限才能修改密码。注意, Linux 为了安全起见,在输入密码时并不会显示位数,所以你不会看到终端有任何改变,不用担心,大胆输入后回车即可。

usermod 命令

usermod 命令可以修改用户信息,如密码、家目录、组信息等等。这里的 mod 是 modify 的简称。

usermod 示例
1
2
3
4
sudo usermod xiao -c 好耶
cat /etc/passwd | grep xiao
# output:
# xiao:x:1001:1001:好耶:/home/xiao:/bin/sh

其中常用参数如下,如果想获取所有参数,可以使用 usermod --help

usermod 常用参数列表
1
2
3
4
5
6
7
8
9
10
Usage: usermod [options] LOGIN

Options:
-c, --comment COMMENT new value of the GECOS field
-d, --home HOME_DIR new home directory for the user account
-g, --gid GROUP force use GROUP as new primary group
-G, --groups GROUPS new list of supplementary GROUPS
-p, --password PASSWORD use encrypted password for the new password
-s, --shell SHELL new login shell for the user account
-u, --uid UID new UID for the user account

userdel, groupdel 命令

userdel, groupdel 命令分别用于删除用户与删除组。

userdel, groupdel 使用示例
1
2
sudo userdel xiao
sudo groupdel xx

其他相关文件

上面已经介绍了 /etc/passwd/etc/group 两个文件,实际上,/etc/shadow/etc/gshadow 也与 Linux 用户密切相关:

  • /etc/shadow 文件
利用管道查找指定用户的信息
1
sudo cat /etc/shadow | grep xiao

需要注意,这个文件读取就需要超级管理员的权限,所以需要使用 sudo,命令输出如下:

/etc/shadow 文件
1
xiao:Dj/alNi.YlkeDIZ0:19154:0:99999:7:::

总计有 9 个字段,分别是 用户名:加密密码:最后修改时间:最小修改时间间隔:密码有效期:密码需要变更前的警告天数:密码过期后的宽限时间:账号失效时间:保留字段,其中,加密密码使用了 SHA-512 散列算法,难以从散列后的值推算原来的值。因此密码存储是安全的。

  • /etc/gshadow 文件
利用管道查找指定组的信息
1
sudo cat /etc/gshadow | grep xiao

需要注意,这个文件读取就需要超级管理员的权限,所以需要使用 sudo,命令输出如下:

/etc/gshadow 文件
1
xiao:!::

总计有 4 个字段,分别是 组名:组密码:组管理员名:支持的账号名

用户登录时的系统行为

当用户登录系统时,实际上是调用了 login 程序进行验证,首先 login 程序会对用户名进行分析:如果用户名不是 root,且存在 /etc/nologin 文件,login 将输出 nologin 文件的内容,然后退出。通过验证后,会校验用户名及密码,如果校验成功,那么会启动登录 shell。

在启动登录 shell 时,如果登录 shell 是 bash,那么会读取对应家目录下的 .bashrc 并执行。.bashrc 由于是 . 开头的文件,所以在使用 ls 时不会显示,需要使用 ls -a 才会显示。.bashrc 中的 rc 的含义有很多种说法,常见的可以认为是 runcom, run configuration, run control 的缩写。

查看 .bashrc 的内容,你会发现一些有趣的代码:

.bashrc 的有趣内容
1
2
3
4
# some more ls aliases
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'

alias 命令是别名的意思,你可以为一个较长的命令起一个简短的别名,例如,在 bash 中,你输入 ll 就相当于 ls -alF

利用 .bashrc 配置环境变量(点击可以折叠)

环境变量是指 shell 程序运行时能够直接使用的变量,例如:

环境变量示例
1
echo $PATH

其中 PATH 就是一个环境变量,访问时在前面加上美元符号 $ 即可,我们可以这样将环境变量赋值:

赋值环境变量
1
export LD=/home/xiao/lib

如果想在 PATH 变量中追加内容,可以这么写:

在 PATH 中追加内容
1
export PATH=$PATH:/home/xiao/lib

这就相当于把 /home/xiao/lib 追加到 PATH 变量后。但是这么写,有一个巨大的问题,那就是如果关闭后,重新启动一个 shell,那么辛辛苦苦配置的变量就没有了,这时,我们就可以在 .bashrc 文件末尾添加这样的 export 命令,使得环境变量在注销重新登录后依然有效。

那么类似 PATH 这样的环境变量有什么用呢?通常,在不同的 shell 程序中,可能会读取不同的环境变量,但 PATH 变量是一个很特殊的环境变量,它是 shell 查找可执行程序的路径集合。如果你想使用的程序不在 PATH 目录下,那么你就不能直接调用。你可以使用 which 命令查看当前使用的程序的绝对路径,例如:

查找程序的绝对路径
1
2
3
which ls
# output:
# /usr/bin/ls

你会发现,我们常用的 ls 命令,其实在 /usr/bin 目录下,而这个目录,正是在 PATH 环境变量里。如果你运行:

将 PATH 清空
1
export PATH=

那么你再试试能不能使用 ls 命令了,你会发现 shell 提醒你找不到 ls 命令。这就是环境变量的作用。

偏题一下,其实 Windows 也有环境变量(点击可以折叠)

其实 Windows 系统在运行时也有环境变量,并且也有 PATH 变量。在使用命令提示符时,除了命令提示符的内置命令,大多命令也是在 PATH 中寻找,在 Windows 中设置环境变量使用 set, setx 命令,这里不再展开。或者直接打开高级系统设置,环境变量,进行修改。需要注意备份,如果环境变量丢失,有很多程序都不能正常运行!

文件权限

我们随便查看一个文件 ls -lh /etc/passwd

/etc/passwd 的权限
1
-rw-r--r-- 1 root root 1.9K Aug 16 16:30 /etc/passwd

从左到右,依次是:

  • 1 个字符,表示文件类型:- 表示文件,d 表示目录,c 表示字符型文件,l 表示链接文件,这里是 - 表示文件
  • 9 个字符,表示文件权限:分别是文件所有者、文件所有人所属组、其它人的权限,依次为读、写、执行,即 rwx,如果有权限则用字母,如果没有对应的权限,则使用 - 代替,这里是 rw-r--r-- 表示文件所有者 root 有读写权限,同属于 root 组的用户有读权限,其他用户有读权限
  • 1 个数字,表示连接计数,这里是 1
  • 文件所有者,这里是 root
  • 文件所属组,这里是 root
  • 文件大小,这里是 1.9K
  • 修改日期,这里是 8 月 16 日 16 时 30 分
  • 文件名,这里是 /etc/passwd

rwx 权限很好理解,r 是 read,表示读权限, w 是 write,表示写权限, x 是 execute,表示可执行权限。我们可以通过 chmodchown 命令更改文件权限。

chmod 命令

chmod 命令可以修改文件或目录的权限,是 change file mode bits 的简称。

chmod 使用示例
1
sudo chmod +x hello.sh

这就是为 hello.sh 文件添加可执行权限。为了更好地进行权限管理,人们发明了一种计数的方法,实现快速的权限控制,其中 r 读权限等于 4,w 写权限等于 2,x 可执行权限 等于 1,如果需要几种权限,将其加起来即可,这样我们就可以用 3 个数字代表这三种权限了。例如要将 hello.sh 的权限更改为 rwxr-xr-x,只需运行:

chmod 使用示例
1
sudo chmod 755 hello.sh

之前使用的 chmod 600 FILE 其实就是将文件权限改为仅所有者用户可以读写,同组用户或其他用户都不可读写也不能执行。

chown 命令

chown 命令可以修改文件的所有者与所有组,是 change owner 的简称。

chown 使用示例
1
2
3
sudo chown root:root hello.sh   # 将 hello.sh 的所有者及所有组均设为 root
sudo chown -R xiao:xiao ~/a # 将家目录下 a 目录的所有子目录与文件的
# 所有者及所有组设为 xiao

至此,恭喜你完成了第三章的学习!第三章主要带读者了解了 Linux 用户与权限控制的有关内容,同时也简要涉及了环境变量,命令别名等内容,能看到这里,实属不易!目前,你已经学会了 Linux 文件处理,并且大部分的权限问题都能正确处理了。现在,我们已经可以愉快地使用 Linux 系统了。第四章就将介绍 Linux 上软件的安装与卸载,学会后,你就可以扩充自己的 Linux 命令库,使用其他人写好的,便利的程序辅助自己的开发与科研,也可以自己探索 Linux 系统了!

第四章 在 Linux 上安装 / 卸载软件

首先恭喜你看到了这里,后面的内容将会轻松不少,大多就是安装一些软件与一些好的软件的推荐。不再会有大段知识性的内容。

你可能还不清楚 Linux 软件安装的便利之处,我先询问一个问题,如何在 Windows 上安装软件?可能有人会说,有 XX 软件管家,但马上有人反驳,这个 XX 软件管家上面的软件并不是官方来源,里面有可能有捆绑或是广告,所以正确的方法应该是去找软件的官网,然后下载安装包,安装,然后配置,再运行。

实际上,这个流程听上去就非常麻烦。在 Linux 上,你就不会有这些烦恼了,因为几乎每个 Linux 发行版都内置了一个包管理器,你可以使用包管理器,输入一行命令,即可完成软件搜索、安装、卸载等等操作。相信你一定觉得很便利,下面我们就来看看如何使用 Linux 包管理器安装卸载软件。

使用包管理器

在不同的 Linux 发行版上,有不同的包管理器,例如,在 Ubuntu 上,使用 apt 管理;在 Cent OS 上,使用 yum 管理;在 Arch Linux 上,使用 pacman 管理;在 Gentoo 上,使用 emerge 管理,不一而足。这些包管理器作者都或多或少接触过,它们的使用思路其实都是相通的,本教程为了便利起见,就以 apt 包管理器为例,讲解使用方法。

首先,在使用包管理器前,应该先换源,因为一些原因,部分包的下载连接在国内无法访问,所以我们需要把包管理器的软件更新源改为国内源。对于 ubuntu 而言,访问 清华大学开源镜像站丨Ubuntu 镜像使用帮助,上面详细介绍了如何更换软件源。你需要根据 Ubuntu 的版本选择,如果你不清楚你的 Ubuntu 的版本号,可以使用 cat /etc/issue 查看。

更换软件源后,你就可以正常使用包管理器了。

apt 使用示例
1
2
3
4
5
6
7
8
9
sudo apt update       # 更新软件源,这是安装、升级包前必做的命令
sudo apt upgrade # 升级所有可升级的软件包
sudo apt install <package_name> # 安装软件包
sudo apt search <keyword> # 根据关键字查找软件包
sudo apt remove <package_name> # 移除软件包
sudo apt purge <package_name> # 移除软件包和配置文件
sudo apt autoremove # 清理不再使用的依赖和库文件
sudo apt show <package_name> # 显示软件包具体信息
apt list --installed # 列出所有已安装的软件包

apt 的强大之处就在于可以自动处理软件包的依赖,它会帮你安装这个软件所依赖的其他软件,免去你配置环境的苦恼。

下面举几个实际使用的例子,加深读者的理解

apt 升级系统中的所有包
1
sudo apt update && sudo apt upgrade
apt 安装 ranger 软件
1
2
sudo apt update
sudo apt install ranger

你会看到这样的输出:

apt 安装 ranger 的输出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
bzip2 libdeflate0 libgc1 libgif7 libid3tag0 libimlib2 libjbig0
libjpeg-turbo8 libjpeg8 libtiff5 libwebp7 libx11-xcb1
libxcb-shm0 w3m w3m-img
Suggested packages:
bzip2-doc atool caca-utils highlight | python3-pygments mediainfo |
exiftool poppler-utils | mupdf-tools unoconv
cmigemo dict dict-wn dictd libsixel-bin mime-support w3m-el xdg-utils xsel
The following NEW packages will be installed:
bzip2 libdeflate0 libgc1 libgif7 libid3tag0 libimlib2 libjbig0
libjpeg-turbo8 libjpeg8 libtiff5 libwebp7 libx11-xcb1
libxcb-shm0 ranger w3m w3m-img
0 upgraded, 16 newly installed, 0 to remove and 0 not upgraded.
Need to get 2,390 kB of archives.
After this operation, 7,365 kB of additional disk space will be used.
Do you want to continue? [Y/n]

apt 询问你是否继续,大写 Y 说明 Y 是默认选择,也就是说如果你想继续,可以直接回车,或者输入 yY 然后回车都可安装。如果你后悔了,那么输入 n 即可退出安装。

选择继续后,稍事等待,即可安装完成。这时,你可以在终端输入 ranger 使用刚刚安装的软件。ranger 是一个方便的文件管理软件,左右方向键可以切换上下级目录,上下键可以更改目录,这样就可以快速浏览文件了,按 Q 可以退出。

如果想要卸载 ranger 可以使用以下命令:

apt 卸载 ranger
1
2
3
sudo apt remove ranger      # 移除 ranger 软件包
# 或者直接使用下面的命令,完全清除 ranger 包及所有数据
sudo apt purge ranger

这就是 Linux 安装软件的基本步骤了,非常便利。如果你想安装软件,只要使用 apt 即可。那么如果我想安装一个软件,但我不清楚这个软件包的名称怎么办呢?这时可以使用 apt search 搜索。

apt 搜索示例
1
apt search python

你会看到所有含有 python 的软件包,当然这个数量实在是太多了,我们可以使用 grep 进一步查找 python 开头的软件包

apt 搜索结合 grep 命令
1
apt search python | grep ^python

比方说你找到了你想要的 python3.10,那么就可以使用 sudo apt install python3.10 安装了。

编译安装软件

有些情况下,部分软件没有提供二进制包,也就是说,有些软件只提供了源代码,或是只有其他 Linux 发行版格式的软件包。这时,我们可以选择自行编译安装。

还有些情况,你不是系统的管理员(没有 sudo 权限),无法使用包管理器 apt 安装软件,那么你就可以使用编译安装的方法,这样,你就没有必要使用管理员权限安装软件了。

你或许认为这太麻烦,毕竟我自己写的程序还不能编译通过,我还能很容易地编译其他人的程序吗?实际上,在 Linux 下使用源代码形式发行的软件,大多编译步骤非常简单,你只需要在第一次编译前安装好编译环境,后面的操作也就相当便利了。

一般来说,编译过程可以分为两步,第一步是将源码编译为目标文件,第二步是将目标文件链接为可执行程序。其中第二步需要处理错综复杂的依赖关系,好在,Linux 有 make 命令,可以通过 Makefile 文件自动地完成链接功能。大多数软件的源代码都会自带一个 configure 脚本,他可以根据当前系统的环境生成 Makefile 文件,然后就可以愉快地使用 make 完成源代码的编译。

Linux 源码安装步骤基本可以分为 5 步:

  1. 获取源代码并解压
  2. 查看 INSTALL 或 README 文件,开发者会在文件中详细描述如果安装
  3. 使用 configure 命令,生成 Makefile 文件
  4. 编译,执行 make 命令
  5. 安装,执行 make install 将上一步编译好的文件安装到指定的目录或系统中

不同的软件编译安装方法可能并不相同,所以需要仔细阅读 INSTALL 或 README 文件,开发者会详细说明其编译安装的方法,以及编译所需的软件。

下面,我将以编译安装 nginx 为例,进行说明:

编译安装 nginx

  • 安装编译所需的软件

在 Ubuntu 系统中,你可以使用 sudo apt install build-essential 安装基本的编译工具链。

安装编译工具链
1
2
3
sudo apt install build-essential
sudo apt install wget curl git
sudo apt install libpcre3 libpcre3-dev libssl-dev zlib1g zlib1g-dev
  • 下载源代码并解压

在这里,我们使用 wget 命令下载源代码,如果源代码是用 git 存储库形式存储,你可以使用 git clone 命令克隆下来。

下载源代码
1
wget http://nginx.org/download/nginx-1.21.4.tar.gz

wget 命令其实就是将文件下载到当前目录下,与浏览器提供的下载功能是一样的。

解压源代码
1
tar -zxvf nginx-1.21.4.tar.gz
  • 阅读安装说明

源代码解压完成后,我们进入源代码的目录,查看安装的说明

查看安装说明
1
2
3
4
cd nginx-1.21.4
cat README
# output:
# Documentation is available at http://nginx.org

软件告诉你查看其官网,在官网下,可以看到右侧有 Building nginx from Sources 一项,点击即可查看 相关说明

  • 生成 Makefile 文件

阅读说明后,我们可以生成 Makefile 文件了

生成 Makefile 文件
1
2
3
4
5
6
7
8
./configure --prefix=/usr/local/nginx \
--with-http_ssl_module \
--with-http_stub_status_module \
--with-file-aio \
--with-http_v2_module \
--with-http_realip_module \
--user=nginx \
--group=nginx

这里为了说明 configure 的作用,我们使用了很多个选项,这些选项的详细说明在上面的网页中可以查看,其中 --prefix 是指软件编译完后,安装的位置,这里我们设置成了 /usr/local/nginx,这个目录通常就是 Linux 建议的用户编译软件的安装目录。

当你执行后,你会看到 configure 程序正在检查你的系统环境以及编译器的信息,如果报错 Error 的话,可以查看缺少的库,并使用软件包安装即可。在执行完毕后,你可以看到一些摘要。

configure 完成后的摘要
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Configuration summary
+ using system PCRE library
+ using system OpenSSL library
+ using system zlib library

nginx path prefix: "/usr/local/nginx"
nginx binary file: "/usr/local/nginx/sbin/nginx"
nginx modules path: "/usr/local/nginx/modules"
nginx configuration prefix: "/usr/local/nginx/conf"
nginx configuration file: "/usr/local/nginx/conf/nginx.conf"
nginx pid file: "/usr/local/nginx/logs/nginx.pid"
nginx error log file: "/usr/local/nginx/logs/error.log"
nginx http access log file: "/usr/local/nginx/logs/access.log"
nginx http client request body temporary files: "client_body_temp"
nginx http proxy temporary files: "proxy_temp"
nginx http fastcgi temporary files: "fastcgi_temp"
nginx http uwsgi temporary files: "uwsgi_temp"
nginx http scgi temporary files: "scgi_temp"
  • 开始编译

在生成 Makefile 后,就可以使用 make 命令编译程序了。

使用 make 编译
1
make

如果你想多线程编译程序(默认是单核),那么你可以使用 -j 选项

使用多线程编译
1
make -j 8

这里的数字 8 是指编译的线程数,如果你是 8 核的电脑,那就使用 8,请注意编译的线程数不要超过核心数,否则会影响编译效率,如果你还想在编译期间使用服务器,也不要占满核心数,否则服务器会非常卡顿。

如果没有报错,那么你会看到

make 编译完成
1
make[1]: Leaving directory '/home/xiao/nginx-1.21.4'

如果不幸报错了,那么你可以自行搜索错误的信息,并进行相关配置,然后清除之前编译的内容,再重新编译

清除上次编译的残留后重新编译
1
make clean && make
  • 安装程序

编译完成后,你就可以使用 make install 安装。需要注意的是,之前我的安装目录设置为 /usr/local/nginx,这个目录需要管理员才能创建,所以安装时要使用 sudo

安装程序
1
sudo make install

然后你就可以正常使用 nginx 程序了,nginx 是异步框架的网页服务器,也可以用作反向代理、负载平衡器和HTTP缓存。在此处不介绍其使用。

至此,恭喜你完成了第四章的学习!第四章主要带读者了解了 Linux 上安装卸载软件的方式,相较于 Windows 系统,这种安装方式显得简单了许多,你会花更少的时间在环境的配置上,无形中提高了开发的效率。至此,读者已经掌握了 Linux 的基本内容,对于初学者而言,这些知识已经足够使用。第五章主要是介绍 Linux 的其他常用命令以及推荐一些 Linux 上很好用的软件。

第五章 Linux 常用命令及软件

恭喜你能看到这里,现在,你已经能够在 Linux 上完成几乎所有的文件操作,权限操作,也学会了安装、卸载软件,那么接下来,作者要再补充介绍几个 Linux 的常用命令,并且推荐一些 Linux 上好用的软件,让我们继续吧。

网络文件下载

在 Linux 命令行中,我们也会有下载一些网络上的文件的需求,通常,我们使用 wgetcurl 命令下载网络上的文件。wget 在第四章 编译安装软件时已经有所涉及,使用非常简单,wget URL 就可以下载文件了。

wget 使用
1
2
3
wget [option]... [URL]...
# e.g.
wget http://nginx.org/download/nginx-1.21.4.tar.gz

curl 命令会默认将下载的内容输出到终端,如果你需要保存到文件,需要使用 --output 选项。

curl 输出到终端
1
curl www.baidu.com

你会看到百度的网页源码,如果你想使用 curl 下载文件,可以这么写:

curl 下载文件
1
curl http://nginx.org/download/nginx-1.21.4.tar.gz --output nginx-1.21.4.tar.gz

文件上传与下载

如果你想将自己电脑上的文件上传到服务器上,或是将服务器上的文件下载到电脑上,那么可以使用 sftp (SSH File Transfer Protocol, also Secure File Transfer Protocol) 协议完成,由于这个使用代码不太优雅。所以这里推荐使用软件完成文件的上传下载。

如果你使用的终端程序自带了文件传输功能,那么当然可以使用终端自带的文件传输,如果没有,这里推荐使用 Filezilla。其安装使用非常简单。

Filezilla 软件截图
Filezilla 软件截图

软件左侧是本地的文件,右侧是服务器的文件,如果要下载,可以直接使用右键单击服务器的文件或文件夹,点击下载即可,如果要上传,也只需要右击本地的文件或文件夹,点击上传即可。

系统性能监控

有时,我们需要监控系统的运行情况,例如 CPU、内存等的使用,这时,可以使用内置的命令 top 查看。

输入 top 命令后,就能看到 CPU、内存的占用,也能看到正在运行的进程,但是其界面比较丑陋,所以我们通常使用其他程序代替 top

例如,我们可以使用 htop 查看系统资源占用。htop 需要额外安装,运行 sudo apt install htop 即可。

htop 界面
htop 界面

htop 界面默认上部是 CPU、内存、交换空间的信息,还有电脑负载以及开启时长。下面是进程的信息。

如果你还想再极客一点,也可以使用 btopbtop 也需要额外安装,运行 sudo apt install btop 即可。

btop 界面
btop 界面

很酷,不是吗?

如果你想要查看网络的使用情况,你当然可以查看 btop,当然,你也可以使用 bmon 软件,运行 sudo apt install bmon 即可。

bmon 界面
bmon 界面

如果你想查看服务器的端口占用情况,可以使用 netstat 命令,使用 sudo apt install net-tools 安装即可。

查看服务器端口占用
1
netstat -ntlp
netstat 简要输出
1
2
3
4
5
6
7
8
9
10
11
12
Active Internet connections (only servers)
Proto Local Address State PID/Program name
tcp 0.0.0.0:22 LISTEN 889/sshd
tcp 127.0.0.1:8888 LISTEN 1159/python3
tcp 127.0.0.1:25 LISTEN 1171/master
tcp 0.0.0.0:443 LISTEN 923/nginx: master p
tcp 127.0.0.1:8360 LISTEN 1363/docker-proxy
tcp 0.0.0.0:80 LISTEN 923/nginx: master p
tcp6 :::22 LISTEN 889/sshd
tcp6 ::1:25 LISTEN 1171/master
tcp6 :::8000 LISTEN 890/frps
tcp6 :::30000 LISTEN 893/v2ray

你会看到服务器上所有监听的端口。

文件浏览

如果你想快速地在服务器上浏览文件,那么我推荐你使用 ranger 程序。直接使用 sudo apt install ranger 安装即可。

ranger 截图
ranger 截图

如果你想尝试更复杂的文件管理器,你可以使用 mc 程序,直接使用 sudo apt install mc 安装即可。

mc 截图
mc 截图

进程管理

有时,我们需要有一个类似 Windows 任务管理器一样的软件,查看 Linux 的进程,或是强行停止一些进程。在 Linux 下,你可以使用 ps 命令查看当前的进程。ps 是 process snapshot 的缩写。

ps 使用示例
1
2
ps       # 查看当前用户进程
ps aux # 查看所有进程

你会发现,ps aux 的输出太长了,所以我们可以使用 grep 查找里面的进程。

ps 查找进程
1
ps aux | grep python

终端会输出所有的 python 进程。仔细观察输出,其有 11 个字段,依次是:

  • USER 是进程运行的用户
  • PID 是进程的 ID
  • %CPU 是进程的 CPU 占用情况
  • %MEM 是进程的内存占用情况
  • VSZ 是 虚拟内存的使用情况
  • RSS 是驻留集的大小,是非交换物理内存的使用
  • TTY 是进程是依存于什么终端
  • STAT 是进程的状态
  • START 是进程启动的时间或日期
  • TIME 是进程的累计 CPU 时间
  • COMMAND 是进程的命令与参数

有了进程的 PID,就可以唯一确定一个进程,我们就可以对进程进行一些操作了。你可以使用 kill 命令杀死进程,命令形式如下:

停止一个进程
1
kill -9 PID

例如,我在运行 ps aux | grep python 后,发现我这个 python 进程的 PID 是 10756,那么我就可以使用 kill -9 10756 杀死这个 python 进程。

由于 Linux 默认进程是依存于一个终端的,所以如果你关闭这个终端,那么进程也会停止。比如我正在用服务器计算一个东西,但是很不幸,网络断开了,这时,这个进程由于终端的关闭就会被杀死。这显然是我们不想看到的。那应该如果操作呢?我们可以使用 nohup & 命令将命令转为后台运行。

nohup 使用
1
nohup command &

由于不会在终端上输出,所以 nohup 会默认将标准输出写入到 nohup.log 文件中,如果你想重定向输出,可以使用重定向运算符。

nohup 重定向
1
nohup command > log.txt 2>&1 &

这样就能将标准输出与标准错误都写入到 log.txt 中。举个例子:

nohup 案例
1
nohup python3 calculating.py > log.txt 2>&1 &

这样就能将 python3 caculating.py 转到后台运行,也不用担心断网了。

终端复用

当然,你可能会觉得上面使用 nohup 太过麻烦,我总不能每次运行命令时都要用 nohup 包裹起来吧,而且网络是不稳定的,指不定什么时候就会掉线。在这种情况下,你可以使用终端复用工具。它的基本原理就是创建一个不依赖终端的虚拟终端进程,在你的终端关闭后,这个虚拟进程依然可以继续运行,常用的主要是 screen 工具,但是其比较古老,本教程建议使用的是 tmux

你可以使用 sudo apt install tmux 安装这个工具。

然后你直接输入 tmux,就能打开一个新的终端,在里面运行的命令,在关闭终端后,仍然会运行。

tmux 小教程(点击可以折叠)

tmux 其实是一个非常好用的小工具,为其单独写一篇教程也不为过。在这里,我们就精简一下,只介绍 tmux 最实用的功能。

你可以使用 tmux 创建一个 tmux 终端。然后使用快捷键将终端分离。

注意,tmux 在未做其他配置时,默认的快捷键是由前导键和快捷键组成,你需要先按 CTRL + B 后,才能输入快捷键。

例如分离终端快捷键是 D,你需要先按 CTRL + B 后,再按 D 键。

终端分离后,你就会退回到你的终端,这时你的终端并没有被杀死,你可以用 tmux ls 命令查看所有正在运行的终端,最前面的一个数字表示终端的编号,此后你可以使用 tmux attach-session -t ID 来重新连接到这个终端。如果你想杀死这个终端,可以使用 tmux kill-session -t ID 命令。

使用 tmux 可以将一个终端变为好几个终端,你可以使用快捷键来分屏。

左右分屏:先 CTRL + B%
上下分屏:先 CTRL + B"
切换目前激活的部分:先 CTRL + B 后使用方向键

了解以上内容后,就可以正常使用 tmux 了,当然,如果你对 tmux 很感兴趣,也欢迎你查看作者的另一篇文章 我的 Linux 深度学习工作环境丨环境搭建教程 的终端配置,里面介绍了 tmux 的美化过程。

我的 tmux 截图
我的 tmux 截图

编程软件

相信你使用 Linux 系统大概率是为了编程,所以当然少不了编译器等等编程软件。在 Linux 上,你可以很方便的安装这些编译器:

C 语言编译器:gcc, clang
Python 环境:python, miniconda

如果你对深度学习感兴趣,相信你也要配置 NVIDIA 显卡,这一部分通常都是系统管理员的工作,本教程不再涉及,如果你感兴趣,可以参考作者的另一篇文章 我的 Linux 深度学习工作环境丨环境搭建教程 的深度学习环境搭建。

这里简要介绍一个代码版本控制工具 git

git

git 是代码控制的工具,使用 sudo apt install git 以安装它。当然,git 的高级使用也是较为复杂的,如果你只是单纯用来线性的控制版本,那么你只需要了解下面的命令即可,如果你对 git 很感兴趣,推荐你阅读 廖雪峰的 Git 教程,通俗易懂。

安装完成后,你需要进行 git 的基本配置,也就是填写自己的昵称与邮箱:

git 配置
1
2
git config --global user.name "Your Name"
git config --global user.email "[email protected]"

需要注意,如果你想使用 github 等等代码仓库,这个邮箱请保证与注册 github 的邮箱相同。

目的 命令 简述
建立 git 库 git init
将更改添加到暂存区 git add FIELNAME
git add –all
提交 git commit –m “MESSAGE” 提交目前所有已添加到暂存区的更改
查看更改日志 git log 可以查看每次更改记录对应的作者、日期、备注和哈希码
git reflog 可以查看所有记录(包括回退之前)
转到某个版本 git reset –hard 哈希码 输入哈希码前几位,可以与其他记录区分即可

只建议使用 git 工具管理文本类型的文件,因为文本类型的文件更改比较独立。

Visual Studio Code

当然你可能会觉得,在终端里编程并不优雅,虽然 vim 提供了代码补全以及很多插件支持,但对于初学者而言毕竟太不友好。这时,你可以使用划时代的文本编辑器,微软的 Visual Studio Code 利用 ssh 连接到服务器上,进行文件编辑,享受与本机编程同样的体验,如果你对这种编程方式很感兴趣,可以阅读作者的另一篇文章 我的 Linux 深度学习工作环境丨环境搭建教程,里面详细介绍了 VS Code 软件的配置并且推荐了许多高效的插件。

总结

首先恭喜各位读者看到这里,你已经学完了这篇很长的教程,现在你可以无障碍地使用 Linux 命令行(CLI)了。

当然,有些读者并不会止步于此,还想了解更多 Linux 方面的内容,或是对 shell 编程很感兴趣,作者也提供一些链接以便深入学习:

Changelog

这里记录了本页面所有的显著更改。
All notable changes to this page will be documented in here.

2022-08-10

  1. 修改第五章 Linux 常用软件为 Linux 常用命令及软件;
  2. 在第二章中增加链接章节 ln
  3. 删除了教程中的 docker 部分,因为对初学者并不友好。

2022-08-04

完成第五章 Linux 常用软件。

2022-07-28

完成第四章 在 Linux 上安装 / 卸载软件。

2022-07-25

完成第三章 Linux 用户与权限控制。

2022-07-21

完成第二章 了解 Linux 文件操作。

2022-07-14

完成第一章 连接到 Linux 终端。

2022-07-10

完成第〇章 什么是 Linux 命令。

2022-07-04

完成教程大纲编写。

评论