Neden `cat / dev / null> / var / log / messages 'ı seçtin?


77

Bu bash betiği örnek sayfasında , yazar bu betiği sunar:

# Cleanup
# Run as root, of course.

cd /var/log
cat /dev/null > messages
cat /dev/null > wtmp
echo "Log files cleaned up."

Neden cat /dev/nullbirşeyin üzerine çıktın? Burada neyin amaçlandığını anlayamıyorum (bunun while TRUE; sleep 1; elihwiçin kullanmak gibi {some busy program}mi?). Yine de yazar “Sıradışı bir şey değil” diyor.

Yanıtlar:


41

Genellikle cat /dev/null > [something]dosya içeriğini silmek istediğinizde, gerçek dosya durumuna kesin olarak sıfır kesinti riski olduğundan emin olun. Dosyanın içeriği, cat /dev/nullhenüz bulunduğu dosya tarafından silinir - var olduğu ve bulunduğu dosya sistemi tarafından bilindiği gibi - hala aynı inode numarası, sahiplik ve izinlerle orada olacaktır.

Bir günlük dosyası söz konusu olduğunda, günlük dosyasının kendisinin başka bir işlem tarafından "kullanımda" olarak işaretlenmesi olabilir. Öyleyse - örneğin rm /var/log/messages && touch /var/log/messages- diğer işlemlere zarar verebilir ve çalışan işlemlerin boğulmasına neden olabilir. Bir şekilde, bir şekilde dosyaya bağlı belirli bir inode numarasına kilitlenmiş bir işlem /var/log/messagesaniden paniğe neden olabilir ve “Hey! Ne oldu /var/log/messages! ”Dosya hala orada olsa bile. Mülkiyet ve izinlerin yanlış bir şekilde yeniden yaratılmasıyla ilgili potansiyel sorunlardan bahsetmeyin.

Dosyanın kullanım / durumundaki bu belirsizlik nedeniyle kullanımı, bir kütüğü cat /dev/null > [something]silmek isteyen ancak mevcut işlemlerin işleyişine potansiyel olarak müdahale etmek istemeyen sistem yöneticileri tarafından kullanımı tercih edilir .

Ayrıca, yazara bağladığınız sayfa bağlamında aşağıdakileri belirtir:

Burada olağandışı bir şey yoktur, sadece konsoldaki komut satırından veya bir terminal penceresinden tek tek kolayca çağrılabilen bir komut seti. Komutları bir komut dosyasına yerleştirmenin avantajları, onları tekrar tekrar yazmak zorunda kalmadan çok ötesine geçer.

Bu yüzden yazarın bahsettiği “olağandışı bir şey” söz konusu bash betiğinin ne olduğu ile ilgili olarak: Komut satırından kolayca çalıştırılabilen ancak bir metin dosyasına yerleştirilen basit bir komut dizisidir. tekrar tekrar yazmak zorunda kalmaktan kaçının.


10
jlliagre "Hayatta kalmak" için tek şey, asıl yazarın neden bunu yaptığı üzerine odaklanan sorunun bağlamıdır. Eğer "efsaneyi" reddetmekten çekinmiyorsanız, lütfen asıl yazarın kodlama yönteminin içeriğini ve bunun neden başka yöntemlerle değiştirilebileceğini düşündüğünüze dair bir perspektif sağlayan bir cevap gönderin.
JakeGould

7
@jlliagre Cyrus'un cevabı, asıl yazarın neden bu metodu kullandığı ya da arkasındaki mantığın temel sorusunu ele almaz. Bahsedilen eğitim oldukça eski ve makul şekilde kabul edildi. Yanlış değil veya sözde bir "şehir efsanesi" ne de sürdürmez. Aksine, bir kişinin kodlaması, bir kişinin kodlaması gibi. Kadar basit. Güvenilirlik veya performans üzerinde olumsuz etkisi olmayan bir stil sorunudur.
JakeGould

3
truncate -s 0aynı şeyi yapar ve daha az aptalca olur. Bununla birlikte, kabuk programcıları muhafazakar bir gruptur ve biri bu komuttan yoksun olacak kadar eski ya da kaçık sistemlerle karşılaşabilir.
Schwern

5
@ skift cat /dev/null > /foo/bardosyayı keser; echo "" > /foo/barkeser ve sonra tek bir yeni satır karakteri yazar.
David,

2
Bu yöntemin rm & touch'a göre bir başka avantajı, mülkiyet ve izinlerin muhafaza edilmesidir.
jjmontes

121

Neden birşeye / dev / null'a katılıyorsun?

Bunu, inode'u sağlam tutarken bir dosya içeriğini kesmek için yapacaksınız. Bu dosyayı okumak veya yazmak için açık olan tüm programlar, dosya boyutunun sıfıra ayarlanması gerçeğinin dışında etkilenmez.

Sık rastlanan sahte bir alternatif, dosyayı kaldırdıktan sonra yeniden oluşturmaktır:

rm file
touch file

veya benzerleri:

mv file file.old
gzip file.old
touch file

Mesele şu ki, bu yöntemler eski dosyanın silinen dosyayı silme işlemi sırasında açtıkları işlemler ile yazılmasının engellenmemesidir. Unix dosya sistemlerinin altında olmasının nedeni, bir dosyayı sildiğinizde, yalnızca adını (yolunu) içeriğinden (inode) ayırırsınız. Inode okuma veya yazma için açık olan süreçler olduğu sürece canlı tutulur.

Bu, birkaç olumsuz etkiye neden olur: Silinen bir dosyayı açmak için basit / taşınabilir bir yol olmadığından, dosya silindikten sonra yazılan günlükler kaybolur. Bir işlem silinen dosyaya yazdığı sürece, içeriği hala dosya sistemindeki alanı kullanıyordur. Bu, diski doldurduğu için dosyayı kaldırır / oluşturursanız, diskin dolu kaldığı anlamına gelir. Bu ikinci sorunu çözmenin bir yolu, günlük işlemlerini yeniden başlatmaktır, ancak kritik hizmetler ve aracı günlükler için kesin olarak kaybolacaklarını yapmak istemeyebilirsiniz. Ayrıca, oluşturduğunuz dosyanın orijinalinden aynı izinlere, mal sahibine ve gruba sahip olmama nedeniyle de yan etkileri olabilir. Bu, örneğin bir günlük analizcisinin yeni oluşturulan dosyayı okumasını veya daha da kötüsü, günlük işleminin kendi günlüklerini yazmasını engelleyebilir.

İlk yöntem, cat /dev/null > filehedefi doğru bir şekilde başarmakla birlikte, sert bir şehir efsanesine rağmen, cat /dev/nullkısmı kesinlikle hiçbir işe yaramaz. Tasarım gereği boş olan bir sahte dosyayı açar, ondan hiçbir şey okuyamaz ve sonunda çıkar. Bu komutun kullanılması, tuş vuruşlarının, baytların, sistem çağrılarının ve CPU döngülerinin israfıdır ve hiç şüphesiz daha hızlı no-op komutuyla herhangi bir işlevsel değişiklik yapılmadan :veya hatta çoğu kabukla hiçbir komut olmadan değiştirilebilir.

Ne kadar işe yaramaz cat /dev/nullolduğunu açıklamak için bir metafor deneyeyim . Diyelim ki amacınız bir bardak boşaltmak.

  • Önce ondan herhangi bir sıvıyı çıkartın. Bu yeterlidir ve tam olarak ne ( > file) yaptığı, yönlendirmelerin her zaman önce işlendiği gerçeğini verir.

  • Sonra, boş bir şişeyi ( /dev/null) seçip boş bardağa ( cat) dökün . Bu anlamsız adım ...

Bağlantılı belgenizi sonuna kadar okursanız , komut satırının gelişmiş sürümünden bu satırdaki yorumları görebilirsiniz:

    cat / dev / null> wtmp #   ':> wtmp' ve '> wtmp' aynı etkiye sahiptir.

Gerçekten de; cat /dev/nullkodda çok kötü tutuldu.

Yani Aşağıdaki kod tüm ortak kabukları (hem çalışmak anlamına gelir cshve shaileleri):

cd /var/log
: > messages
: > wtmp
echo "Log files cleaned up."

ve bunun gibi Bourne sözdizimi kullanarak tüm kabukları ile çalışacaktır ash, bash, ksh, zshbeğeni ve:

cd /var/log
> messages
> wtmp
echo "Log files cleaned up."

Bununla birlikte, eski POSIX öncesi Bourne mermilerinde, bu komutlardan herhangi birinin, cat /dev/nulldaha sonra kendisine eklenmiş hala çalışan bir kabuk betiği tarafından yazıldığı takdirde, bir dosyayı kısaltmayacağını unutmayın. Sıfır bayt bir dosya yerine, boyutu değişmeden seyrek bir dosya olacaktır. Aynı şey, eğer dosya yazmadan önceki geçerli olduğunu düşündüğü pozisyonu arayan bir süreçle yazılırsa olur.

Ayrıca, bir dosyayı kısaltmak için önerilen bazı alternatif çözümlerin kusurları olduğunu unutmayın.

  • Aşağıdakilerden ikisi de sadece işi yapmıyor. Ortaya çıkan dosya boş değil, boş bir satır içeriyor. Bu wtmpsabit genişlikli kayıtları saklamak gibi günlük dosyaları kıracak .

    echo > file
    echo "" > file
  • Bir BSD shseçeneğine dayanan bir sonraki taşınabilir değildir, POSIX yankı için izin verilen herhangi bir seçenek belirtmez, bu nedenle " -n" ile bir satır içeren bir dosyaya sahip olabilirsiniz :

    echo -n > file
  • Bu da bir System V shkaçış dizisi kullanarak taşınabilir değildir . Bazı kabuklar " \c" ile bir satır içeren bir dosya oluşturacaktır :

    echo "\c" > file
  • Bu işi yapmak için tasarlanmış bir komutu kullanıyor. Sorun kullanılamıyor truncateçünkü POSIX tarafından belirtilmeyen bu komut bir Unix / Linux sisteminden eksik olabilir.

    truncate -s 0

Son olarak, burada taşınabilir olan ve işi düzgün şekilde yapacak birkaç alternatif var:

  • Dosyaya açıkça boş bir dize basılması:

    printf "" > file
  • Daha okunaklı olmasa da trueno-op’a tamamen denk olan komutu kullanarak ::

    true > file

1
@JonathanLeffler Ben cshmutlaka belgelenmemiş olmasına rağmen tüm mevcut uygulamaların bir parçası olduğuna inanıyorum . Solaris csh kılavuz sayfasından : Null command. This command is interpreted, but performs no action.. tcshEl kitabında veya orijinal BSD'lerde de aynı şeyden bahsetmedim cshancak bu sözdizimi her zaman işe yarayabilirdi.
jlliagre

6
Yazmanın bir nedeni cat /dev/null, niyetlerinizi açık hale getirmektir.
Davidmh

1
@Davidmh Bu mantıklı olurdu, ancak ifadeniz gerçek kontrollerine karşı gelmiyor. Bu kabuk deyimini muhtemelen birkaç on yıl boyunca gözlemledim. Yazara arkasındaki gerekçeyi sorma fırsatım olduğunda, sıfır sıfır bayt enjekte etmenin etkin bir yolu olmanın, kullanmaktan ya da hiçbir şeyden daha güvenilir bir yöntem kullanmanın her zaman temelsiz teorileri oldum . Bu sayfada, kısa ve net olan Cyrus cevabı sıfır oy alırken, JakeGould'un zorlu olanı hayırsız (oylamalara bakın) zaten en az dört oy aldı. /dev/null:cat /dev/null
jlliagre

2
@jlliagre benim kabuğum hakkındaki bilgim oldukça basit, bu yüzden belki de en iyi nüfus hedefi değilim; ama çıplak >ya da :belli değil. Efsanelerin kullanımı nedeniyle yayılmasının utanç verici olduğuna katılıyorum.
Davidmh

4
@Davidmh Yönlendirmeden önce gerçekten açık bir şey istiyorsanız, printf "" > filehangisinin taşınabilir (POSIX) olduğunu ve genellikle bir kabuk yerleşimi olarak uygulananların hafif olduğunu öneririm .
Aralık'ta

6

Dosyayı sıfır boyutuna getirmek zahmetli bir yoldur.

cd /var/log
> messages
> wtmp
echo "Log files cleaned up."

Bu sözdizimi her kabukta işe yaramaz.
reinierpost

2
Doğru. Soru sadece "bash" ile etiketlendi.
Cyrus

@reinierpost Tüm Bourne tarzı mermilerde işe yarayacak, değil mi? Endişelenmeyelim csh.
Barmar

: > messagesayrıca çalışır. :ya trueda hiçbir şey basmayan ve doğru dönen komutlar için daha belirgin seçeneklerdir.
Peter Cordes

-3

Açık bir dosyayı kesmek için. Bu eşdeğerdir ve daha anlaşılırdır:

echo -n > /var/log/messages

(Newline'dan kaçınmak için -n eklendi)


3
Bu gerçekten daha anlaşılır ama maalesef eşdeğer değil. Durumdaki gibi işlevleri bile kıracak wtmp. Güncellenmiş cevabımı gör.
jlliagre

echo -n, newline'ı engeller.
bbaassssiiee

6
Kullanmak eminseniz Gerçekten olacak bash, -naksi takdirde tüm Bourne kabukları çalışması garanti edilmez.
jlliagre
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.