Bash'da geçici dosyalar oluşturma


150

Bh komut dosyalarında geçici dosyalar oluşturmanın nesnel olarak daha iyi yolları var mı?

Normalde sadece aklıma gelen tempfile-123 gibi her şeyi adlandırırım, çünkü komut dosyası bittiğinde silinecektir. Bunu yapmanın mevcut klasördeki olası bir tempfile-123 üzerine yazmaktan başka bir dezavantajı var mı? Yoksa daha dikkatli bir şekilde geçici bir dosya oluşturmanın herhangi bir avantajı var mı?


1
Geçici dosyaları kullanmayın. Bunun yerine geçici olarak dizinleri kullanın. Ve mktemp kullanmayın. Nedenine
ceving

17
@ceving Bu makale, en azından mktemp kabuk komutuna (mktemp kütüphane çağrısının aksine) uygulandığında yanlıştır. Mktemp dosyayı kısıtlayıcı bir umask ile oluşturduğundan, verilen saldırı sadece saldırgan saldırganla aynı hesap altında çalışıyorsa çalışır ... bu durumda oyun zaten kaybolur. Kabuk komut dosyası oluşturma dünyasındaki en iyi uygulamalar için bkz. Mywiki.wooledge.org/BashFAQ/062
Charles Duffy

Ayrıca tempfile(1)sahip sistemlerde de kullanabilirsiniz .
sonraki duyuruya kadar duraklatıldı.

Yanıtlar:


179

mktemp(1)Adam sayfa oldukça iyi açıklıyor:

Geleneksel olarak, birçok kabuk betiği pid ile birlikte programın adını sonek olarak alır ve bunu geçici dosya adı olarak kullanır. Bu tür adlandırma şeması tahmin edilebilir ve oluşturduğu yarış durumu bir saldırganın kazanması için kolaydır. Daha güvenli olsa da, yine de daha düşük bir yaklaşım, aynı adlandırma şemasını kullanarak geçici bir dizin oluşturmaktır. Bu, birinin geçici bir dosyanın alt üst edilmeyeceğini garanti etmesine rağmen, yine de basit bir hizmet reddi saldırısına izin verir. Bu nedenlerle mktemp'in kullanılması önerilir.

Bir senaryoda, mktemp gibi bir şey çağırıyorum

mydir=$(mktemp -d "${TMPDIR:-/tmp/}$(basename $0).XXXXXXXXXXXX")

hangi geçici bir dizin oluşturur ve gerçek dosyaları okunabilir ve yararlı bir şey güvenli bir şekilde adlandırabilir.

mktempstandart değildir, ancak birçok platformda bulunur. "X" ler genellikle bazı rasgeleliklere dönüştürülecek ve daha fazlası muhtemelen daha rasgele olacaktır; ancak, bazı sistemler (meşgul kutusu kül, biri için) bu rasgeleliği diğerlerinden daha önemli ölçüde sınırlar


Bu arada, geçici dosyaların güvenli bir şekilde oluşturulması, kabuk komut dosyalarından daha fazlası için önemlidir. Bu yüzden python tempfile , perl File :: Temp , ruby Tempfile vb. Vardır


1
-T seçeneği kullanımdan kaldırılmıştır: gnu.org/software/coreutils/manual/html_node/…
Tibor Vass

7
Kullanımla en çok güvenli ve en çapraz platform yolu görünüyor mktempbirlikte olduğu basenameşöyle, mktemp -dt "$(basename $0). XXXXXXXXXX". Bu olmadan kullanılırsa mktempbasename gibi bir hata alabilirsiniz : geçersiz şablon, /tmp/MOB-SAN-JOB1-183-ScriptBuildTask-7300464891856663368.sh.XXXXimlik ', dizin ayırıcı içerir .
i4niac

7
Yazım hatalarını dikkate almayın (fazladan boşluk). mktemp -dt "$(basename $0).XXXXXXXXXX"doğru yoldur.
i4niac

3
@ i4niac: OS X topraklarında bol miktarda boşluk olduğunu belirtmeniz gerekiyor$0 .mktemp -dt "$(basename "$0").XXXXXX"
Orwellophile

11
Ayrıca senaryo yürütme sonunda tempdir kaldırmak güzel olabilir:trap "rm -rf $mydir" EXIT
KumZ

43

Evet, mktemp kullanın .

Geçici dosyaları depolamak için tasarlanmış bir klasör içinde geçici bir dosya oluşturur ve size benzersiz bir ad garanti eder. Bu dosyanın adını verir:

> mktemp
/tmp/tmp.xx4mM3ePQY
>

19

Bakmak isteyebilirsiniz mktemp

Mktemp yardımcı programı, verilen dosya adı şablonunu alır ve benzersiz bir dosya adı oluşturmak için bir kısmının üzerine yazar. Şablon, kendisine eklenmiş bir dizi 'X' eklenmiş herhangi bir dosya adı olabilir, örneğin /tmp/tfile.XXXXBox. Sondaki 'X'ler', geçerli işlem numarası ve rastgele harflerin bir kombinasyonu ile değiştirilir.

Daha fazla bilgi için: man mktemp


11

Daha dikkatli bir şekilde geçici bir dosya oluşturmanın herhangi bir avantajı var mı?

Geçici dosyalar genellikle /tmpdiğer tüm kullanıcıların ve işlemlerin okuma ve yazma erişimine sahip olduğu geçici dizinde (örneğin ) oluşturulur (başka herhangi bir komut dosyası yeni dosyaları orada oluşturabilir). Bu nedenle komut dosyası, doğru izinlerle (ör. Yalnızca sahip için okuyun, bkz:) kullanmak gibi dosyaları oluşturma konusunda dikkatli olmalı help umaskve dosya adı kolayca tahmin edilememelidir (ideal olarak rastgele). Aksi takdirde, dosya adları benzersiz değilse, aynı komut dosyasıyla birden çok kez çakıştı (örn. Yarış durumu)) veya bazı saldırganlar bazı hassas bilgileri ele geçirebilir (örn. izinler çok açık olduğunda ve dosya adının tahmin edilmesi kolay olduğunda) veya dosyayı kendi kod sürümüyle oluşturabilir / değiştirebilir (ne olduğuna bağlı olarak komutları veya SQL sorgularını değiştirmek gibi) saklanmış).


Geçici dizini oluşturmak için aşağıdaki yaklaşımı kullanabilirsiniz:

TMPDIR=".${0##*/}-$$" && mkdir -v "$TMPDIR"

veya geçici dosya:

TMPFILE=".${0##*/}-$$" && touch "$TMPFILE"

Ancak yine de öngörülebilir ve güvenli sayılmaz.

Başına göre man mktempokuyabiliriz:

Geleneksel olarak, birçok kabuk betiği pid ile birlikte programın adını sonek olarak alır ve bunu geçici dosya adı olarak kullanır. Bu tür adlandırma şeması tahmin edilebilir ve oluşturduğu yarış durumu bir saldırganın kazanması için kolaydır.

Bu nedenle, güvenli olmak için, mktempbenzersiz geçici dosya veya dizin ( -d) oluşturmak için komut kullanılması önerilir .


2
tam olarak ne soruldu. Yine de mükemmel bir çözüm olabilir.
jpbochi

1
@jpbochi Soruyu cevaplamak için cevabı geliştirdim. Bunun yardımcı olup olmadığını bana bildirin.
kenorb

2
Gerçekten cevabı geliştirir. Benim oyum zaten seninti. Daha fazla oy veremezsiniz. Ben Bir öneri anlatmaya olduğunu ${0##*/}ve $$genişletmek ya da onun hakkında bazı belgelere bağlantı.
jpbochi

0

mktemp , özellikle dosyayla bir süre çalışmayı planlıyorsanız, muhtemelen en çok yönlü olanıdır.

Ayrıca , dosyaya yalnızca geçici olarak başka bir komuta girdi olarak ihtiyaç duyuyorsanız, işlem ikame operatörünü de kullanabilirsiniz <(), örneğin:

$ diff <(echo hello world) <(echo foo bar)
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.