Job Control
在shell中可以使用 UNIX 提供的信号机制执行进程间通信。当一个进程接收到信号时,它会停止执行、处理该信号并基于信号传递的信息来改变其执行。信号是一种软件中断。Unix信号如下:
Killing a process
结束进程:
SIGINT
(Ctrl-C
)SIGQUIT
(Ctrl-\
)都常常用来发出和终止程序相关的请求。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 重定向处理)。
让已经在运行的进程转到后台运行:
- 可以键入
Ctrl-Z
( SIGTSTP
信号) - jobs查看所有作业
-
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> <空格>
在不同的面板排布间切换
大多数 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
类似;