https://missing.csail.mit.edu/
https://missing-semester-cn.g...
https://www.bilibili.com/vide...

笔记

工作管制

shell 会应用 UNIX 提供的信号机制执行过程间通信。当一个过程接管到信号时,它会进行执行、解决该信号并基于信号传递的信息来扭转其执行。就这一点而言,信号是一种软件中断。

完结过程

  • See man signal for reference
  • kill: sends signals to a process; default is TERM
  • SIGINT: ^C; interrupt program; terminate process
  • SIGQUIT: ^\; quit program
  • SIGKILL: terminate process; kill program; cannot be captured by process and will always terminate immediately

    • Can result in orphaned child processes
  • SIGSTOP: pause a process

    • SIGTSTP: ^Z; terminal stop
  • SIGHUP: terminal line hangup; terminate process; will be sent when terminal is closed

    • Use nohup to avoid
  • SIGTERM: signal requesting graceful process exit

    • To send this signal: kill -TERM <pid>

上面这个 Python 程序向您展现了捕捉信号 SIGINT 并疏忽它的基本操作,它并不会让程序进行。为了进行这个程序,咱们须要应用 SIGQUIT 信号。

#!/usr/bin/env python import signal, timedef handler(signum, time):    print("nI got a SIGINT, but I am not stopping")signal.signal(signal.SIGINT, handler)i = 0while True:    time.sleep(.1)    print("r{}".format(i), end="")    i += 1 
$ python sigint.py24^CI got a SIGINT, but I am not stopping26^CI got a SIGINT, but I am not stopping30^\[1]    39913 quit       python sigint.py

暂停和后盾执行过程

应用 fgbg 命令复原暂停的工作。它们别离示意在前台持续或在后盾持续。

jobs 命令会列出以后终端会话中尚未实现的全副工作。能够应用 pid 援用这些工作(也能够用 pgrep 找出 pid)。也能够应用百分号 + 工作编号(jobs 会打印工作编号)来选取该工作。如果要抉择最近的一个工作,能够应用 $! 这一非凡参数。

命令中的 & 后缀能够让命令在间接在后盾运行,不过它此时还是会应用 shell 的规范输入。

应用 Ctrl-Z 放入后盾的过程依然是终端过程的子过程,一旦敞开终端(会发送另外一个信号 SIGHUP),这些后盾的过程也会终止。为了避免这种状况产生,能够应用 nohup (一个用来疏忽 SIGHUP 的封装) 来运行程序。针对曾经运行的程序,能够应用 disown

$ sleep 1000^Z[1]  + 18653 suspended  sleep 1000$ nohup sleep 2000 &[2] 18745appending output to nohup.out$ jobs[1]  + suspended  sleep 1000[2]  - running    nohup sleep 2000$ bg %1[1]  - 18653 continued  sleep 1000$ jobs[1]  - running    sleep 1000[2]  + running    nohup sleep 2000$ kill -STOP %1[1]  + 18653 suspended (signal)  sleep 1000$ jobs[1]  + suspended (signal)  sleep 1000[2]  - running    nohup sleep 2000$ kill -SIGHUP %1[1]  + 18653 hangup     sleep 1000$ jobs[2]  + running    nohup sleep 2000$ kill -SIGHUP %2$ jobs[2]  + running    nohup sleep 2000$ kill %2[2]  + 18745 terminated  nohup sleep 2000$ jobs 

终端多路复用

终端多路复用使咱们能够拆散以后终端会话并在未来从新连贯。这让您操作远端设施时的工作流大大改善,防止了 nohup 和其余相似技巧的应用。

当初最风行的终端多路器是 tmux

  • 会话 - 每个会话都是一个独立的工作区,其中蕴含一个或多个窗口

    • tmux 开始一个新的会话
    • tmux new -s NAME 以指定名称开始一个新的会话
    • tmux ls 列出以后所有会话
    • tmux 中输出 <C-b> d(detach),将以后会话拆散
    • tmux a(attach)从新连贯最初一个会话。您也能够通过 -t 来指定具体的会话
  • 窗口 - 相当于编辑器或是浏览器中的标签页,从视觉上将一个会话宰割为多个局部

    • <C-b> c 创立一个新的窗口,应用 <C-d>敞开
    • <C-b> N 跳转到第 N 个窗口,留神每个窗口都是有编号的
    • <C-b> p(previous)切换到前一个窗口
    • <C-b> n(next)切换到下一个窗口
    • <C-b> , 重命名以后窗口
    • <C-b> w 列出以后所有窗口
  • 面板 - 像 vim 中的分屏一样,面板使咱们能够在一个屏幕里显示多个 shell

    • <C-b> " 程度宰割
    • <C-b> % 垂直宰割
    • <C-b> <方向> 切换到指定方向的面板,<方向> 指的是键盘上的方向键
    • <C-b> z(zoom)切换以后面板的缩放
    • <C-b> [ 开始往回卷动屏幕。您能够按下空格键来开始抉择,回车键复制选中的局部
    • <C-b> <空格> 在不同的面板排布间切换

扩大浏览: 这里 是一份 tmux 疾速入门教程, 而这一篇 文章则更加具体,它蕴含了 screen 命令。您兴许想要把握 screen 命令,因为在大多数 UNIX 零碎中都默认装置有该程序。

别名

# colorlssource $(dirname $(gem which colorls))/tab_complete.shalias ls=colorlsalias l="ls -lh"alias ll="ls -lAh"alias la="ls -lah"alias hz="history | fzf"alias mv="mv -i"alias cp="cp -i"alias mkdir="mkdir -p"# To ignore an alias run it prepended with \ls# Or disable an alias altogether with unaliasunalias la# To get an alias definition just call it with aliasalias l# Will print l='ls -lh'

配置文件(Dotfiles)

  • shell startup scripts
  • guide to dotfiles on github
  • example popular dotfiles

治理配置文件的一个办法是,把它们集中放在一个文件夹中,例如 ~/.dotfiles/,并应用版本控制系统进行治理,而后通过脚本将其 符号链接 到须要的中央。这么做有如下益处:

  • 安装简单: 如果您登录了一台新的设施,在这台设施上利用您的配置只须要几分钟的工夫;
  • 能够执行: 您的工具在任何中央都以雷同的配置工作
  • 同步: 在一处更新配置文件,能够同步到其余所有中央
  • 变更追踪: 您可能要在整个程序员生涯中继续保护这些配置文件,而对于长期我的项目而言,版本历史是十分重要的

一些技巧:

if [[ "$(uname)" == "Linux" ]]; then {do_something}; fi# 应用和 shell 相干的配置时先查看以后 shell 类型if [[ "$SHELL" == "zsh" ]]; then {do_something}; fi# 您也能够针对特定的设施进行配置if [[ "$(hostname)" == "myServer" ]]; then {do_something}; fi# Test if ~/.aliases exists and source itif [ -f ~/.aliases ]; then    source ~/.aliasesfi

远端设施

SSH (Secure Shell)

# 连贯设施ssh foo@bar.mit.edu ssh foobar@192.168.1.42# 如果存在配置文件,能够简写ssh bar# 执行命令# 在本地查问远端 ls 的输入ssh foobar@server ls | grep PATTERN# 在远端对本地 ls 输入的后果进行查问ls | ssh foobar@server grep PATTERN

SSH 密钥

基于密钥的验证机制应用了密码学中的公钥,咱们只须要向服务器证实客户端持有对应的私钥,而不须要公开其私钥。这样您就能够防止每次登录都输出明码的麻烦了机密就能够登录。

ssh-keygen -t ed25519 -C "_your_email@example.com_"# If you are using a legacy system that doesn't support the Ed25519 algorithm, use:ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

生成的 id_rsaid_rsa.pub 两个文件(或者 id_ed25519id_ed25519.pub),别离为的私钥公钥。私钥等效于你的明码,所以肯定要好好保留它。要查看您是否持有某个密钥对的明码并验证它,您能够运行 ssh-keygen -y -f /path/to/key

ssh 会查问 .ssh/authorized_keys 来确认那些用户能够被容许登录。您能够通过上面的命令将一个公钥拷贝到这里:

cat .ssh/id_ed25519.pub | ssh foobar@remote 'cat >> ~/.ssh/authorized_keys' 

如果反对 ssh-copy-id 的话,能够应用上面这种更简略的解决方案:

ssh-copy-id -i .ssh/id_ed25519.pub foobar@remote

通过 SSH 复制文件

应用 ssh 复制文件有很多办法:

  • ssh+tee, 最简略的办法是执行 ssh 命令,而后通过这样的办法利用规范输出实现 cat localfile | ssh remote_server tee serverfile。回顾一下,tee 命令会将规范输入写入到一个文件;
  • scp :当须要拷贝大量的文件或目录时,应用scp 命令则更加不便,因为它能够不便的遍历相干门路。语法如下:scp path/to/local_file remote_host:path/to/remote_file
  • rsyncscp 进行来改良,它能够检测本地和远端的文件以避免反复拷贝。它还能够提供一些诸如符号连贯、权限治理等精心打磨的性能。甚至还能够基于 --partial标记实现断点续传。rsync 的语法和scp相似。

端口转发

本地端口转发

近程端口转发

常见的情景是应用本地端口转发,即远端设施上的服务监听一个端口,而您心愿在本地设施上的一个端口建设连贯并转发到近程端口上。例如,咱们在远端服务器上运行 Jupyter notebook 并监听 8888 端口。 而后,建设从本地端口 9999 的转发,应用 ssh -L 9999:localhost:8888 foobar@remote_server 。这样只须要拜访本地的 localhost:9999 即可。

SSH 配置

应用 ~/.ssh/config 文件来创立别名,相似 scprsyncmosh的这些命令都能够读取这个配置并将设置转换为对应的命令行选项。

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

服务器侧的配置通常放在 /etc/ssh/sshd_config。您能够在这里配置免密认证、批改 shh 端口、开启 X11 转发等等。也能够为每个用户独自指定配置。

杂项

连贯近程服务器的一个常见痛点是遇到由关机、休眠或网络环境变动导致的掉线。如果连贯的提早很高也很让人厌恶。Mosh(即 mobile shell )对 ssh 进行了改良,它容许连贯漫游、间歇连贯及智能本地回显。

有时将一个远端文件夹挂载到本地会比拟不便, sshfs 能够将远端服务器上的一个文件夹挂载到本地,而后您就能够应用本地的编辑器了。

Shell & 框架

常见的 Shell:

  • bash
  • zsh
  • fish

常见的 Shell 框架:

  • oh-my-zsh
  • prezto

终端模拟器

一些经典的模拟器:

  • xterm
  • GNOME Terminal
  • Konsole
  • Xfce Terminal
  • urxvt
  • Terminator

一些新兴的模拟器(通常具备更好的性能,例如上面两个具备 GPU 减速):

  • Alacritty
  • kitty

课后练习

工作管制

习题 1

$ sleep 1000^Z[1]  + 689 suspended  sleep 1000$ sleep 2000                                                                   ^Z[2]  + 697 suspended  sleep 2000$ jobs[1]  - suspended  sleep 1000[2]  + suspended  sleep 2000$ bg %1[1]  - 689 continued  sleep 1000$ jobs[1]  - running    sleep 1000[2]  + suspended  sleep 2000$ pgrep -af "sleep 1"689 sleep 1000$ pkill -f "sleep 1"[1]  - 689 terminated  sleep 1000$ jobs[2]  + suspended  sleep 2000$ pkill -f "sleep 2"$ jobs[2]  + suspended  sleep 2000$ pkill -9 -f "sleep 2"[2]  + 697 killed     sleep 2000$ jobs

参见 man kill,默认发送的信号是 TERM。-9 等价于 -SIGKILL 或者 -KILL

习题 2

$ sleep 10 &[1] 1121$ pgrep sleep | wait ; ls[1]  + 1121 done       sleep 10   Nothing to show here
$ pidwait() {    wait $1    echo "done"    eval $2}$ sleep 10 &[1] 1420$ pidwait 1420 "ls"[1]  + 1420 done       sleep 10done   Nothing to show here