Dosyanın üzerine yazılma sürecinde olup olmadığını belirleme?


25

Belirli bir dizinde tar dosyalarını arayan otomatik bir işlem (1 dakika cron betiği aracılığıyla) dağıtmam gerekiyor. Eğer bir tar dosyası bulunursa, uygun yere bir tartar kalmaz ve ardından tar dosyası silinir.

Katranlı dosyalar otomatik olarak bu sunucuya SSH üzerinden başka bir sunucudan kopyalanır. Bazı durumlarda, tar dosyaları çok fazla dosyayla birlikte oldukça büyüktür.

Çalıştırmayı umduğum sorun: tar dosyasının sunucuya kopyalanması> 1 dakika sürerse ve cron betiği her dakika çalıştırıldığında, .tar.gz dosyasını görmeye ve yapmaya çalışacak tar dosyasını hala yazma sürecinde olmasına rağmen, untar.

Bir dosyanın halihazırda yazılı olup olmadığını veya sadece kısmi bir dosya olup olmadığını sınamak için (bash komutlarıyla) herhangi bir yolu var mı?

Düşündüğüm bir alternatif, dosyanın farklı bir dosya uzantısı (gibi .tar.gz.part) olarak kopyalanması .tar.gzve aktarım tamamlandıktan sonra yeniden adlandırılmasıydı . Ancak, dosyanın önce komut satırında tam olup olmadığını belirlemenin basit bir yolu olup olmadığını anlamaya çalışacağımı düşündüm ... Herhangi bir ipucu?


2
Dosya tam olarak nasıl aktarılıyor? Örneğin rsync, aktarım sırasında geçici bir dosya adı kullanır (varsayılan olarak) ve yalnızca dosya tamamen aktarıldıktan sonra , onu asıl dosya adına yeniden adlandırır.
Piskvor

Yanıtlar:


12

Doğru yoldasınız, dosyayı yeniden adlandırmak atomik bir işlemdir, bu nedenle yükleme işleminden sonra yeniden adlandırmayı gerçekleştirmek basit, zarif ve hataya açık değildir. Aklıma gelen bir başka yaklaşım lsof | grep filename.tar.gz, dosyaya başka bir işlem tarafından erişilip erişilmediğini kontrol etmek için kullanmaktır .


7
( lsof filename.tar.gzdaha verimli ve daha doğru lsof | grep filename.tar.gz)
Rich

BTW, dosya
adının

14

En iyi bahis, lsofbir dosyanın herhangi bir işlem tarafından açılıp açılmadığını belirlemek için kullanmaktır :

#  lsof -f -- /var/log/syslog
COMMAND   PID   USER   FD   TYPE DEVICE SIZE/OFF  NODE NAME
rsyslogd 1520 syslog    1w   REG  252,2    72692 16719 /var/log/syslog

Yazılma sürecinde olup olmadığını kolayca söyleyemezsiniz, ancak yazılıyorsa açık olması GEREKİR.


Düzenleme: Önerilen çözümü uygulamaya çalışmak yerine asıl sorunu burada çözelim!

Dosyayı aktarmak için rsync kullanın:

  rsync -e ssh remote:big.tar.gz .

Bu şekilde, dosya mevcut olanın üstüne kopyalanmayacak ancak .big.tar.gz.XXXXXXaktarım tamamlanıncaya kadar geçici bir dosyaya ( ) kopyalanıp yerine taşınacaktır.


6

Biraz eski, ama cevapların çoğu sorunun tam anlamıyla özlüyor

Ama önce dosyanın komut satırında tam olup olmadığını belirlemenin bir yolu olup olmadığını anlamaya çalışacağımı düşündüm ...

Genel olarak, yok. Bunu belirlemek için yeterli bilgiye sahip değilsiniz.

Çünkü dosyanın kapalı olduğunu belirlemek, dosyanın bütün olup olmadığını belirlemekle aynı değildir . Örneğin, bağlantı transfer sırasında yarı yolda kaybedilirse, bir dosya "kapanır".

Sadece @ Alex'in cevabı bu hakkı aldı. Ve bir lsofşekilde kullandığı için bile düştü .

Dosyanın eksiksiz bir şekilde aktarılıp aktarılmadığını belirlemek için başarıyla aktarılmış daha fazla veri gerekir. Gibi:

Düşündüğüm bir alternatif, dosyanın farklı bir dosya uzantısı (gibi .tar.gz.part) olarak kopyalanması .tar.gzve aktarım tamamlandıktan sonra yeniden adlandırılmasıydı .

Bu, dosyanın tamamen ve başarıyla aktarıldığını bildirmenin mükemmel bir yoludur. Aynı dosya sisteminde kaldığınız sürece dosyaları bir dizinden diğerine de taşıyabilirsiniz. Veya gönderenin filename.donetamamlandığını bildirmek için boş bir dosya göndermesini isteyin.

Ancak, tüm yöntemler bir şekilde aktarımın başarıyla tamamlandığını bildiren gönderene güvenmek zorundadır. Çünkü sadece gönderen bu bilgiye sahip.

Bazı dosya biçimlerinde (PDF'ler gibi), dosyanın tamamlanıp tamamlanmadığını belirlemenizi sağlayan veriler bulunur. Ancak öğrenmek için dosyanın tamamını açmalı ve okumalısınız.

lsofsadece dosyanın artık açık olmadığını söyleyecektir - neden artık açılmadığını size söylemez . Dosyanın ne kadar büyük olması gerektiğini size söylemez.


1
Bunu yeterince oylayamıyorum. XY problemini burada çözmek iyi iş.
Beefster

5

Bunu yapmanın en iyi yolu incron kullanmaktır ("cron sistemini inotify "). Bir dizine inotify saat ayarlamanızı sağlar , bu da sizi dosya işlemlerinden haberdar eder. Bu durumda dir dizini bir close_write için izlemelisiniz. Bu, bir yazmadan sonra dosya kapatıldıktan sonra komutunuzu çalıştırmanıza izin verecektir.


2

Lsof, bir dosyanın hangi modda açık olduğunu algılayabilir gibi görünüyor:

lsof -f -- a_file
COMMAND   PID  USER   FD   TYPE DEVICE SIZE/OFF     NODE NAME
cat     52391 bob    1w   REG    1,2       15 19545007 a_file

1w yazdığı yeri görüyor musun? Bu, dosya tanımlayıcı numarasının 1 ve modun w veya yazma olduğu anlamına gelir.


FDTarla gösterileri 3rbenim için dosya okuma için açık olduğunda.
Sopalajo de Arrierez,

0

Kullanarak inotifywaitsonra ne olursa olsun elde edebilirsiniz - bir komut yürütmeden önce bir dosya yazma tamamlanana kadar beklemek yeteneğine sahiptir.

Aşağıdakiler sürekli olarak yeni dosyalar için bir klasör izler ve dosyaya yazma işlemi bittiğinde komutu döngüde yürütür.

WATCH_DIR=/directory/to/monitor
DEST_DIR=/x/y/z

/usr/bin/inotifywait --recursive --monitor --quiet -e moved_to -e close_write --format '%w%f' "$WATCH_DIR" | while read -r INPUT_FILE; do

mv "$0" "$DEST_DIR"

done

Daha fazla yapılandırma seçeneği için https://linux.die.net/man/1/inotifywatch adresine bakın.

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.