Linux'ta “>>” kullanırken bash dosyaları O_APPEND'ta açar mı?


38

Eğer kullanırsak, echo 1234 >> some-fileBelgelendirme çıktının eklendiğini söyler.

Tahminim, eğer bir dosya yoksa, O_CREAT yeni bir dosya yapacak. Eğer >kullanıldı, ardından O_TRUNC dosyasını varolan keser.

Durumda >>: Dosya O_WRONLY (veya O_RDWR) olarak açılacak ve sonlandırılıp yazma işlemi yapılacak mı, O_APPEND taklit edilerek mi yapılacak? Yoksa dosya O_APPEND olarak açılacak ve eklenmenin gerçekleşmesini sağlamak için çekirdeğe bırakılacak mı?

Bunu soruyorum, çünkü bir koruyucu işlem, çıktı dosyası NFS bağlama noktasından olduğunda eko tarafından eklenen bazı işaretleyicilerin üzerine yazıyor ve NFS Dokümantasyonu, O_APPEND'in sunucuda desteklenmediğini, bu nedenle istemci çekirdeğinin onu ele alması gerektiğini söylüyor. Sanırım koruyucu süreç O_APPEND kullanıyor, ancak linux'da baskı yapıldığından emin değil >>, bu yüzden soruyu burada soruyorum.


12
NFS'deki sorun O_APPENDdesteklenmiyor; Sorun taklit edilmesi. Yerel bir dosya sisteminde, açılmış aynı dosyaya yazılan birçok işlem O_APPEND asla birbirlerinin verilerinin üzerine yazılmaz; NFS'de, O_APPENDyarış öncesi olasılıkları bırakarak yazmadan önce sona ermesiyle öykünülür. NFS'de bununla ilgili hiçbir yol yok; Her paralel yazarın kendi dosyasını yazması gerekir. Bu sorunu çözmenin tek yolu, NFS sunucusundaki bir sunucu işlemini ayarlamak, günlüğe kaydedilenlerin günlüğe kaydedilmesini sağlamak |nc server portve sunucunun günlüğe gelen verileri eklemesini sağlamaktır.
Guntram Blohm,

@GuntramBlohm, +1, onay için teşekkürler. Temel olarak, öneriniz dosyaya yalnızca bir yazar işlemi kullanmaktır ve diğer tüm yazar işlemleri bu işlemden geçer.
Prem,

Pek çok iyi cevap, Hangi cevabı kabul etmem gerektiğinden emin değilim. İlk Bruce Ediger, O_APPEND'in kullanıldığını gösterdi. Sonraki Random832, bunun standartlarda verildiğini gösterdi. Sonunda, Eric Renouf kaynak kodunu aynı cevapla gösterdi. Üç perspektifin tamamı son tam resme ekler.
Prem,

6
Kısacası, NFS bir hata yüküdür ve kullanılmamalıdır.
R. ..

2
Evet, ama O_EXCL icat edildiğinde bu yolu çoktan öğrendik.
Kevin,

Yanıtlar:


60

Bunu koştum: strace -o spork.out bash -c "echo 1234 >> some-file"sorunuzu çözmek için. Bulduğum şey bu:

open("some-file", O_WRONLY|O_CREAT|O_APPEND, 0666) = 3

echoKomutu çalıştırdığım dizinde "some-file" isimli bir dosya yoktu .


50

Bu sadece Bash'te yapılmaz, standart tarafından istenir.

Tekli Unix Spesifikasyonundan :

Eklenen çıktı yeniden yönlendirmesi, adı belirtilen dosya tanımlayıcısında çıktı almak için açılacak olan kelimenin genişlemesinden kaynaklanan dosyaya neden olur. Dosya, POSIX.1-2008 Sistem Arabirimleri biriminde tanımlandığı gibi open () işlevinin O_APPEND bayrağıyla çağrıldığı gibi açılır. Dosya yoksa, oluşturulacaktır.

Bu nedenle POSIX uyumlu herhangi bir kabuk bunu yapmalıdır. Bazı Unix sistemlerinde /bin/shPOSIX olmayan bir Bourne kabuğu olabilir (Bourne kabuğu daha önce O_APPENDicat edilmeden önce yazılmıştır ) ve mevcut POSIX kabuğu tipik olarak Solaris gibi farklı bir yoldaki konumda kshbulunacaktır .sh/usr/xpg4/bin


2
İlginç bir şekilde, bunu yapmayan bir kabuk Bourne kabuğu. Bourne kabuğu O_TRUNC olmadan açılır ve sonuna kadar lseek () s. Bunun nedeni, O_APPEND bayrağının eklenmesinden önce yazılmış olmasıdır open(). >>kendisi öncül Thomson kabuğu tarafından tanıtıldı.
Stéphane Chazelas

1
@ StéphaneChazelas Ayrıca, çeşitli versiyonlar için C kabuğu kaynağını aradım ve O_APPEND bayrağı 4.3BSD-Reno'ya kadar tanıtılmadı.
Random832

"Sanki" diyor, bu yüzden farklı şekilde uygulanamadı (ancak aynı gözlemlenebilir etkiyi üretiyor)? Standart , "sanki" davranan bir şey olan O_APPEND kullanımını gerektiriyor gibi görünmüyor .
Thomas

1
@Thomas Bu, O_APPEND için belgelenen tüm davranışları elde edeceğiniz anlamına gelir; bu, her yazının sonunda yeniden konumlandırma anlamına gelir. "Sanki", geleneksel olmayan Unix platformlarında aslında open () işlevini çağırmaktan başka bir yolla açılmasına izin vermesi amaçlanan standartlar bütünüdür.
Random832

+1, bu davranışın standartlarda olduğunu göstermek için.
Prem,

32

Kaynağa bakıldığında, O_APPEND kullanıyor. 710-713 make_cmd.csatırındaki basım 4.3.30 için şunu okuyun:

case r_appending_to:                /* >>foo */
case r_append_err_and_out:          /* &>> filename */
  temp->flags = O_APPEND | O_WRONLY | O_CREAT;
  break;

+1, kaynak kodu perspektifinden cevabı göstermek için.
Prem,

19

straceYerel bir (NFS olmayan) bir dosya sisteminde kullanıldığını araştıralım :

$ strace -eopen -- bash -c "echo foo >> /tmp/testfile000" 2>&1 | grep /tmp/testfile000
open("/tmp/testfile000", O_WRONLY|O_CREAT|O_APPEND, 0666) = 3

$ strace -eopen -- bash -c "echo foo > /tmp/testfile000" 2>&1 | grep /tmp/testfile000
open("/tmp/testfile000", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3

Diğer kabukları, yani dash, dash, shBusyBox' ve mkshaynı şekilde davranırlar.

Seçenek -e open, -e trace=openyalnızca open()sistem çağrısını izlemek anlamına gelir .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.