2015-10-26 145 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