LOADING...

加载过慢请开启缓存(浏览器默认开启)

loading

The Missing Semester

The Shell

  • echo $PATH 列出所有环境变量
  • which echo 查找echo的位置
  • macos、linux路径是斜杠,而windows是反斜杠*
  • ~ 用户文件夹 - 上一个位置
  • ls --help 查看帮助文档
  • ~/bin 中文件所有用户均可执行
  • mv 重命名/移动文件位置
  • cp 复制文件
  • rm 删除文件(永久删除,不进回收站) rmdir 删除指定空目录
  • Ctrl+L 清屏终端并回到顶部
  • echo “hello” > hello.txt 重定向输入输出(如echo到文件中、从文件中echo)
  • cat hello.txt 打印文件内容到终端
  • >> 在输入输出流后面追加内容
  • | 管道,将|前面的输出连接为|后面的输入
  • tail -n5 打印出输入文本的最后五行
  • ~/sys 各种硬件配置
  • 常见命令行标志参数
    • --help 显示简略用法
    • --version-V 显示软件版本信息
    • --verbose-v 输出详细的运行信息
    • -- 停止处理后面的标志参数(若文件名是-r时,防止歧义)

Shell Scripting

  • foo=bar (中间无空格)将bar赋给变量foo

  • $foo调用“bar” (fish中是set foo bar)

  • $(ls) 调用括号内容(如ls的输出) 如foo=$(pwd) 将pwd输出内容存到foo变量中

  • ' ' 引用的字符串输出原本字符 如echo ‘Value is $foo’ 输出为$foo

  • " " 引用的字符串输出特殊含义 如上面一句输出为foo储存的量

  • $ + 字符

    • $? 判别上一个命令是否产生错误,即返回值 echo $?

      • 若错误或未执行,返回 1 (理解为未正确执行的报错1);

      • 若正确,返回 0 (理解为正确执行后的退出代码return 0)

    • $0 正在运行的脚本的名称

    • $1\$9 脚本的第~个参数

    • $# 参数数量

    • $$ 正在运行的命令的进程ID

    • $@ 进程中的所有参数

    • $_ 上一条命令的最后一个参数(交互式shell中可按Esc后键入,来获取该值)

  • true 永远真, $? == 0 ; false 永远假,$? == 1

  • && 逻辑且 如果前面真($? == 0) 后面才会执行;只要有一个$? == 1,就不会向后执行

  • || 逻辑或 如果前面假($? == 1) 后面才会执行;只要有一个$? == 0,就不会向后执行

  • ; 连接两端代码,但语句结尾不加分号

  • shell函数格式

    func () {
        mkdir -p "$1"
        cd "$1"
    }
    

    加载写在文件中的shell函数

    source func.sh
    
  • $( cmd ) 的值是cmd命令的输出,即命令替换

  • <( cmd ) 会执行cmd命令,并将结果输出到一个临时文件中,即进程替换

  • grep foobar "$file" 寻找文件中是否有该字符串,有则返回0,没有则返回1

    for file in "$@"; do
        grep foobar "$file" > /dev/null 2> /dev/null
        # 如果模式没有找到,则grep退出状态为 1
        # 我们将标准输出流和标准错误流重定向到Null,因为我们并不关心这些信息
        if [[ $? -ne 0 ]]; then
            echo "File $file does not have any foobar, adding one"
            echo "# foobar" >> "$file"
        fi
    done
    
  • bash中进行比较时,尽量用双方括号[[ ]]而非单方括号[ ]

  • 通配符

    • ? 代表一个或多个字符
    • * 代表零个或多个字符
    • { } 压缩公共子串,如image.{png, jpg}对应这两个文件
    • {a..z} a到z的字符串
  • shebang行

    shebang是由#!构成的字符序列,为了让内核知道用python解释器而不是shell命令来运行这段脚本

    #!/usr/local/bin/python
    
  • shell函数和脚本的不同点:

    • 函数只能与shell使用相同的语言,脚本可以使用任意语言。因此在脚本中包含 shebang 是很重要的
    • 函数仅在定义时被加载,脚本会在每次被执行时加载。函数的加载比脚本略快一些,但每次修改函数定义,都要使用source重新加载一次

Shell Tools

  • find 命令 递归查找文件/文件夹

    -name -type -path -size -mtime 限定名称、类型、路径、大小、修改日期

    -exec + 命令 操作文件

  • grep命令:查找文件中的文本

    grep的选项:

    -i 不区分大小写查找

    -C 获取查找结果的上下文

    -v 输出不匹配的结果,反选

    -R 递归地进入子目录并搜索

  • history 访问历史命令

  • xargs命令 接受标准输入作为参数,并处理

    -d参数 可更改分隔符,如

    echo "ONE TWO THREE" | xargs mkdir
    # 会生成三个文件夹"ONE,TWO,THREE"
    echo "ONT TWO THREE" | xargs -d "\t" mkdir
    # 将分隔符改为制表符,只生成一个文件夹"ONE TWO THREE"
    
  • tar命令 压缩、解压文件

    -c 压缩 -x 解压 -t 查看内容 -r 向压缩文件末尾追加文件 -u 更新原压缩包文件 (只能用其中一个功能)

    -z 有zip属性的 -v 显示所有过程

    -f 命名为(只能放在最后一个)

  • head -num 文件 查看文件前num行内容

Editors(Vim)

  • 普通模式快捷键
    • i 在闪烁词前面插入文本(insert)
    • a 在闪烁词后面插入文本
    • x 删除闪烁词
    • w 选中至下一个单词(word)(中文就是汉字)
    • b 单词的开头(beginning)
    • e 单词的结尾(ending)
    • d 删除(delete)
    • u 撤销一步操作(undo)
    • U 撤销一行中的所有改动
    • r 替换(replace)
    • R 进入替换模式
    • y 复制
    • p 粘贴(paste)
    • o 行首/在光标下面插入一行
    • O 在光标上面插入一行
    • $ 行尾
    • v 进入可视模式(vision)
    • V 进入整行选中模式
    • ~ 改变选中字符的大小写
  • 快捷键组合使用

    • dw 光标处删除一个单词

    • dd 删除一整行

    • d$ 从行尾往前删除

    • d+数字 删除多少个

      如:d2w 删除两个单词

      ​ 2dd 删除两行

    • cw/ce 删除光标以后一个单词,并进入insert模式(c: change)

    • c$ 删除光标后内容直至行末,并进入insert模式

    • f+字母 跳到第一个字母

    • H 屏幕上的首行

    • M 屏幕上的中间

    • L 屏幕上的底部

    • gg 跳转到文件首行

    • G 跳转到文件末行

    • 数字+G 跳转到第_行

    • ctrl+r 撤销之前的撤销命令

    • ctrl+g 显示文件信息/当前所在的行列(goto)

    • ctrl+o 回到之前位置

    • ctrl+i 回到较新位置

    • ctrl+v 进入矩形框选中模式

    • ctrl+u 上翻页

    • ctrl+d 下翻页

  • 查找

    • /+字符串 查找

      • n 查找下一个
      • N 查找上一个
    • ?+字符串 查找(逆向)

    • 在括号处按% 查找对应括号位置

  • 命令

    • :set ic 查找不区分大小写模式

      :set noic 查找区分大小写模式

    • :s/old/new 替换第一个old为new

    • :s/old/new/g 替换一行中所有的old为new

    • :%s/old/new/g 替换全文所有old为new,并提示确认(/gc)

    • :!命令 执行外部命令(如 ls mkdir)

    • :w 文件名 保存为_

    • :e 文件名 打开文件(edit)

    • :r+… 提取…文件/…命令并插入到光标下面

    • :qa 退出所有窗口

Data Wrangling

  • journalctl命令 查看日志文件

  • sed 基于ed构建的流编辑器,可利用简单的脚本命令来修改文件,有很多可选参数

    s命令格式:sed -E ‘s/regex/substitution/‘ 将符合正则表达式regex的内容替换为substitution

  • wc命令 计算字数、行数、字节数

  • 正则表达式REGEX

    . 除换行符之外的任意单个字符

    a*匹配前面字符零次或多次

    a+匹配前面字符一次或多次

    [abcd]匹配a, b, c, d中的任意一个字符

    [^abc]匹配除a, b, c以外的任意一个字符

    [0-6]匹配0到6的任意一个字符

    [ ]代表一个字符

    [abc]{5}匹配5个abc中的字符

    a{1,3}匹配a不少于1次,不超过3次

    (rx1|rx2)任何能够匹配rx1或rx2的结果

    a?匹配0个或1个a

    ^start匹配行首是start的行

    end$匹配行尾是end的行

    ( )与命令结合,起数学中括号作用

\d匹配任意数字字符

\w代表[A-Za-z0-9],用于匹配英文文本

\s空格字符

\转义符,将有特殊意义的字符转换为本身意义;或把普通字符 转换为特殊意义

\D大写的字符表示原意义的相反含义,如\D表示匹配任意一个 非数字字符

  • sort命令 将输入数据进行排序

    -n 升序排序

    -r 倒序排序

  • uniq命令 检查文件中重复出现的行列

    -c 在每列旁边显示该行重复出现的次数

  • awk命令 强大的文本处理工具

    awk是一种编程语言,格式为awk '{模式串} {代码块}'

    awk '{print $2}'
    # 代码块中,$0表示整行内容,\$1到\$n表示一行中的n个区域(默认用空格分割)
    awk '$1 == 1 && $2 ~ /^c[^ ]*e$/ { print $2 }'
    # 模式串中,先筛选第一部分为1的,还要满足下面的正则表达式,再执行操作
    
  • paste命令 用于合并文件

  • bc命令 计算器,计算输入的值

    bc 文件 计算文件中的运算值

  • tee命令 读取输入数据,并保存到文件中

Command-line Environment

  • 进程控制

    • SIGINT信号,用Ctrl+c发出

    • SIGQUIT信号,用Ctrl+\发出

    • SIGTERM信号,用kill命令发出,

    • SIGSTOP信号,用Ctrl+z发出,暂停/挂起进程

    • SIGHUP信号,关闭终端时发出的信号

    • fg命令 在前台恢复暂停的工作

    • bg命令 在后台恢复暂停的工作

    • jobs命令 列出当前终端会话中尚未完成的全部任务

      可用pid选取进程,也可用%+进程编号来选取进程

      $!选择最近的一个进程

    • pgrep命令 查看进程的pid

      pgrep 关键字 查找进程pid

    • ps命令 查看正在运行的进程

    • pkill命令 给予进程名来结束进程

    • 守护进程(daemon):在后台保持运行,不需要用户手动运行或者交互的进程

      以守护进程运行的程序名一般以 d 结尾,比如 SSH 服务端 sshd

  • 终端多路复用

    tmux是一个终端多路复用器,可基于面板和标签分割出多个终端窗口,可以同时与多个 shell 会话进行交互;可以分离当前终端会话并在将来重新连接(可用于clash开机自启、保持启动)

    • 会话:一个独立的工作区。在shell中,会话与终端窗口绑定,而在tmux中解除绑定

      tmux 开始一个新的会话

      tmux new -s NAME 以制定名称开始一个新的会话

      tmux ls 列出当前所有会话

      <Ctrl+b> d 将当前回话分离

      tmux -t a 重新连接会话(没有-t则连接最后一个)

    • 窗口:从视觉上将一个回话分割为多个部分

      <Ctrl+b> c 创建新窗口 <Ctrl+d> 关闭

      <Ctrl+b> N 跳转到第N个窗口

      <Ctrl+b> p 上一个窗口 <Ctrl+b> n 下一个窗口

      <Ctrl+b> w 列出所有窗口

    • 面板:分屏,在一个屏幕里显示多个shell

  • 别名与配置文件

    • alias命令 设置别名

      alias 别名="原命令"

      alias 列出所有别名

      alias 别名 获取别名定义

      unalias 别名 删除别名

    • 在默认情况下 shell 并不会保存别名。为了让别名持续生效,需要将配置放进 shell 的启动文件里,像是.bashrc.zshrc

    • 可编辑配置文件来加强可移植性,如

      # 针对不同的设备编写不同的配置
      if [[ "$(uname)" == "Linux" ]]; then {do_something}; fi
      
      # 使用和 shell 相关的配置时先检查当前 shell 类型
      if [[ "$SHELL" == "zsh" ]]; then {do_something}; fi
      
      # 针对特定的设备进行配置
      if [[ "$(hostname)" == "myServer" ]]; then {do_something}; fi
      
      # 在不同程序间共享别名
      if [ -f ~/.aliases ]; then
          source ~/.aliases
      fi
      
  • 远程设备

    • ssh命令

      ssh foo@bar,mit.edu 用ssh连接到其他服务器,并可以直接远程执行命令

    • ssh-keygen命令 可生成密钥

      # 生成名字叫id_ed25519的密钥
      ssh-keygen -o -a 100 -t ed25519 -f ~/.ssh/id_ed25519
      
    • ssh会查询.ssh/authorized_keys来确认哪些用户可以被允许登录,可用以下命令拷贝公钥

      cat .ssh/id_ed25519 | ssh foobar@remote 'cat >> ~/.ssh/authorized_keys'
      
      # 或者
      
      ssh-copy-id -i .ssh/id_ed25519.pub foobar@remote
      
    • scp命令 安全传输文件

      # 从该服务器下载文件或目录
      # -r 递归复制整个目录
      scp -r root@192.168.1.1:/home/t.log ./
      
      # 上传文件到该服务器
      scp t.log root@192.168.1.1:/home
      
    • rsync命令 安全传输文件(只传输更改的文件,速度比scp更快),语法与scp相似

      -a 同步文件元信息(大小、修改日期)

    • ssh端口转发

      ssh -L 本地端口转发 ssh -R 远程端口转发

      # 监听远程服务器foobar的8888端口,并建立从本地端口9999的转发
      # 此时访问localhost:9999即可监听
      
      ssl -L 9999:localhost:8888 foobar@remote_server
      
    • ssh配置

      编辑~/.ssh/config文件

      Host vm
          User foobar
          HostName 172.16.174.141
          Port 2222
          IdentityFile ~/.ssh/id_ed25519
          LocalForward 9999 localhost:8888
      
      # 在配置文件中也可以使用通配符
      Host *.mit.edu
          User foobaz
      

Version Control(Git)

  • git中的对象

    • Blob对象 数据对象,即文件
    • Tree 树,即目录
    • commit 提交
  • git存储数据时,所有的对象都会基于它们的SHA-1哈希进行寻址

    # 用下面命令可查看
    git cat-file -p 698281bc680d1995c5f4caaf3359721a5a58d48d
    
  • 用引用(指向commit的指针)可以赋予这些哈希值人类可读的名字

  • 当前的位置索引:HEAD

    HEAD可指向分支,也可以指向提交,可分离HEAD

  • 暂存区

  • git命令行接口(<>忽略)

    • git init 创建一个新的git仓库,数据会存放在.git目录下

    • git status 显示当前的仓库状态

    • git commit 创建一个新的提交/快照/版本

      --amend 修改上一次提交

    • git diff <filename> 显示与暂存区文件的差异

    • git diff <reversion> <filename> 显示某文件两个版本之间的差异

    • git branch 显示分支

    • git branch <name> 创建分支

    • git checkout <name> 改变HEAD/目前的分支

    • git merge <version> 把<version>合并到当前分支

    • git rebase <version> 线性化合并分支到<version>

    • ^ 向上移动到parent

      ^<num> 从左到右依次移动到第<num>个parent

      # 移动到分支main的parent节点
      git checkout main^
      
      # 依次移动到目标
      git checkout HEAD^3
      
    • ~<num> 一次向上移动<num>次

    • -f 将分支强制指向某个提交,如

      # 将main分支强制指向HEAD的第三季parent提交
      git branch -f main HEAD~3
      
    • git reset <version> 将当前分支撤销到<version>这个节点

    • git revert <version> 撤销更改(并分享给别人)

      原理:多一个新提交,引入更改来撤销上个提交

    • git cherry-pick <version1> ... 将<version1>等一些提交复制到当前HEAD所在位置下面

    • git rebase -i <version> 交互式排序各个提交

    • git tag <v1> <version> 将<version>这个提交贴上<v1>标签

    • git dscribe <name> 输出离<name>最近的tag

    • git checkout -- <file> 丢弃更改

    • git log <file> 列出文件历史提交记录

      -<num> 列出文件最新的num次提交

    • git blame <file> 列出文件的修改记录

    • git show <object> 列出查看的对象

    • git add <file> 将文件添加到暂存区

  • git远端操作

    • git clone 上传/下载仓库

    • 远端分支命名规范为ogigin/<name>

    • git push 将本地数据推送到远程仓库

      git push <origin> <place> 切换到<place>分支,再到远程的<origin>/<place>分支中,将没有的记录更新上去

      git push <origin> <source>:<destination> 将<source>这一节点推送到远程<origin>的<distination>分支

      若<source>为空白,则删除<origin>的<distination>分支

    • git fetch 从远程仓库获取数据(只会更新到最新的origin/main状态)

      git fetch <origin> <place> 切换到远程<place>分支,再到本地的<origin>/<place>分支中,将没有的记录更新上去

      git push <origin> <source>:<destination> 将<source>这一节点推送到本地<origin>的<distination>分支

      若<source>为空白,则在本地<origin>创建一个新的<destination>分支

    • git pull 从远程仓库获取数据并合并到本地(fetch+merge)

      git pull --rebase (fetch+rebase)

    • git checkout -b foo origin/main 切换到一个叫foo的新分支,并使其追踪远程的main

      或:git branch -u origin/main foo

    • git remote 列出远端

    • git remote add <name> <url> 添加一个远端

  • PR pull requestion 即将自己的代码提交上去,让原作者拉取

Debugging and profiling

  • seq 开始 步长 结束 输出固定间隔的数字

    # 在终端中打印多种颜色
    
    for R in $(seq 0 20 255); do
        for G in $(seq 0 20 255); do
            for B in $(seq 0 20 255); do
                printf "\e[38;2;${R};${G};${B}m█\e[0m";
            done
        done
    done
    
  • journalctl命令 查看系统日志

  • /var/log/ 大多数程序日志的所在地

  • pdb是Python的调试器

    • l(ist) - 显示当前行附近的11行或继续执行之前的显示
    • s(tep) - 执行当前行,并在第一个可能的地方停止
    • n(ext) - 继续执行直到当前函数的下一条语句或者 return 语句
    • b(reak) - 设置断点(基于传入的参数)
    • p(rint) - 在当前上下文对表达式求值并打印结果
    • r(eturn) - 继续执行直到当前函数返回
    • q(uit) - 退出调试器
  • time 命令 在命令前面加上time前缀,可统计命令执行的实际时间、用户时间、系统时间

    • real - 从程序开始到结束流失掉的真实时间,包括其他进程的执行时间以及阻塞消耗的时间(例如等待 I/O或网络)
    • user - CPU 执行用户代码所花费的时间
    • sys - CPU 执行系统内核代码所花费的时间

​ 进程消耗的实际CPU = user + sys

Metaprogramming

  • make指令 最常用的构建工具,可由构建目标相关依赖构建规则来构建出文件

    • make -f rules.txt 根据构建规则rule.txt了来构建文件

    • Makefile文件由一系列rules构成

      # 以下是每一条rule的格式
      # <target>是必须的,<prerequisites>和<command>至少存在一个
      
      # <target> : <prerequisites1> ...
      # 	<command>
      # 如:
      
      result.txt: source.txt
          cp source.txt result.txt
      
    • 若make命令运行时没有指定目标,默认执行makefile文件的第一个目标

      <target>也可以是某个操作的名字,叫作伪目标(phony target),可以在rule前面加一行.PHONY: <P_target>来声明,防止伪目标与文件名重名

    • 前置条件(prerequisites)通常是一组文件名,之间用空格分隔.只要有一个前置文件不存在,或者有过更新,”目标”就需要重新构建

    • 命令(command)由一行或多行的Shell命令组成,它的运行结果通常就是生成目标文件。每行命令之前必须有一个tab键

    • 每行命令在一个单独的shell中执行。这些Shell之间没有继承关系。解决方法:

      # 多行命令写到一行中,用;分隔
      var-kept:
          export foo=bar; echo "foo=[$$foo]"
          
      # 在换行符前加反斜杠转义
      var-kept:
          export foo=bar; \
          echo "foo=[$$foo]"
          
      # 用.ONESHELL命令
      
          .ONESHELL:
          var-kept:
              export foo=bar; 
              echo "foo=[$$foo]"
      

Security

  • 度量了不确定性,并可以用来决定密码的强度

    熵的单位是比特,对于一个均匀分布的随机离散变量,熵等于$\log_2n$.(n是所有可能的个数)

  • 密码散列函数:可将任意大小的数据映射为一个固定大小的输出,如SHA-1, SHA-2等

  • sha1sum命令 接收字符串,输出加密过的SHA-1密码

    $ printf 'hello' | sha1sum
    aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
    
  • 对称加密

    信息的发送方和接收方使用同一个密钥去加密和解密数据,所以又叫私钥加密

  • 非对称加密

    用公钥或私钥中的任何一个进行加密,用另一个进行解密,所以又叫公钥加密

API

  • curl 利用url工具上传、下载文件的工具

    curl <url> 下载该url的html文件,并打印到屏幕

  • 大多数线上服务提供的 API(应用程序接口)让你可以通过编程方式来访问这些服务的数据

    它们的结构化 URL 通常使用 api.service.com 作为根路径,用户可以访问不同的子路径来访问需要调用的操作,以及添加查询参数使 API 返回符合查询参数条件的结果

showimg