将输出附加到文件时出现奇怪的错误 [英] Strange bug when appending output to file

查看:25
本文介绍了将输出附加到文件时出现奇怪的错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 bash 中附加到文件时,我有一个奇怪的错误,即使我告诉它要附加,文本也会被删除.

I have a strange bug when appending to file in bash where text gets deleted even though I’m telling it to append.

我有一个 bash 脚本,我可以在其中执行以下操作

I have a bash-script where I do the following

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

fortran_program 程序(给出相同结果的精简版)是:

The program fortran_program (a stripped down version of it that gives the same result) is:

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

这应该给我 Run program AB 在 foo.txt 执行后.但是我发现 Run B 代替,所以原始文本已被覆盖并且 A 不包括在内.

This should give me Run program AB in foo.txt after the execution. However I find Run B instead so the original text has been overwritten and A is not included.

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

I did strace -f ./script and found the following output that looks relevant:

...
[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 个字符长(相同length 作为我尝试写入的第一个字符串)然后 ftruncate 将其截断为 3 个字符(即 Run),然后将 B 写入文件.

From my very limited understanding of this it seems that A is written to the file, then lseek is called which gives that the file is only 3 characters long (same length as the first string I try to write) and then ftruncate truncates it at 3 characters (i.e. Run) and then writes B to the file.

以下 c 中的程序 (echo "Run program" > foo.txt; ./c_program) 重现了该行为,因此它似乎不仅仅与 Fortran 相关(尽管只有 ifort 编译代码给出上面的错误)

The following program in c (echo "Run program" > foo.txt; ./c_program) reproduces the behaviour so it seems it is not just fortran related (though only ifort compiled code gives the error above)

#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 导致我使用的集群存在问题,但我对此知之甚少(而且我不知道如何修复它),所以我在这里询问.

The strange thing is that when I run the code above on my laptop it does the expected thing and gives me Run Program AB so it seems logical that lseek causes the problem on the cluster I use, but I know to little of it (and I have no idea how to fix it) so I'm asking it here.

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

Why does this happen and most importantly: is there a way to fix this?

这很烦人,因为为了避免它,我需要制作一个临时文件并将运行的输出通过管道传输到该文件中,然后将原始文件与临时文件合并,以获得所需的输出到 foo.txt.

This is quite annoying since to avoid it I need to make a temp file and pipe the output from the run into this and then condencate the original file with the temp-file afterwards to get the desired output to foo.txt.

我遇到问题的系统规格:

System specifications where I have the problem:

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 视为单独的记录,这导致新台词(还有寻路? - 这对我来说也很麻烦).

My Fortran is very rusty, but I think that by default Fortran treats each write as a separate record, which is resulting in the new lines (and the seeks? - which seems a buggy to me, too).

如果你想抑制这种行为,这可能更接近你想要的:

If you want to suppress that behavior, this might be a little closer to what you're looking for:

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

这篇关于将输出附加到文件时出现奇怪的错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆