OS X, bash: açık dosya tanımlayıcılarında daha az çalışıyor, kedi çalışmıyor


10

Üzerinde çalıştığım bir bash betiğinde (Ubuntu ve OS X üzerinde çalışması gerekiyor), yüzlerce komutun çıktısını bir dosyaya yönlendirmem gerekiyor. Hepsine
eklemek yerine &>..., sadece

exec 9>&1
exec 5<>/tmp/some-file.txt
exec 1>&5

Şimdiye kadar iyi, ama tüm bu komutların yarısında, dosya tanımlayıcısını açık tutarken şimdiye kadar yazılan her şeyi okumam gerekiyor.
Şimdi, Ubuntu'da

cat /dev/fd/5

veya

tee </dev/fd/5

ancak OS X'te hiçbir şey yazdırılmaz (ve komutlar hemen çıkar).
Ancak, lessI kullanarak her iki dosyanın içeriğini görebilirsiniz.
Yukarıdaki etkiyi (her iki işletim sistemi üzerinde de çalışarak) kullanarak

less /dev/fd/5 | tee

ama bu bir hack gibi görünüyor.

Öyleyse neden OS X'te görülemeyen lessşeyleri görebiliyorsunuz cat? (Ya da tüm BSD torunları etkileniyor mu?)
Yoksa yanlış bir şey mi yapıyorum?

Yanıtlar:


13

OS X'te, Linux dışında desteklendikleri tüm sistemlerde olduğu /dev/fd/xgibi , açılış a yapmak gibidir dup(x), sonuçta elde edilen fd, fd x ile aynı açık dosya tanımına işaret eder ve özellikle dosya içinde aynı ofsete sahip olur.

Linux burada bir istisnadır. Linux'ta, fd x'de açılan dosyaya /dev/fd/xbir sembolik bağlantı /proc/self/fd/xve /proc/self/fd/xsahte bir sembolik bağlantıdır. Linux'ta open("/dev/fd/x", somemode), açıkken aynı dosyaya yepyeni bir açık dosya açıklaması alırsınız x. Elde ettiğiniz yeni fd hiçbir şekilde fd x ile ilişkili değildir. Özellikle, ofset dosyanın başlangıcında olacaktır O_APPEND(tabii ki ile açmanız dışında ) ve mod (okuma / yazma / ekleme ...) fd x'deki moddan farklı olabilir (hatta ters modda açarken borunun diğer ucu gibi fd x'de olanlardan oldukça farklı bir şey). (Bu aynı zamanda, örneğin açamadığınız soketler için işe yaramayacağı anlamına gelir () ).

Yani, Linux'ta,

exec 5<> file
echo test >&5

Fd 5'in ofseti dosyanın sonundadır. Yaparsan

cat <&5

Hiçbir şey almıyorsunuz.

Yine de yaptığınız zaman:

cat /dev/fd/5

Görüyorsunuz testçünkü catyeni bir salt okunur fd file, fd 5 ile ilgisiz hale geliyor.

Diğer sistemlerde,

cat /dev/fd/5

cat fd 5'in bir kopyası olan bir fd alır, bu yüzden hala dosyanın sonunda bir ofset ile.

Bunun nedeniyle çalışmasının lessnedeni, lessbir nedenden ötürü, lseek()dosyanın başlangıcında bu fd'yi ( lseek(1); lseek(0)dosyanın aranabilir olup olmadığını belirlemek için yapar ) olmasıdır.

Burada, muhtemelen her ikisinin de farklı ofsetleri olmasını istiyorsanız, okumak için bir fd ve yazmak için bir fd'ye sahip olmak istersiniz:

exec 5< file 9>&1 > file

Yoksa eğer hala orada dosyayı yeniden açabilir veya bir yapmanız gerekecek lseek()olarak lessyapar.

ksh93ve zshyerleşik bir lseek()operatöre sahip tek mermiler :

cat <&5 <#((0)) # ksh93
{sysseek 0; cat} <&5 # zsh, zmodload zsh/system to enable that builtin

Veya:

cat /dev/fd/5 5<#((0))  # ksh93
sysseek -u 5 0; cat /dev/fd/5 # zsh
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.