将输出附加到文件时出现奇怪的错误
我在追加到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
我的Fortran语言是很生疏,但我认为,在默认情况下Fortran语言把每个write
作为一个单独的记录,这是导致新的线(和寻找? - 这似乎也是我的错误)。
program main
write(*,100, advance='no') 'A'
write(*,100, advance='no') 'B'
100 format (A)
end program
感谢您的回答。我添加的代码只是一个重现错误的例子。我在运行的代码中有数百次写入,并且希望以日志文件的形式存储,因此对于我来说,更改所有代码不是一个好的选择。无论如何,我尝试了你的修复,现在追加的'Run program'变成了'Ru'。 strace显示它在“AB”('write(1,“AB”,2)')上合并,但在它仍然调用'lseek(1,0,SEEK_CUR)'和'ftruncate'之后。 – Winther
我添加了来自strace的一些输出更多,如果是相关的:
如果要抑制这种行为,你正在寻找这可能是一个有点接近。我不知道要找什么(除了显而易见的),所以请让我知道如果我应该包括所有这些。 – Winther
是否将LD_PRELOAD环境变量设置为集群上的某些内容?这可能是您使用重新定义的lseek函数。 –
这可能是一个延迟相关的问题。如果你在echo和bash脚本的运行之间放置一个睡眠(10秒或者愚蠢的大的东西)会怎么样? – Ross