关于ssh:MIT-计算机教育中缺失的一课-笔记命令行环境

7次阅读

共计 7645 个字符,预计需要花费 20 分钟才能阅读完成。

_写在后面:本篇内容来自于 MIT 推出的课程:计算机教育中缺失的一课,这门课程介绍了命令行、弱小的文本编辑器的应用、应用版本控制系统提供的多种个性等等。中文课程主页。

本篇内容为第五节:命令行环境。本节的次要内容如下:

  1. 如何同时执行多个不同的过程并追踪它们的状态、如何进行或暂停某个过程以及如何使过程在后盾运行。
  2. 一些可能改善 shell 及其他工具的工作流的办法,这次要是通过定义别名或基于配置文件对其进行配置来实现的
  3. 如何应用 SSH 操作远端机器

工作管制

完结过程

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

当咱们输出 Ctrl-C 时,shell 会发送一个 SIGINT (interrupt program) 信号到过程。另外一个退出程序的信号:SIGQUIT (quit program),能够通过 Ctrl-\ 触发。

只管 SIGINTSIGQUIT 都经常用来收回和终止程序相干的申请。SIGTERM 则是一个 更加通用的、也更加优雅地退出信号。为了收回这个信号咱们须要应用 kill 命令, 它的语法是:kill -TERM <PID>

暂停和后盾执行过程

在终端中,键入 Ctrl-Z 会让 shell 发送 SIGTSTP 信号。此时,程序被挂起,并没有完结。

应用 jobs 命令,能够查看以后会话中的过程。当程序被挂起时,能够应用 fg 命令,将挂起的程序继续执行,或者应用 bg 命令,将程序放到后盾继续执行。能够通过 jobs 打印后果中的过程标号,来援用某一个过程,如过程标号为 [1],后续能够通过 bg %1 的形式来将该过程在后盾运行,也能够通过 kill %1 的形式杀掉该过程。

执行命令时,在最初增加 &,能够间接让程序在后盾执行。然而留神,这个过程依然是终端的子过程,所以敞开终端时,这个过程也会被终止(此时发送的信号为 SIGHUP)。为了避免这种状况,能够在程序最前应用 nohup 程序:nohup command command_options,此时关掉终端,程序依然会继续执行。

以下代码演示了这些命令:

❯ sleep 1000
^Z
[1]  + 60227 suspended  sleep 1000
❯ nohup sleep 2000 &
[2] 60237
appending output to nohup.out
❯ jobs
[1]  + suspended  sleep 1000
[2]  - running    nohup sleep 2000
❯ bg %1
[1]  - 60227 continued  sleep 1000
❯ jobs
[1]  - running    sleep 1000
[2]  + running    nohup sleep 2000
❯ kill %1
[1]  - 60227 terminated  sleep 1000
❯ jobs
[2]  + running    nohup sleep 2000
❯ kill -SIGHUP %2
❯ jobs
[2]  + running    nohup sleep 2000
❯ kill %2
[2]  + 60237 terminated  nohup sleep 2000
❯ jobs

以下为 Linux 零碎中的信号列表,具体能够通过 man signal 来查问:

     No    Name         Default Action       Description
     1     SIGHUP       terminate process    terminal line hangup
     2     SIGINT       terminate process    interrupt program
     3     SIGQUIT      create core image    quit program
     4     SIGILL       create core image    illegal instruction
     5     SIGTRAP      create core image    trace trap
     6     SIGABRT      create core image    abort program (formerly SIGIOT)
     7     SIGEMT       create core image    emulate instruction executed
     8     SIGFPE       create core image    floating-point exception
     9     SIGKILL      terminate process    kill program
     10    SIGBUS       create core image    bus error
     11    SIGSEGV      create core image    segmentation violation
     12    SIGSYS       create core image    non-existent system call invoked
     13    SIGPIPE      terminate process    write on a pipe with no reader
     14    SIGALRM      terminate process    real-time timer expired
     15    SIGTERM      terminate process    software termination signal
     16    SIGURG       discard signal       urgent condition present on socket
     17    SIGSTOP      stop process         stop (cannot be caught or ignored)
     18    SIGTSTP      stop process         stop signal generated from keyboard
     19    SIGCONT      discard signal       continue after stop
     20    SIGCHLD      discard signal       child status has changed
     21    SIGTTIN      stop process         background read attempted from control terminal
     22    SIGTTOU      stop process         background write attempted to control terminal
     23    SIGIO        discard signal       I/O is possible on a descriptor (see fcntl(2))
     24    SIGXCPU      terminate process    cpu time limit exceeded (see setrlimit(2))
     25    SIGXFSZ      terminate process    file size limit exceeded (see setrlimit(2))
     26    SIGVTALRM    terminate process    virtual time alarm (see setitimer(2))
     27    SIGPROF      terminate process    profiling timer alarm (see setitimer(2))
     28    SIGWINCH     discard signal       Window size change
     29    SIGINFO      discard signal       status request from keyboard
     30    SIGUSR1      terminate process    User defined signal 1
     31    SIGUSR2      terminate process    User defined signal 2

终端多路复用(Terminal multiplexer)

来自维基百科的解释:终端多路复用器是一种软件应用程序,可用于在单个终端显示器,终端仿真器窗口,PC / 工作站零碎控制台或近程登录会话中 多路复用几个独自的基于伪终端的登录会话 ,或者 从终端拆散和从新附加会话。最罕用的终端多路复用软件为 tmux

tmux 中有三个十分重要的概念,别离为:会话、窗口和面板,对于其有很多重要的快捷键须要把握:

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

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

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

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

别名设置

设置别名能够节俭大量工夫,将常常输出的命令设置为十分短的标记,用法为:alias alias_name="command arg1 arg2",以下是几个示例:

# 创立常用命令的缩写
alias ll="ls -lh"

# 可能少输出很多
alias gs="git status"
alias gc="git commit"
alias v="vim"

# 手误打错命令也没关系
alias sl=ls

# 从新定义一些命令行的默认行为
alias mv="mv -i"           # -i prompts before overwrite
alias mkdir="mkdir -p"     # -p make parent dirs as needed
alias df="df -h"           # -h prints human readable format

# 别名能够组合应用
alias la="ls -A"
alias lla="la -l"

# 在疏忽某个别名
\ls
# 或者禁用别名
unalias la

# 获取别名的定义
alias ll
# 会打印 ll='ls -lh'

须要将想要设置别名的代码保留到 shell 的启动文件里,比方 .bashrc.zshrc

配置文件

一些常见的配置文件,位于用户目录下,以 . 结尾:

  • bash~/.bashrc~/.bash_profile
  • git~/.gitconfig
  • vim~/.vimrc~/.vim 目录
  • ssh~/.ssh/config
  • tmux~/.tmux.conf

治理这些配置文件举荐的形式:将这些文件都放到一个目录下,而后通过 git 管制版本,通过链接的形式,将文件链接到对应的文件上。这样的益处是不言而喻的:如果有多台电脑须要配置,能够一键配置;并且更改配置也会同步到每一台电脑。

远端设施

通过 ssh 连贯近程服务器,服务器能够通过 URL 指定(例如 bar.mit.edu),也能够应用 IP 指定(例如foobar@192.168.1.42)。

能够间接通过 ssh foobar@server ls 来在服务器上执行 ls 命令,只筹备执行一条命令时十分不便。

应用秘钥连贯近程服务器时,须要向服务器证实客户端持有对应的私钥。本地生成私钥:应用 ssh-keygen。将公钥传到服务器,有以下两种形式:

# 第一种形式,间接上传
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 复制文件,能够应用 scp 命令,语法为:scp path/to/local_file remote_host:path/to/remote_file。更好的是应用 rsync,它对 scp 进行了改良,能够检测本地和远端的文件以避免反复拷贝。

应用 SSH 端口转发

端口转发有两种:本地端口转发和近程端口转发。

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

SSH 配置文件

因为各种选项的存在,SSH 命令可能会很长,咱们能够通过配置 ~/.ssh/config 文件,来保留服务器的配置,这个文件能够被 scprsync 等命令读取,转换为对应的命令行选项。配置示例:

Host vm
    User foobar
    HostName 172.16.174.141
    Port 2222
    IdentityFile ~/.ssh/id_ed25519
    LocalForward 9999 localhost:8888

# 在配置文件中也能够应用通配符
Host *.mit.edu
    User foobaz

课后练习

工作管制

  1. 咱们能够应用相似 ps aux | grep 这样的命令来获取工作的 pid,而后您能够基于 pid 来完结这些过程。但咱们其实有更好的办法来做这件事。在终端中执行 sleep 10000 这个工作。而后用 Ctrl-Z 将其切换到后盾并应用 bg 来持续它的执行。当初,应用 pgrep 来查找 pid 并应用 pkill 完结过程而不须要手动输出 pid。(提醒:: 应用 -af 标记)。

    ❯ sleep 10000
    ^Z
    [1]  + 62750 suspended  sleep 10000
    ❯ bg
    [1]  + 62750 continued  sleep 10000
    ❯ pgrep sleep
    62750
    ❯ pkill -af sleep
    [1]  + 62750 terminated  sleep 10000
  2. 如果您心愿某个过程完结后再开始另外一个过程,应该如何实现呢?在这个练习中,咱们应用 sleep 60 & 作为先执行的程序。一种办法是应用 wait 命令。尝试启动这个休眠命令,而后待其完结后再执行 ls 命令。

    ❯ sleep 10 &
    [3] 62850
    # wait 只可能期待以后 shell 的子过程
    ❯ wait 62850; ls
    [3]  + 62850 done       sleep 10
然而,如果咱们在不同的 bash 会话中进行操作,则上述办法就不起作用了。因为 `wait` 只能对子过程起作用。之前咱们没有提过的一个个性是,`kill` 命令胜利退出时其状态码为 `0`,其余状态则是非 `0`。`kill -0` 则不会发送信号,然而会在过程不存在时返回一个不为 `0` 的状态码。请编写一个 `bash` 函数 `pidwait`,它承受一个 `pid` 作为输出参数,而后始终期待直到该过程完结。您须要应用 `sleep` 来避免浪费 `CPU` 性能。`wait` 程序实现:```bash
myWait() {
    pid=$1
    while true; do
        kill -0 $pid
        if [[$? -eq 0]]; then
            echo "process exists, wait for 1 seconds..."
            sleep 1
        else
            break
        fi
    done
    echo "process finished!"
    ls
}
```
将程序保留为 `wait.sh`,程序执行与后果:```bash
❯ source wait.sh
❯ sleep 10
^Z
[1]  + 63612 suspended  sleep 10
❯ bg
[1]  + 63612 continued  sleep 10
❯ myWait 63612
process exists, wait for 1 seconds...
process exists, wait for 1 seconds...
process exists, wait for 1 seconds...
process exists, wait for 1 seconds...
process exists, wait for 1 seconds...
[1]  + 63612 done       sleep 10
myWait:kill:3: kill 63612 failed: no such process
process finished!
wait.sh
```

终端多路复用

  1. 请实现这个 tmux 教程:https://www.hamvocke.com/blog/a-quick-and-easy-guide-to-tmux/
  2. 参考这些步骤来学习如何自定义 tmux:https://www.hamvocke.com/blog/a-guide-to-customizing-your-tmux-conf/

    1. 配置文件位于:~/.tmux.conf
    2. 将前缀从 Ctrl+b 替换为 Ctrl+a,不便输出

      # remap prefix from 'C-b' to 'C-a'
      unbind C-b
      set-option -g prefix C-a
      bind-key C-a send-prefix
    3. 应用 | 将面板垂直宰割,应用 - 将面板程度宰割

      # split panes using | and -
      bind | split-window -h
      bind - split-window -v
      unbind '"'
      unbind %
    4. 更快捷地重载配置,应用 前缀 +r

      # reload config file (change file location to your the tmux.conf you want to use)
      bind r source-file ~/.tmux.conf \; display-message "Config reloaded..."
    5. 更快捷地切换面板,应用 Alt 键加方向键来切换面板

      # switch panes using Alt-arrow without prefix
      bind -n M-Left select-pane -L
      bind -n M-Right select-pane -R
      bind -n M-Up select-pane -U
      bind -n M-Down select-pane -D
    6. 开启鼠标模式(不肯定须要)

      # Enable mouse mode (tmux 2.1 and above)
      set -g mouse on
    7. 进行主动重命名窗口,通过 , 手动重命名,每个窗口能够执行不同的上下文

别名

  1. 创立一个 dc 别名,它的性能是当咱们谬误的将 cd 输出为 dc 时也能正确执行。

    alias dc="cd"
  2. 执行 history | awk '{$1="";print substr($0,2)}' | sort | uniq -c | sort -n | tail -n 10 来获取您最罕用的十条命令,尝试为它们创立别名。留神:这个命令只在 Bash 中失效,如果您应用 ZSH,应用 history 1 替换 history

配置文件

让咱们帮忙您进一步学习配置文件:

  1. 为您的配置文件新建一个文件夹,并设置好版本控制
  2. 在其中增加至多一个配置文件,比如说您的 shell,在其中蕴含一些自定义设置(能够从设置 $PS1 开始)。
  3. 建设一种在新设施进行疾速装置配置的办法(无需手动操作)。最简略的办法是写一个 shell 脚本对每个文件应用 ln -s,也能够应用专用工具
  4. 在新的虚拟机上测试该装置脚本。
  5. 将您现有的所有配置文件挪动到我的项目仓库里。
  6. 将我的项目公布到 GitHub。

我将我的 tmuxvimzsh 的配置文件上传到了 GitHub,欢送基于此进行批改:https://github.com/chris-algo/dotfiles。


广告工夫

如果您喜爱我的文章,欢送给我点赞关注!也欢送关注我的公众号:算法小哥克里斯。

正文完
 0