Job Control

在shell中可以使用 UNIX 提供的信号机制执行进程间通信。当一个进程接收到信号时,它会停止执行、处理该信号并基于信号传递的信息来改变其执行。信号是一种软件中断。Unix信号如下:

Killing a process

结束进程:

  • SIGINTCtrl-C
  • SIGQUITCtrl-\)都常常用来发出和终止程序相关的请求。
  • SIGTERM 则是一个更加通用的、也更加优雅地退出信号。为了发出这个信号我们需要使用 kill命令, 它的语法是: kill -TERM <PID>

Pausing and backgrounding processes

暂停进程:

​SIGSTOP​​ 会让进程暂停。在终端中,键入 ​​Ctrl-Z​​ 会让 shell 发送 ​​SIGTSTP​​ 信号。(​​SIGTSTP​​ is the terminal’s version of ​​SIGSTOP​​)



恢复暂停的作业:

使用 ​​fg​​(font) 或 ​​bg​​(back)命令恢复暂停的工作。它们分别表示在前台继续或在后台继续。

​jobs​​ 命令会列出当前终端会话中尚未完成的全部任务。可以使用 pid 引用这些任务(也可以用 ​​pgrep​​ 找出 pid)。

更加符合直觉的操作是使用百分号 + 任务编号(例如%1、%2,可以使用​​jobs​​ 会打印任务编号)来选取该任务。如果要选择最近的一个任务,可以使用 ​​$!​​ 这一特殊参数。



作业后台运行

给命令加上 ​​&​​ 后缀可以让命令在直接在后台运行,这使得我们可以直接在 shell 中继续做其他操作,不过它此时还是会使用 shell 的标准输出(这种情况可以使用 shell 重定向处理)。

让已经在运行的进程转到后台运行:

  1. 可以键入​​Ctrl-Z​​ ( ​​SIGTSTP​​信号)
  2. jobs查看所有作业
  3. ​bg​​转到后台运行

需要注意的是,后台的进程仍然是终端进程的子进程,一旦关闭终端(会发送另外一个信号​​SIGHUP​​),这些后台的进程也会终止。为了防止这种情况发生,您可以使用 ​​nohup​​ (一个用来忽略 ​​SIGHUP​​ 的封装) 来运行程序。针对已经运行的程序,可以使用​​disown​​ 。

$ sleep 1000
^Z
[1] + 18653 suspended sleep 1000

$ nohup sleep 2000 &
[2] 18745
appending 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


Terminal Multiplexers

在使用命令行时,通常会希望同时执行多个任务。出于解决终端过多问题,可以使用终端多路复用器。

现在最流行的终端多路器是 ​​tmux​​。​​tmux​​ 是一个高度可定制的工具,您可以使用相关快捷键创建多个标签页并在它们间导航。

​tmux​​ 的快捷键都是类似 ​​<C-b> x​​ 这样的组合,即需要先按下​​Ctrl+b​​,松开后再按下 ​​x​​。

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

  • ​tmux​​ 开始一个新的会话
  • ​tmux new -s NAME​​ 以指定名称开始一个新的会话
  • ​tmux ls​​ 列出当前所有会话
  • 在 ​​tmux​​ 中输入 ​​<C-b> d​​ ,将当前会话分离
  • ​tmux a​​ 重新连接最后一个会话。您也可以通过 ​​-t​​ 来指定具体的会话

窗口 - 相当于编辑器或是浏览器中的标签页,从视觉上将一个会话分割为多个部分

  • ​<C-b> c​​ 创建一个新的窗口,使用 ​​<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> <空格>​​ 在不同的面板排布间切换
Aliases

大多数 shell 都支持设置别名。shell 的别名相当于一个长命令的缩写,shell 会自动将其替换成原本的命令。

# 创建常用命令的缩写
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 并不会保存别名。为了让别名持续生效,需要将配置放进 shell 的启动文件里,像是​​.bashrc​​ 或 ​​.zshrc​​。

Dotfiles

很多程序的配置都是通过纯文本格式的被称作dotfiles的配置文件来完成的(之所以称为点文件,是因为它们的文件名以 ​​.​​ 开头,例如 ​​~/.vimrc​​。也正因为此,它们默认是隐藏文件,​​ls​​并不会显示它们)。

shell 的配置也是通过这类文件完成的。在启动时, shell 程序会读取很多文件以加载其配置项。

一些其他的工具也可以通过dotfiles进行配置:

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

Remote Machines

登陆远端机器:foo-user, bar.mit.edu-远端机器地址/域名

ssh foo@bar.mit.edu


Executing commands

​ssh foobar@server ls | grep PATTERN​​ 会在本地查询远端 ​​ls​​ 的输出。

​ls | ssh foobar@server grep PATTERN​​ 会在远端对本地 ​​ls​​ 输出的结果进行查询。

Copying files over 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​​;
  • ​rsync​​ 对 ​​scp​​ 进行了改进,它可以检测本地和远端的文件以防止重复拷贝。它还可以提供一些诸如符号连接、权限管理等精心打磨的功能。甚至还可以基于 ​​--partial​​标记实现断点续传。​​rsync​​ 的语法和​​scp​​类似;