TL; DR
Günlük dosyanızı ekleme modunda açın:
cmd >> log
Ardından, güvenle aşağıdakileri kesebilirsiniz:
: > log
ayrıntılar
Bourne benzeri bir kabukla, bir dosyanın yazmaya açık olmasının 3 ana yolu vardır. In salt ( >), okuma + yazma ( <>) veya ekleme (ve salt, >>) modu.
İlk ikisinde, çekirdek, sizin açtığınız pozisyonu hatırlar (sizin, yani, açtığınız dosya tanımlayıcıları tarafından paylaşılan açık dosya açıklaması , dosyayı açtığınız yerden çatallayarak) dosya.
Yaptığınızda:
cmd > log
logstdout için kabuk tarafından salt yazma modunda açıktır cmd.
cmd(kabuk ve olası tüm çocuklar tarafından ortaya çıkan ilk işlem) stdout'larına yazarken , o dosyada paylaştıkları açık dosya açıklaması tarafından tutulan geçerli imleç konumuna yazın.
Örneğin, cmdbaşlangıçta yazarsa zzz, konum bayt ofset 4'te dosyaya yerleştirilir ve bir dahaki sefere cmdveya alt dosyaları dosyaya yazılır; bu, dosyanın aralıkta büyüdüğüne veya küçülmesine bakılmaksızın verilerin yazılacağı yerdir .
Dosya daraltılmışsa, örneğin bir dosya ile kesilmişse
: > log
ve cmdyazıyor xx, bu xxoffset de yazılır 4ve ilk 3 karakter boş karakterlerin yerini alacaktır.
$ exec 3> log # open file on fd 3.
$ printf zzz >&3
$ od -c log
0000000 z z z
0000003
$ printf aaaa >> log # other open file description -> different cursor
$ od -c log
0000000 z z z a a a a
0000007
$ printf bb >&3 # still write at the original position
$ od -c log
0000000 z z z b b a a
0000007
$ : > log
$ wc log
0 0 0 log
$ printf x >&3
$ od -c log
0000000 \0 \0 \0 \0 \0 x
0000006
Bu, yalnızca yazma modunda açık olan (ve okuma + yazma için aynı olan ) bir dosyayı kesmiş gibi kesemeyeceğiniz anlamına gelir, dosya açıklayıcıları dosyada açık olan işlemler, dosyanın başında NUL karakterleri bırakacaktır dosyası (OS / X hariç olanlar genellikle diskte yer kaplamazlar, seyrek dosyalar olurlar).
Bunun yerine (ve çoğu uygulamanın günlük dosyalarına yazarken bunu yaptığını fark edersiniz), dosyayı ekleme modunda açmalısınız :
cmd >> log
veya
: > log && cmd >> log
boş bir dosyaya başlamak istiyorsanız.
Ekleme modunda, son yazma işleminin nerede olduğuna bakılmaksızın tüm yazma işlemleri dosyanın sonunda yapılır:
$ exec 4>> log
$ printf aa >&4
$ printf x >> log
$ printf bb >&4
$ od -c log
0000000 a a x b b
0000005
$ : > log
$ printf cc >&4
$ od -c log
0000000 c c
0000002
Bu, iki işlemin dosyayı yanlışlıkla (örneğin aynı arka plan programının iki örneğini başlattıysanız) açtığı gibi daha güvenlidir, çıktıları birbirinin üzerine yazmaz.
Linux'un son sürümlerinde, şu konuma bakarak geçerli konumu ve dosya tanımlayıcısının ekleme modunda açık olup olmadığını kontrol edebilirsiniz /proc/<pid>/fdinfo/<fd>:
$ cat /proc/self/fdinfo/4
pos: 2
flags: 0102001
Veya:
$ lsof +f G -p "$$" -ad 4
COMMAND PID USER FD TYPE FILE-FLAG DEVICE SIZE/OFF NODE NAME
zsh 4870 root 4w REG 0x8401;0x0 252,18 2 59431479 /home/chazelas/log
~# lsof +f g -p "$$" -ad 4
COMMAND PID USER FD TYPE FILE-FLAG DEVICE SIZE/OFF NODE NAME
zsh 4870 root 4w REG W,AP,LG 252,18 2 59431479 /home/chazelas/log
Bu bayraklar , sistem çağrısına iletilen O ..._ bayraklarına karşılık gelir open.
$ gcc -E - <<< $'#include <fcntl.h>\nO_APPEND O_WRONLY' | tail -n1
02000 01
( O_APPEND0x400 veya sekizli 02000'dir)
Kabuk en Yani >>dosyayı açar O_WRONLY|O_APPENDiken (ve 0.100.000 burada bu soruya alakalı değildir O_LARGEFILE olduğu) >olduğu O_WRONLYsadece (ve <>olduğu O_RDWRiçin).
Şunu yaparsanız:
sudo lsof -nP +f g | grep ,AP
açık dosyaları aramak için O_APPEND, sisteminizde yazmak üzere açık olan çoğu günlük dosyasını bulacaksınız.