若是一个下令需要长时间在服务器上运行,那么许多时刻会用到nohup下令,这时即便远程登录ssh中止了与服务器的联系,那么在服务器上运行的下令也不会因此而被迫住手。

通常情形下,nohup与&连用,&的意思是将该下令放在后台执行。如下:

nohup example.sh &

将exmaple.sh通过&放在服务器后台运行,nohup确保了即便当前ssh远程毗邻中止,example.sh仍然能够不受影响,继续在远程服务器中运行。

最近有两个配对测序文件,需要比对到参考基因组上,通过bwa可以完成,同时由于该文件比较大,运行时间长,为了制止网络毗邻不稳定造成ssh中止,使用nohup

nohup bwa mem ref.fa read1.fq.gz read2.fq.gz > read12.sam &

将两个测序文件合并并天生sam文件。
写好下令,一个回车键按下去,“啪”一声,那就一个爽。然后不用管它,十余个小时之后,果真天生了一个很大的文件read12.sam文件。
然则,当用该sam文件天生bam文件时,提醒错误sam文件存在错误!!!【十余个小时的盘算白费了】
仔细检查了一下sam文件,发现程序运行的效果和程序运行历程中的说明输出到了同一个文件中!

1、尺度输出和尺度错误

尺度输出(standard output)即效果默认的输出地方,好比在bash中,

$ echo 'hello'
hello

在默认状态下,’hello’时输出到你的终端(terminal)上显示。
再如,通过cat下令显示一个文本文件,

$ cat hello.txt
Hello!
This is a test!

然则,若是这个文本文件在当前路径下不存在,在会输出错误:

$ cat No_exist.txt
cat: No_exist.txt: No such file or directory
这时的输出内容“cat: No_exist.txt: No such file or directory”就是尺度错误(standard error)。

2、重导向输出

默认情形下,尺度输出和尺度错误都会在终端显示。若是要将尺度输出不是输出在终端,而是输出到一个其他文件中,这个时刻就是重导向输出,可以通过“>“符号来完成。

echo 'hello' > hello.txt

将“hello”输出到hello.txt文件中,系统会新创建该文件,若是路径中存在该文件,旧的文件将会被笼罩。
还可以使用”>>”符号,这样不会笼罩旧文件,会将”hello”添加到旧文件中。
那么,这儿有一个问题,是不是所有输出到终端的内容都可以重导向输出到一个文件中?好比,若是是尺度错误,能否通过”>”输入到文件中?

$ cat No_exist.txt > output.txt
cat: No_exist.txt: No such file or directory

效果证实:不能!output.txt依旧是一个空文件,而错误内容并没有泛起在该文件中,依旧在终端显示!以是不能直接通过”>”将尺度错误输出到文件中!
那么应该怎样才能将尺度错误输出到文件中呢?

3、文件形貌符

在bash中,通常使用3个整数来示意尺度输入(0)、尺度输出(1)和尺度错误(2)。
若是要把尺度错误输出到文件中,可以使用

cat No_exist.txt 2> tt.txt

这时在tt.txt文件中就会泛起尺度错误“cat: No_exist.txt: No such file or directory”。
同样的原理,我们可以将尺度错误重导向输出为尺度输出,2>&1
好比

,

Allbet电脑版下载ALLbet6.com

欢迎进入Allbet电脑版下载(Allbet Game):www.aLLbetgame.us,欧博官网是欧博集团的官方网站。欧博官网开放Allbet注册、Allbe代理、Allbet电脑客户端、Allbet手机版下载等业务。

,
$ cat No_exist.txt 
cat: No_exist.txt: No such file or directory
$ cat No_exist.txt 2>&1
cat: No_exist.txt: No such file or directory

虽然它们在终端上输出的内容看起来没有什么区别,然则它们的身份是不一样的,第一个是以尺度错误的形式输出的,而第二个是尺度输出。我们可以通过管道符号验证一下它们的差别。

$ cat No_exist.txt | sed 's/or/and/'
cat: No_exist.txt: No such file or directory
$ cat No_exist.txt 2>&1| sed 's/or/and/'
cat: No_exist.txt: No such file and directory

现在可以看出区别了,第一个尺度错误无法通过管道符号把“or”替换成“and”,而第二个是尺度输出,可以通过管道符号,把其中的“or”替换成“and”.
同样的原理,也可以将尺度输出重导向为尺度错误“1 >2&“

那么回过头来,看最最先的那个问题,为什么nohup同时会运算效果和运算历程的形貌输出到同一个sam文件中呢?
为了简捷,用下面的代码(example.sh)重现了nohup中的错误。

#!/bin/bash

echo "this is outcome!"
sleep 1
echo "sleep for 1s" >&2
echo "this is outcome, too!"
sleep 2
echo "second sleep for 2s" >&2

其中sleep的历程形貌通过 >&2以尺度错误的形式泛起,而outcome则以尺度输出的形式输出。
正常情形下,运行:

$ ./example.sh > outcome.txt
sleep for 1s
second sleep for 2s

$ cat outcome.txt 
this is outcome!
this is outcome, too!

尺度错误直接输出到了终端中,运行效果输出到了outcome.txt中,没有任何问题。然则在nohup的情形下,这种情形就变了。
在nohup的说明中,提到“若是尺度输出是在终端,那么输出的内容将会被添加到‘nohup.out’文件中;若是尺度错误的输出是在终端,那么内容将会被重导向到尺度输出“。这就意味着,在没有特殊说明的情形下,尺度输出和尺度错误将会被重导向输出到同一个地方。如下,

$ nohup ./example.sh 
appending output to nohup.out

$ cat nohup.out 
this is outcome!
sleep for 1s
this is outcome, too!
second sleep for 2s

在nohup.txt文件中不仅泛起了我想要的运行效果,还泛起了我不想要的运行历程!这也就注释了为什么在我的sam文件中会泛起许多本不应该属于该文件的内容。
既然知道了缘故原由,那么解决问题就不难了。我们可以通过重导向输出,把运行效果和运行历程划分输出到差别的文件中。

$ nohup ./example.sh 2>stderr.log 1>outcome.txt

$ cat stderr.log 
sleep for 1s
second sleep for 2s

$ cat outcome.txt 
this is outcome!
this is outcome, too!

这样,将历程以尺度错误形式输出到stderr.log中,将效果以尺度输出形式输出到outcome.txt中。
以是本文最开头提到的下令可以改为:

nohup bwa mem ref.fa read1.fq.gz read2.fq.gz 1> read12.sam 2>read12.log &

总结

nohup在默认条件下,尺度错误和尺度输出会重导向到同一个文件中;通过文件形貌符(0,1,2)来对控制输出内容;养成优越的输出控制习惯,对尺度输出和尺度错误要区别对待。

===== THE END =====

参考资料:

https://robots.thoughtbot.com/input-output-redirection-in-the-shell#file-descriptors
https://www.brianstorti.com/understanding-shell-script-idiom-redirect/