2015-10-26 128 views
3

我在追加到bash中的文件时出现了一个奇怪的错误,即使我告诉它要追加文本,文本也会被删除。将输出附加到文件时出现奇怪的错误

我有一个bash脚本,我做了以下

echo "Run program" > foo.txt 
./fortran_program >> foo.txt 

程序fortran_program(它的一个精简版,让相同的结果)是:

program main 
write(*,*) 'A' 
write(*,*) 'B' 
end program 

这应该给执行后,我在foo.txt中执行Run program AB。但是,我发现Run B,因此原始文本已被覆盖,并且不包括A

我做strace -f ./script,发现下面的输出,看起来相关:

... 
[pid 36681] open("foo.txt", O_WRONLY|O_CREAT|O_APPEND, 0666) = 3 
[pid 36681] dup2(3, 1)     = 1 
[pid 36681] close(3)     = 0 
... 
[pid 34260] write(1, " A\n", 3)   = 3 
[pid 34260] lseek(1, 0, SEEK_CUR)  = 3 
[pid 34260] ftruncate(1, 3)    = 0 
[pid 34260] write(1, " B\n", 3)   = 3 
... 

从我有限的这种理解似乎A被写入文件,然后lseek叫这使该文件只有3个字符长(与我尝试写入的第一个字符串长度相同),然后ftruncate将其截尾为3个字符(即Run),然后将B写入文件。

在C以下程序(echo "Run program" > foo.txt; ./c_program)抄录所以现在看来​​,这不只是FORTRAN相关(虽然只有ifort编译的代码提供上述错误)

#include<unistd.h> 
#include<sys/types.h> 
#include<sys/stat.h> 
#include<fcntl.h> 

int main(){ 
    int n, f; 
    f = open("foo.txt", O_WRONLY | O_CREAT | O_APPEND, 0666); 
    write(f," A\n",3); 
    n = lseek(f,0,SEEK_CUR); 
    ftruncate(f,n); 
    write(f," B\n",3); 
} 

奇怪的是,我在运行时的行为在我的笔记本电脑上面的代码它做预期的事情,并给我Run Program AB所以看起来合乎逻辑,lseek导致我使用的集群上的问题,但我知道一点(我不知道如何解决它),所以我这是在这里问的。

为什么会发生这种情况,最重要的是:有没有办法解决这个问题?

这是很烦人的,因为为了避免它,我需要做一个临时文件和管道从运行到这个输出,然后condencate与临时文件的原始文件后,以获得所需的输出foo.txt

系统规格在那里我有问题:

ifort 14.0.2 20140120 
gcc 4.4.7 20120313 
Linux cluster 2.6.32-431.29.2.el6.x86_64 #1 SMP Sun Jul 27 15:55:46 EDT 2014 x86_64 x86_64 x86_64 GNU/Linux 

,并在那里的工作

gcc 4.8.5 
Darwin laptop 13.4.0 Darwin Kernel Version 13.4.0: Sun Aug 17 19:50:11 PDT 2014; root:xnu-2422.115.4~1/RELEASE_X86_64 x86_64 
+0

我添加了来自strace的一些输出更多,如果是相关的:

如果要抑制这种行为,你正在寻找这可能是一个有点接近。我不知道要找什么(除了显而易见的),所以请让我知道如果我应该包括所有这些。 – Winther

+0

是否将LD_PRELOAD环境变量设置为集群上的某些内容?这可能是您使用重新定义的lseek函数。 –

+1

这可能是一个延迟相关的问题。如果你在echo和bash脚本的运行之间放置一个睡眠(10秒或者愚蠢的大的东西)会怎么样? – Ross

回答

0

我的Fortran语言是很生疏,但我认为,在默认情况下Fortran语言把每个write作为一个单独的记录,这是导致新的线(和寻找? - 这似乎也是我的错误)。

program main 
write(*,100, advance='no') 'A' 
write(*,100, advance='no') 'B' 
100 format (A) 
end program 
+0

感谢您的回答。我添加的代码只是一个重现错误的例子。我在运行的代码中有数百次写入,并且希望以日志文件的形式存储,因此对于我来说,更改所有代码不是一个好的选择。无论如何,我尝试了你的修复,现在追加的'Run program'变成了'Ru'。 strace显示它在“AB”('write(1,“AB”,2)')上合并,但在它仍然调用'lseek(1,0,SEEK_CUR)'和'ftruncate'之后。 – Winther