【问题标题】:Strange bug when appending output to file将输出附加到文件时出现奇怪的错误
【发布时间】:2016-01-26 04:43:19
【问题描述】:

我在 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 导致我使用的集群出现问题似乎是合乎逻辑的,但我知道的很少它(我不知道如何解决它)所以我在这里问它。

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

这很烦人,因为为了避免它,我需要创建一个临时文件并将运行中的输出通过管道传输到此文件中,然后将原始文件与临时文件合并,以获得所需的输出到 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

【问题讨论】:

  • 如果相关,我从 strace 中添加了更多输出。我不知道要寻找什么(除了显而易见的),所以请告诉我是否应该包含所有内容。
  • LD_PRELOAD 环境变量是否设置为集群上的某个值?可能是您使用了重新定义的 lseek 函数。
  • 这可能是与延迟相关的问题。如果你在 bash 脚本中的 echo 和 run 之间设置了一个睡眠(10 秒或更长的时间)怎么办?
  • @AnthonyScemama 不,它是空的。而且我没有在我的 bashrc 中预加载任何库。

标签: linux bash append


【解决方案1】:

我的 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
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-26
  • 1970-01-01
  • 2015-12-24
  • 2020-10-19
  • 2011-01-08
  • 2014-01-20
相关资源
最近更新 更多