使用 Unix Shell
Unix 是生物信息学的基础计算环境,因为它的设计理念与这种不灵活、易损坏的方法截然相反。Unix shell 的设计目的是让用户通过将较小的模块化程序连接在一起,轻松构建复杂的程序。这就是 Unix 的设计理念:
Write programs that do one thing and do it well. Write programs to work together. Write programs to handle text streams, because that is a universal interface.
将标准输出重定向到文件中
为什么不能直接使用复制粘贴?
单纯的复制粘贴可能损坏原文件,生物信息学中的重要原则就是不能对原数据进行破坏,而且很多生物学数据都比较大,直接打开电脑内存可能不够,标准输出就给了我们这样的一个方法,不必一次将全部数据一口气写入到内存中,保证了安全
Unix shell 利用流简化了合并大文件等任务。使用流可以避免不必要地将大文件载入内存。相反,我们可以通过将大文件的内容打印到标准输出流和将该数据流从我们的终端重定向到我们希望保存合并结果的文件。你可能用过 cat
程序将文件内容打印到标准输出(不重定向时则打印到终端屏幕)
cat README.md
cat
还允许我们将多个文件的内容按照它们在命令参数中出现的顺序打印到标准输出流中。这实质上是将这些文件连接起来,如这里的 tb1 和 tga1 翻译序列:
cat tb1-protein.fasta tga1-protein.fasta
虽然这些文件已经连接起来,但结果并没有保存在任何地方--这些行只是打印到终端屏幕上。为了将这些连接结果保存到文件中,需要将终端屏幕上的标准输出流重定向到文件中。重定向是 Unix 中的一个重要概念,在生物信息学中也会经常用到
我们使用操作符 >
或 >>
将标准输出重定向到文件。操作符 >
将标准输出重定向到文件,并覆盖文件中的任何现有内容(请注意这一点并小心操作),而后一个操作符 >>
则追加到文件(保留内容并添加到末尾)。如果没有现存文件,这两个操作符都会先创建一个文件,然后再将输出重定向到该文件。要连接两个 FASTA 文件,我们可以像之前一样使用 cat
,但会将输出重定向到一个文件:
cat tb1-protein.fasta tga1-protein.fasta > zea-proteins.fasta
请注意,将标准输出重定向到文件时,不会有任何内容打印到终端屏幕上。在我们的示例中,整个标准输出流最终都进入了 zeaproteins.fasta
文件
重定向标准误差
由于许多程序使用标准输出流输出数据,因此需要为错误、警告和用户读取的信息设置一个单独的流。标准错误就是专门用于这一目的的数据流。与标准输出一样,标准错误默认也是指向终端的。在实际操作中,我们经常希望将标准错误流重定向到一个文件,这样信息、错误和警告就会被记录到一个文件中,以便日后检查
为了将每个流重定向到不同的文件,我们将上一节中的 >
操作符与用于重定向标准错误流的新操作符 2>
结合起来:
command > output.txt 2> error.txt
>
将标准输出 (stdout) 重定向到 output.txt
2>
将标准错误 (stderr) 重定向到 error.txt
这里的 command
指的是执行的命令
同样 2>>
的意思是追加
如果希望将标准输出和标准错误流合并到同一个文件,可以使用 &>
(在 Bash 中)或 2>&1
(在更广泛的 shell 环境中):
command > all_output.txt 2>&1
此时原数据和报错都将写入到 all_output.txt
中
使用 tail 查看错误日志
查看文件的最后 10 行(默认)
tail filename.log
指定行数
tail -n 10 filename.log
-n 10
指定显示最后 10 行
tail 10 filename.log
- 可以不使用
-n
实时监控日志
tail -f filename.log
-f
(follow):持续输出文件末尾的内容,并在文件更新时自动显示新内容。
适用于监控系统日志:
tail -f /var/log/syslog
使用标准输入重定向
command < inputfile > outputfile
在这里,inputfile
用来将指令输入给 command
,并且将输出的内容重定向到 outputfile
中
使用管道(Unix Pipe)
使用管道建立简单的程序
假设有一段DNA序列:
>sequence_1
ATGCGTACGTAGCTAGCTAGCTAGCTAGCTAGCTAGCTAGCTAGCTAGC
TACGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGA
CGTAGCTAGCTAGCTAGCTAGCTAGCTAGCTAGCTAGCTAGCTAGCTAG
ASDE
我需要筛选出其中不属于 ATCG
的碱基,便可以使用管道:
grep -v "^>" sequence_01.fasta | grep --color -i "[^ATCG]"
这段命令可以分为两段
grep -v "^>" sequence_01.fasta
首先,我们删除以 >
字符开头的 FASTA 标题行。我们的正则表达式模式是 ^>
,它匹配所有以 >
字符开头的行。在正则表达式中,圆点符号有两种含义,但在本文中,它是用来将模式锚定到行的开头。因为我们要排除以 >
开头的行,所以使用 grep
选项 -v
反转匹配行。最后,我们用管道符将标准输出转到下一条命令
grep -v "^>" sequence_01.fasta
ATGCGTACGTAGCTAGCTAGCTAGCTAGCTAGCTAGCTAGCTAGCTAGC
TACGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGA
CGTAGCTAGCTAGCTAGCTAGCTAGCTAGCTAGCTAGCTAGCTAGCTAG
ASDE
之后使用:
grep --color -i "[^ATCG]"
其次,我们要查找不属于 A、T、C 或 G 的任何字符。最简单的方法是构建一个不匹配 A、T、C 或 G 的正则表达式模式。当在括号中使用时,空格符号可以匹配任何不在括号中的字符。此外,我们使用 -i 忽略大小写,因为 a、t、c 和 g 都是有效的核苷酸(小写字符通常用于表示屏蔽重复或低复杂度序列)。最后,我们添加了 grep
的 --color
选项,以给匹配的非核苷酸字符着色
结合管道与重定向
可以结合管道与重定向,将一个程序的输出结果作为另外一个程序的输入,同时将错误信息重定向到一个指定的文件中,便于我们浏览与排查错误:
command1 input1.txt 2> command1.stderr | command2 2> command2.stderr > result.txt
有时我们可以将错误流重定向到标准输出流,这样的话我们可以使用 grep
获取到其中的错误:
command1 2>&1 | grep "error"
tee
命令
tee
将管道标准输出流转移到一个中间文件中,就像水管工的 T 型接头一样,Unix 程序 tee
将管道标准输出流的副本转移到一个中间文件,同时仍将其通过标准输出流:
program1 input.txt | tee intermediate-file.txt | program2 > results.txt
这样的话,输出的中间文件会被保存到 intermediate-file.txt
中
管理并且与进程互动
将进程置入后台
在运行的时候,可以在命令后使用 &
将进程放入后台进行运行:
grep -v "^>" sequence_01.fasta | grep --color -i "[^ATCG]" > result.txt &
[1] 16187 16188
Shell 返回的数字[1]
就是进程ID或者PID,我们可以通过这个ID来检查任务的运行状态,可以通过 jobs
来查看后台程序的运行状态
jobs
[1]+ Running program1 input.txt > results.txt
如何要将程序带回前台,可使用 fg
,这会将最新的程序带回后台,如果你想指定带回哪个工作任务,可以使用进程ID:
fg [%作业编号]
其中 %
可以省略,比如说:
fg 1
我们可以通过组合键 Control-Z
发送停止信号来暂停进程。对于我们假想的程序 1,我们可以通过以下方式来实现:
python3 long_script.py # 运行一个长时间任务
# 按下 Ctrl + Z 暂停
[1]+ Stopped python3 long_script.py
恢复任务到前台:
fg 1 # 恢复 python3 long_script.py 到前台
或者让他继续在后台运行:
bg 1 # 让 python3 long_script.py 在后台继续
终止进程
可以使用 Control + C
来终止前端进程,比如:
ping google.com # 运行中...
# 按下 Ctrl + C 终止
使用 kill
+ jobs
终止后台进程:
jobs # 查看后台作业
kill %<作业号> # 终止指定作业(如 %1)