作者 | 梁唐
出品 | 公众号:Coder梁(ID:Coder_LT)
大家好,日拱一卒,我是梁唐。
不知道大家有没有这样一种体验,在实际写代码或者是工作、做项目的过程当中经常被一些简单的问题难住。比如vim的一些命令不熟悉,或者是git的一些操作不知道怎么弄,命令行除了ls cd
之外一无所知。总觉得书到用时方恨少。
别说是还没毕业的学生了,即使是一些毕业多年的程序员老鸟也难免会查查谷歌或者Stack Overflow。我每次遇到这样问题的时候总会忍不住想, 要是上学的时候学校里能专门开一门课程讲一讲这些基本工具的使用,给学生做一个深度的科普,该有多好。
也许是听到了众多程序员的心声,2020年的时候,MIT开设了一门公开课。它的标题很有意思,叫做《missing smester》,消失的学期。课程当中收录的正是这些大部分学校课程当中不会专门涉及,但是又至关重要的基础知识。
课程量不算大,算上最后的答疑部分,一共也只有十一节课。但这十一节课当中包含了命令行、git、vim等许多非常重要的知识和技能,非常非常值得一看。
虽然课程里讲的内容非常基础,但温故知新,我也收获了非常多。因此强烈推荐给大家。
这门课在B站上也有搬运,链接:https://www.bilibili.com/video/BV1x7411H7wa?spm_id_from=333.337.search-card.all.click
这门课的notes写得非常好,这个系列是这门课notes的一个翻译和整理。
动机
作为计算机科学家,我们知道计算机非常擅长处理高重复性的任务。
然而我们尝尝忽略,我们使用计算机的过程其实和计算机处理程序时类似,也一样充满了重复。我们在处理计算机相关的问题上拥有大量的工具可以使用,只需要动动手指输入命令或程序,就可以完成一些高度复杂的任务。
然而,我们当中的很多人,只使用了这些工具的很小一部分。有时候仅仅是死记硬背了一些命令,或者是在遇到困难的时候,盲目地从网上复制粘贴命令。
这门课视图解决这个问题,我们希望教会你如何最大限度地使用这些工具,给你展示一些新的工具丰富你的技能树,给你更多的鼓舞和兴趣,让你勇敢地探索。这就是我们对计算机科学领域中消失的学期的定义。
课程结构
这门课包含了11个长度约1小时的课程,每一节课都有一个特定的主题。
每节课之间都是高度独立的,但在课程进行的过程当中,我们还是会假设你已经学会了之前的内容。我们会把课程的笔记公开在网上,但也有很多课上的内容是笔记里没有的。上课的视频也同样会放在网上。
我们尝试着在11小时的课程当中尽可能多地包含基础知识,所以课程的内容会比较密集。为了保证你们能顺利地跟上节奏,每节课后都会有针对要点的一系列练习。
由于时间的限制,所以没办法对所有的工具都进行深入的探讨。可能的话,我们会试着提供继续钻研和学习的资源。
Topic 1: The Shell
什么是 shell?
现代的计算机拥有大量的方式和用户进行交互,美观的用户界面、声音甚至是AR或者是VR都已经逐渐普及。
对于80%的用户来说,这已经足够了,但这也意味着很多基本功能的限制。因为你没办法进行图形界面中没有的操作,也没办法声控一个没有开发的功能。为了充分应用计算机的功能,解除图形界面的限制,我们需要回到上古时期,使用文本界面来控制计算机,这个就是shell。
几乎所有的平台都有shell,只不过它们的形式可能不同。尽管细节上有所区别,但核心都是一样的:允许你运行程序,输入指令,显示结果。
在这节课当中,我们将聚焦在Bourne Again Shell上,简称bash
。这也是使用最广泛的shell,它的语法和其他的shell也非常接近。为了打开shell界面,你需要一个terminal(终端)。一般来说,计算机当中都会自带,你也可以自己安装一个。
使用shell
当你打开terminal,你会看到一个光标,大概长这样:
这个是shell的主要文本界面,它告诉你,你当前的工作路径是机器上missing
,并且你当前所在的地方是~
,这是home
的简称。
$
符号说明你不是一个超级用户(root user),我们将会详细解释root user。你可以在光标处输入指令,它会被shell解读并运行。最基础的命令是运行一个程序:
现在我们运行了date
程序,它会打印当前的日期和时间。之后shell会继续让我们输入指令,我们可以输入一个带参数的指令:
在这个例子当中,我们告诉shell运行一个叫做echo
的程序,参数是hello
。
echo
程序会把参数进行输出,shell会按照空格对命令进行拆分。以第一个单词作为程序名进行运行,将剩余的单词作为参数。如果你想要传递一个带有空格或者其他特殊字符的参数,需要使用引号(如"My Photos")或者是取义符(My Photos)。
但shell是怎么知道去哪里寻找date
和echo
程序的呢?
其实shell只是一个编程环境,就像是Python和Ruby一样,所以它也有变量、条件、循环和函数。当你在shell中运行命令的时候,你其实是编写了一个简易的代码交给了shell来解释运行。
当shell被要求运行一个不是shell中的关键字的命令时,它会去环境变量PATH中进行查找。PATH中包含了一系列文件夹路径以:分隔,shell会在这些路径当中找到名称匹配的程序进行运行。
当我们运行echo
命令时,shell发现它不在shell的关键字中之后,会先在$PATH
路径当中进行查找。
当找到之后,就会进行运行(假设有权限运行,权限这部分之后讲解)。我们可以使用命令which
找到我们运行的程序所在的路径。我们也可以自己给定我们要运行的程序的路径来绕过path机制。
shell中的指引
shell中的path是一系列文件夹组成的list,在Linux和macOS当中以/
分隔,在Windows当中以分隔。
在Linux和macOS当中,/
路径表示系统的根目录,是所有文件和路径的根节点。而Windows当中磁盘的根目录会有多个分区,比如C:
。我们会假设你在这门课程中使用的是Linux文件系统。
以/
开头的路径被称为绝对路径,其他的路径都是相对路径。相对路径是相对于当前路径而言的路径,我们可以通过命令pwd
来查看当前路径,通过cd
命令来修改当前路径。.
代表当前路径,..
代表当前路径的父路径。
注意,图中的shell提示了我们当前所在的路径,这是可以配置的。你可以修改你的终端的配置,显示所有你需要的信息,这也会在之后的课程当中提及。
总的来说,当我们运行一个程序时,除非指定,它会在当前目录运行。
查看当前路径中的内容,可以使用ls
命令:
除非我们在第一个参数中输入一个路径,否则它会列出当前路径下的内容。
大多数命令都会有flags和options,通过-
接收参数来指定行为。通常运行程序时加上-h
或--help
flag可以得到一些帮助信息告诉我们每个flag和options如何使用。
比如ls --help
告诉我们:
加上参数-l
之后会得到关于文件的更多的信息。我们看一下输出结果:
开头的d
表示missing
是一个文件夹,然后紧跟着一系列字符(rwx),这些表明了这个文件/文件夹的权限。权限一共有9个字母,分成三组。
第一组rwx
表示表示文件owner的权限,r
表示可读,w
表示可写,x
表示可运行。
第二组r-x
表示所属群组(users)的权限,每个字母表示的含义和owner相同,-
表示没有这一项权限。比如r-x
表示可读可运行,但不可写。
第三组r-x
表示其它用户的权限。所以只有owner拥有修改missing
文件夹的权限,包括添加、删除文件夹内的文件的权限。
要进入一个路径,用户必须拥有这个文件夹以及它所有父路径的search(运行)权限,要列出文件夹中的内容,用户需要有文件夹的读权限。
需要注意/bin
路径下几乎所有文件对其它用户都只有运行权限,这样保证了所有的用户都可以运行这些程序。
其他一些很有用的命令还有mv
(重命名、移动文件),cp
(拷贝文件),mkdir
(创建文件夹)。
如果你想要知道一个程序参数、输入、输出的更多信息,你可以使用man
程序。它接收另外一个程序名作为参数,然后展示它的使用菜单,输入q进行退出。
Connecting programs
在shell当中,程序拥有两个流,即输入流和输出流。当程序试着读入数据时,它是从输入流获取的。当它试着输出时,也是向输出流进行传输。
一般来说,程序的输入和输出设备都是你的终端,也就是以我们的键盘作为输入,以屏幕作为输出。然而,我们可以修改这些流。
最简单的方式就是重定向流,比如< file
和> file
,表示我们以一个文件作为输入,或者是以一个文件作为输出:
像是上面例子所演示的,cat
程序可以输出文件中的内容。当我们给定一个文件作为参数,它会输出文件中的内容到它的输出流上。当cat
没有任何参数的时候,它会将输入流中的内容输出到输出流中(上面第三个样例)。
你也可以使用>>
代替>
,它们的区别是>>
不会替换文件中的内容,而是添加在文件末尾。这些特性结合管道一起使用的时候会非常有用,|
命令可以让我们在程序之间构建管道。让一个程序的输出作为另外一个的输入:
在本节课中,不会太过深入管道的细节,以及它的优势,这部分放在之后的课程中。
多功能且强大的工具
在大多数类Unix系统当中,有一种用户是特殊的,它就是root。
root用户超越了所有权限的限制,它可以创建、读入、更新、删除系统中的任何文件。然而,你不能一直使用root,因为这会非常危险,可能破坏你的系统或者是导致不可逆伤害。
你可以使用sudo
命令代替,就像是它的名称暗示的一样,它允许你像root一样执行某些操作。有时候你会获得permission denied错误,这表示你没有权限。你可以使用sudo
来强行执行,不过在执行之前,一定要确保你的命令是正确的。
有一件你必须要是root才可以做的事情:修改系统文件。
系统文件通常挂载在/sys
路径下,当中将一些内核参数以文件的形式存储。所以你可以很轻易地修改一些内核参数。需要注意的是,/sys
文件在windows和macOS中没有。
比如,你可以通过修改一个名叫brightness
的文件来调整你笔记本屏幕的亮度:
通过往文件中写入一个特定的值,你可以修改屏幕的亮度。
你的整个执行过程可能是这样的(你可能需要先通过find
命令找到对应的文件):
$ sudo find -L /sys/class/backlight -maxdepth 2 -name '*brightness*'
/sys/class/backlight/thinkpad_screen/brightness
$ cd /sys/class/backlight/thinkpad_screen
$ sudo echo 3 > brightness
An error occurred while redirecting file 'brightness'
open: Permission denied
出乎我们意料的是,虽然我们使用了sudo
命令,但仍然报错了。
这是shell中一个我们需要了解非常重要的信息,像是|
这样的管道命令,或者是>
, <
分隔的命令,并不是一个单独的程序。echo
并不知道|
命令的存在,它仅仅是读入和输出。
在上面的例子中,shell在echo 3
时以root执行,而打开brightness
文件时没有,仍然是普通用户。所以被拒绝了,如果我们想要以root执行写入,我们可以这样改写命令:
$ echo 3 | sudo tee brightness
tee
程序可以同时写入/sys
文件,并且以root身份运行,所以不会受到权限限制。
你可以控制/sys
下的一些文件来娱乐或实现一些功能。比如说开启一些LED指示灯,下列代码会开启scrolllock指示灯。
$ echo 1 | sudo tee /sys/class/leds/input6::scrolllock/brightness
Next steps
现在你已经了解了shell的一些基本应用,可以来完成一些基础功能了。
你应该可以跳转到任何你感兴趣的路径下,并且能够使用基础命令的绝大多数功能了。在下节课当中,我们将会接触到更多有趣的命令,并且使用shell来实现更加复杂的一些任务。
Exercises
这门课每节课后都会附带一些练习,有一些是给定了指定的任务去完成,也有一些是开放式的任务,比如说尝试使用X或Y程序。我们强烈推荐你能亲自尝试。
- 这门课我们需要使用Unix shell,比如Bash或者Zsh。如果你使用Linux或者是macOS,那你并不需要为此烦恼。如果你使用的是Windows,你需要确保你运行的不是cmd.exe或者PowerShell。你可以使用
Windows Subsystem for Linux
或者使用Linux虚拟机来使用Unix风格的命令行。为了确保你使用了正确的shell,你可以尝试运行命令echo $SHELL
,如果显示的结果是/bin/bash
或者/usr/bin/zsh
,那么久说明你处在了正确的环境 - 在
/tmp
路径下创建missing
文件夹 - 使用
man
程序来调研touch
程序 - 使用
touch
在missing
下创建semester
文件 - 在文件当中写入以下两行,一次写入一行:
#!/bin/sh
curl --head --silent https://missing.csail.mit.edu
第一行是Bash中的注释,Bash中以#
开启注释。!
即使在双引号当中也有特殊含义。在Bash当中,单引号和双引号是有区别的,你可以调研一下它们的区别
- 尝试运行这个文件,你可以使用
./semester
来运行。使用ls
命令来探究不能运行的原因 - 使用
sh
命令,将semester
作为参数传入运行程序,如sh semester
,为什么这样可以运行,为什么./semester
不行? - 调研
chmod
程序,使用man chmod
- 使用
chmod
来让./semester
可行。你的shell怎么会知道这个文件应该用sh
运行呢?了解一下shebang
获得更多信息 - 使用
|
和>
将semester
输出结果中 "last modified" 日期写入到你home下的last-modified.txt
中 - 编写命令读取
/sys
中你笔记本电源的电量或者笔记本CPU的温度,如果你是macOS用户,你的操作系统可能没有/sys
文件,你可以跳过本题
答案
前六题的命令为:
代码语言:javascript复制cd /tmp
mkdir missing
touch semester
echo '#!/bin/sh' > semester
echo 'curl --head --silent https://missing.csail.mit.edu' >> semester
./semester
img
直接运行会报错,因为没有运行权限。
img
使用命令给semester
添加运行权限:
chmod x semester
shell能知道这个文件使用什么程序执行是因为我们在第一行加上了特殊的注释:#!/bin/sh
,这是指定了该文件执行的程序。
最后,将筛选数据写入文件:
代码语言:javascript复制./semester | grep 'last-modified' > ~/last-modified.txt
喜欢本文的话不要忘记三连~