mit 6.NULL简单记录
相关网站:
MIT6.NULL实用工具介绍
计算机教育中缺失的一课
只是花点时间简单看一下,这博客只是当简单的笔记,没啥阅读价值,建议直接看计算机教育中缺失的一课网站原文
课程概览与 shell
在程序间创建连接
在 shell 中,程序有两个主要的“流”:它们的输入流和输出流。 当程序尝试读取信息时,它们会从输入流中进行读取,当程序打印信息时,它们会将信息输出到输出流中。 通常,一个程序的输入输出流都是您的终端。也就是,您的键盘作为输入,显示器作为输出。 但是,我们也可以重定向这些流!
最简单的重定向是 < file 和 > file。这两个命令可以将程序的输入输出流分别重定向到文件:
1 |
|
cd - 返回进入此目录之前所在目录
find用法:Linux find 命令
1 |
|
grep用法:Linux grep 命令
grep 指令用于查找内容包含指定的范本样式的文件,如果发现某文件的内容符合所指定的范本样式,预设 grep 指令会把含有范本样式的那一列显示出来。
1 |
|
Shell 工具和脚本
shebang:
在计算领域中,Shebang(也称为 Hashbang )是一个由井号和叹号构成的字符序列 #! ,其出现在文本文件的第一行的前两个字符。 在文件中存在 Shebang 的情况下,类 Unix 操作系统的程序加载器会分析 Shebang 后的内容,将这些内容作为解释器指令,并调用该指令,并将载有 Shebang 的文件路径作为该解释器的参数。
例如,以指令#!/bin/sh开头的文件在执行时会实际调用/bin/sh程序(通常是 Bourne shell 或兼容的 shell,例如 bash、dash 等)来执行。这行内容也是 shell 脚本的标准起始行。
由于 # 符号在许多脚本语言中都是注释标识符,Shebang 的内容会被这些脚本解释器自动忽略。 在 # 字符不是注释标识符的语言中,例如 Scheme,解释器也可能忽略以 #! 开头的首行内容,以提供与 Shebang 的兼容性。
1 |
|
查看命令如何使用
最常用的方法是为对应的命令行添加-h 或 –help 标记。另外一个更详细的方法则是使用man 命令。man 命令是手册(manual)的缩写,它提供了命令的用户手册。
有时候手册内容太过详实,让我们难以在其中查找哪些最常用的标记和语法。 TLDR pages 是一个很不错的替代品,它提供了一些案例,可以帮助您快速找到正确的选项。
查找 shell 命令
history 命令允许您以程序员的方式来访问shell中输入的历史命令。这个命令会在标准输出中打印shell中的里面命令。如果我们要搜索历史记录,则可以利用管道将输出结果传递给 grep 进行模式搜索。 history | grep find 会打印包含find子串的命令。
函数 marco 和 polo
我喜欢用fish而不是bash,故我使用fish的格式编写函数
Fish Shell 精简手册
Fish for bash users
source命令是一个内置的shell命令,用于从当前shell会话中的文件读取和执行命令。source命令通常用于保留、更改当前shell中的环境变量。简而言之,source一个脚本,将会在当前shell中运行execute命令。
1 |
|
1 |
|
1 |
|
1 |
|
编辑器 (Vim)
了解基本用法即可,我用vscode
:q 退出(关闭窗口)
:w 保存(写)
:wq 保存然后退出
数据整理
太复杂了,应该用不到,看点简单的就成
sed命令进行正则匹配替换
1 |
|
awk用于处理文本
1 |
|
命令行环境
SIGSTOP 会让进程暂停。在终端中,键入 Ctrl-Z 会让 shell 发送 SIGTSTP 信号
ssh 会查询 .ssh/authorized_keys 来确认那些用户可以被允许登录。您可以通过下面的命令将一个公钥拷贝到这里:
1 |
|
常见的情景是使用本地端口转发,即远端设备上的服务监听一个端口,而您希望在本地设备上的一个端口建立连接并转发到远程端口上。例如,我们在远端服务器上运行 Jupyter notebook 并监听 8888 端口。 然后,建立从本地端口 9999 的转发,使用 ssh -L 9999:localhost:8888 foobar@remote_server 。这样只需要访问本地的 localhost:9999 即可。
版本控制(Git)
Git 将顶级目录中的文件和文件夹作为集合,并通过一系列快照来管理其历史记录。在 Git 中,历史记录是一个由快照组成的有向无环图。
Git 数据模型
1 |
|
1 |
|
Learn Git Branching 通过基于浏览器的游戏来学习 Git ;
调试及性能分析
“最有效的 debug 工具就是细致的分析,配合恰当位置的打印语句” — Brian Kernighan, Unix 新手入门。
对于 UNIX 系统来说,程序的日志通常存放在 /var/log。
过早的优化是万恶之源
像 C 或者 C++ 这样的语言,内存泄漏会导致您的程序在使用完内存后不去释放它。为了应对内存类的 Bug,我们可以使用类似 Valgrind 这样的工具来检查内存泄漏问题。
1 |
|
元编程
Makefile中的指令,即如何使用右侧文件构建左侧文件的规则。或者,换句话说,冒号左侧的是构建目标,冒号右侧的是构建它所需的依赖。缩进的部分是从依赖构建目标时需要用到的一段程序。
语义版本号
- 如果新的版本没有改变 API,请将补丁号递增;
- 如果您添加了 API 并且该改动是向后兼容的,请将次版本号递增;
- 如果您修改了 API 但是它并不向后兼容,请将主版本号递增。
持续集成,或者叫做 CI 是一种雨伞术语(umbrella term,涵盖了一组术语的术语),它指的是那些“当您的代码变动时,自动运行的东西”
测试简介
多数的大型软件都有“测试套件”。您可能已经对测试的相关概念有所了解,但是我们觉得有些测试方法和测试术语还是应该再次提醒一下:
测试套件:所有测试的统称。
- 单元测试:一种“微型测试”,用于对某个封装的特性进行测试。
- 集成测试:一种“宏观测试”,针对系统的某一大部分进行,测试其不同的特性或组件是否能协同工作。
- 回归测试:一种实现特定模式的测试,用于保证之前引起问题的 bug 不会再次出现。
- 模拟(Mocking): 使用一个假的实现来替换函数、模块或类型,屏蔽那些和测试不相关的内容。例如,您可能会“模拟网络连接” 或 “模拟硬盘”。
安全和密码学
熵
熵的单位是 比特。对于一个均匀分布的随机离散变量,熵等于log_2(所有可能的个数,即n)。 扔一次硬币的熵是1比特。掷一次(六面)骰子的熵大约为2.58比特。
使用多少比特的熵取决于应用的威胁模型。 大约40比特的熵足以对抗在线穷举攻击(受限于网络速度和应用认证机制)。 而对于离线穷举攻击(主要受限于计算速度), 一般需要更强的密码 (比如80比特或更多)。
散列函数
抽象地讲,散列函数可以被认为是一个不可逆,且看上去随机(但具确定性)的函数 (这就是散列函数的理想模型)。 一个散列函数拥有以下特性:
确定性:对于不变的输入永远有相同的输出。
不可逆性:对于hash(m) = h,难以通过已知的输出h来计算出原始输入m。
目标碰撞抵抗性/弱无碰撞:对于一个给定输入m_1,难以找到m_2 != m_1且hash(m_1) = hash(m_2)。
碰撞抵抗性/强无碰撞:难以找到一组满足hash(m_1) = hash(m_2)的输入m_1, m_2(该性质严格强于目标碰撞抵抗性)。
别开生面的扔硬币
我可以选择一个值r = random(),并和你分享它的哈希值h = sha256(r)。 这时你可以开始猜硬币的正反:我们一致同意偶数r代表正面,奇数r代表反面。 你猜完了以后,我告诉你值r的内容,得出胜负。同时你可以使用sha256( r )来检查我分享的哈希值h以确认我没有作弊。
对称加密
1 |
|
非对称加密
1 |
|
对称加密和非对称加密可以类比为机械锁。 对称加密就好比一个防盗门:只要是有钥匙的人都可以开门或者锁门。 非对称加密好比一个可以拿下来的挂锁。你可以把打开状态的挂锁(公钥)给任何一个人并保留唯一的钥匙(私钥)。这样他们将给你的信息装进盒子里并用这个挂锁锁上以后,只有你可以用保留的钥匙开锁。
每个人都应该尝试使用密码管理器,比如KeePassXC、pass 和 1Password)。
以守护进程(daemon)运行的程序名一般以 d 结尾,比如 SSH 服务端 sshd,用来监听传入的 SSH 连接请求并对用户进行鉴权。Linux 中的 systemd(the system daemon)是最常用的配置和运行守护进程的方法。运行 systemctl status 命令可以看到正在运行的所有守护进程。
FUSE(用户空间文件系统)
–version 或者 -V 标志参数可以让工具显示它的版本信息(对于提交软件问题报告非常重要)
基本所有的工具支持使用 –verbose 或者 -v 标志参数来输出详细的运行信息。多次使用这个标志参数,比如 -vvv,可以让工具输出更详细的信息(经常用于调试)。同样,很多工具支持 –quiet 标志参数来抑制除错误提示之外的其他输出。
提问&回答
/bin - 基本命令二进制文件
/sbin - 基本的系统二进制文件,通常是root运行的
/dev - 设备文件,通常是硬件设备接口文件
/etc - 主机特定的系统配置文件
/home - 系统用户的主目录
/lib - 系统软件通用库
/opt - 可选的应用软件
/sys - 包含系统的信息和配置(第一堂课介绍的)
/tmp - 临时文件( /var/tmp ) 通常重启时删除
/usr/ - 只读的用户数据
/usr/bin - 非必须的命令二进制文件
/usr/sbin - 非必须的系统二进制文件,通常是由root运行的
/usr/local/bin - 用户编译程序的二进制文件
/var -变量文件 像日志或缓存
source script.sh 和 ./script.sh 有什么区别?
这两种情况 script.sh 都会在bash会话中被读取和执行,不同点在于哪个会话执行这个命令。 对于 source 命令来说,命令是在当前的bash会话中执行的,因此当 source 执行完毕,对当前环境的任何更改(例如更改目录或是定义函数)都会留存在当前会话中。 单独运行 ./script.sh 时,当前的bash会话将启动新的bash会话(实例),并在新实例中运行命令 script.sh。 因此,如果 script.sh 更改目录,新的bash会话(实例)会更改目录,但是一旦退出并将控制权返回给父bash会话,父会话仍然留在先前的位置(不会有目录的更改)。 同样,如果 script.sh 定义了要在终端中访问的函数,需要用 source 命令在当前bash会话中定义这个函数。否则,如果你运行 ./script.sh,只有新的bash会话(进程)才能执行定义的函数,而当前的shell不能。