Geçici dosyalar gibi geçici klasörler kullanabilir miyiz
TMP=$(mktemp ... )
exec 3<>$TMP
rm $TMP
cat <&3
hangisi bu mermi çıkışından sonra otomatik olarak yok edilecek?
Geçici dosyalar gibi geçici klasörler kullanabilir miyiz
TMP=$(mktemp ... )
exec 3<>$TMP
rm $TMP
cat <&3
hangisi bu mermi çıkışından sonra otomatik olarak yok edilecek?
Yanıtlar:
Geçici bir dosya söz konusu olduğunda, sorunuzdaki örnek onu oluşturur, daha sonra dizinden bağlantısını keser ("kaybolmasını sağlar") ve komut dosyası dosya tanımlayıcıyı kapattığında (muhtemelen sonlandırıldığında), dosya tarafından alınan alan sistem tarafından geri alınabilir. Bu, C gibi dillerde geçici dosyalarla başa çıkmanın yaygın bir yoludur.
Bildiğim kadarıyla, bir dizini aynı şekilde açmak mümkün değildir, en azından dizini kullanılabilir hale getirecek hiçbir şekilde değildir.
Bir komut dosyasının sonlandırılması sırasında geçici dosyaları ve dizinleri silmenin yaygın bir yolu, bir temizleme EXIT
tuzağı kurmaktır. Aşağıda verilen kod örnekleri dosyalanmış tanımlayıcıları tamamen dengelemekten kaçınır.
tmpdir=$(mktemp -d)
tmpfile=$(mktemp)
trap 'rm -f "$tmpfile"; rm -rf "$tmpdir"' EXIT
# The rest of the script goes here.
Veya bir temizleme işlevi çağırabilirsiniz:
cleanup () {
rm -f "$tmpfile"
rm -rf "$tmpdir"
}
tmpdir=$(mktemp -d)
tmpfile=$(mktemp)
trap cleanup EXIT
# The rest of the script goes here.
EXIT
Tuzak alınması üzerine icra edilmez KILL
hiçbir temizlik sonra gerçekleştirilen olacağı aracı (tuzak edilemez) bir sinyal. Bununla birlikte, bir INT
veya TERM
sinyali nedeniyle sonlandırıldığında ( bash
veya ksh
başka kabuklarda çalışıyorsa EXIT
, trap
komut satırından sonra bu sinyalleri eklemek isteyebilirsiniz ) veya komut dosyasının sonuna gelmesi veya exit
aramak.
.
ve ..
girişleri bile yok . (Linux'ta test edildi, bunun platformlar arasında tutarlı olup olmadığını bilmiyorum.)
exec another-command
açıkça çağırıyorsa, EXIT tuzağının yürütülmediğini unutmayın .
Betiğiniz bittiğinde yürütülecek bir kabuk işlevi yazın. Aşağıdaki örnekte buna 'temizleme' diyorum ve çıkış düzeylerinde yürütülecek bir tuzak ayarlıyorum, örneğin: 0 1 2 3 6
trap cleanup 0 1 2 3 6
cleanup()
{
[ -d $TMP ] && rm -rf $TMP
}
Daha fazla bilgi için bu gönderiye bakın .
cleanup
temiz bir çıkıştan (0) önce ve SIGHUP (1), SIGINT (2), SIGQUIT (3) ve SIGABRT (6) alındığında çalışır. o olacak değil koşmak cleanup
çünkü vb SIGTERM, SIGSEGV, SIGKILL, SIGPIPE, script çıkışları Bu açıkça yetersizliği olmasıdır.
Daha sonra içindeki yolları kullanmaya çalışmamanız şartıyla içine girebilir ve kaldırabilirsiniz:
#! /bin/sh
dir=`mktemp -d`
cd "$dir"
exec 4>file 3<file
rm -fr "$dir"
echo yes >&4 # OK
cat <&3 # OK
cat file # FAIL
echo yes > file # FAIL
Kontrol etmedim, ancak C dosyasında artık var olmayan bir dizinde openat (2) kullanırken aynı sorun büyük olasılıkla aynıdır.
Kök iseniz ve Linux'taysanız, ayrı bir ad alanı ile ve mount -t tmpfs tmpfs /dir
içinde oynayabilirsiniz .
Komut dosyanız kirli bir çıkışa zorlanırsa (örn. SIGKILL ile) standart yanıtlar (EXIT üzerinde bir tuzak ayarlayın) çalışmaz; hassas verilerin etrafta asılı kalmasına neden olabilir.
Güncelleme:
İşte ad alanı yaklaşımını uygulayan küçük bir yardımcı program. İle derlenmelidir
cc -Wall -Os -s chtmp.c -o chtmp
ve verilen CAP_SYS_ADMIN
dosya yeteneklerini (root olarak)
setcap CAP_SYS_ADMIN+ep chtmp
Çalıştırıldığında (normal olarak) kullanıcı
./chtmp command args ...
dosya sistemi ad alanını paylaşmayacak, bir tmpfs dosya sistemini bağlayacak /proc/sysvipc
, içine girecek command
ve verilen argümanlarla çalışacaktır . command
olacak değil devralan CAP_SYS_ADMIN
yetenekleri.
Bu dosya sistemine, başlatılmayan başka bir işlemden erişilemez ve ne olursa olsun çocukları ve çocukları öldüğünde ( command
içinde oluşturulan tüm dosyalarla) sihirli bir şekilde kaybolur command
. Bunun yalnızca bağlanma ad alanını paylaşmadığına dikkat edin - command
aynı kullanıcı tarafından çalıştırılan diğer işlemler arasında zor engeller yoktur ; onlar hala aracılığıyla ya da isim alanı içinde gizlice ptrace(2)
, /proc/PID/cwd
ya da başka yöntemlerle.
"Yararsız" ın kaçırılması /proc/sysvipc
elbette aptalca, ancak alternatif, /tmp
kaldırılması veya bu küçük programı çatal ve beklemelerle büyük ölçüde karmaşıklaştırması gereken boş dizinlerle spam yapmak olurdu. Alternatif olarak, dir
örn. /mnt/chtmp
ve kurulum sırasında root tarafından oluşturulmasını sağlayın; bunu kullanıcı tarafından yapılandırılabilir yapmayın ve kullanıcının sahip olduğu bir yola ayarlamayın; bu, sizi tuzaklara ve zaman harcamaya değmeyecek diğer tüylü şeylere maruz bırakabilir.
chtmp.c
#define _GNU_SOURCE
#include <err.h>
#include <sched.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/mount.h>
int main(int argc, char **argv){
char *dir = "/proc/sysvipc"; /* LOL */
if(argc < 2 || !argv[1]) errx(1, "usage: %s prog args ...", *argv);
argv++;
if(unshare(CLONE_NEWNS)) err(1, "unshare(CLONE_NEWNS)");
/* "modern" systemd remounts all mount points MS_SHARED
see the NOTES in mount_namespaces(7); YUCK */
if(mount("none", "/", 0, MS_REC|MS_PRIVATE, 0))
err(1, "mount(/, MS_REC|MS_PRIVATE)");
if(mount("tmpfs", dir, "tmpfs", 0, 0)) err(1, "mount(tmpfs, %s)", dir);
if(chdir(dir)) err(1, "chdir %s", dir);
execvp(*argv, argv);
err(1, "execvp %s", *argv);
}
rm $PWD
iş, kabuk hala o dir. Ancak bu "klasöre" yeni dosya yerleştirilemez. Sadece & 3, & 4 dosyası ile okuma / yazma yapabilirsiniz. Yani bu hala "geçici dosya", "geçici klasör" değil.
Belirli bir mermiye mi ihtiyacınız var?
Zsh bir seçenekse, lütfen okuyun zshexpn(1)
:
<(...) yerine = (...) kullanılırsa, bağımsız değişken olarak iletilen dosya, liste işleminin çıktısını içeren geçici bir dosyanın adı olur. Bu , girdi dosyasında
lseek
(bkz.lseek(2)
) Olmasını bekleyen bir program için <formu yerine kullanılabilir .[...]
Başka bir sorun, ikame içeren bir komutun bulunduğu yerde
&!
veya&|
sonunda görünen durum da dahil olmak üzere, geçici bir dosya gerektiren bir işin kabuk tarafından reddedildiği her zaman ortaya çıkar . Bu durumda, kabuk artık işin belleğine sahip olmadığından geçici dosya temizlenmez. Geçici bir çözüm, örneğin bir alt kabuk kullanmaktır.(mycmd =(myoutput)) &!
çatallı alt kabuk komutun bitmesini bekleyecek ve geçici dosyayı kaldıracaktır.
Bir işlem ikamesinin uygun bir süre boyunca devam etmesini sağlamak için genel bir çözüm, bunu anonim bir kabuk işlevine (işlev kapsamıyla hemen çalıştırılan bir kabuk kodu parçası) bir parametre olarak iletmektir. Örneğin, bu kod:
() { print File $1: cat $1 } =(print This be the verse)
aşağıdakine benzer bir şey çıkarır
File /tmp/zsh6nU0kS: This be the verse
Örneğin, bir dosyanın şifresini çözmek ve daha sonra alt dosya sona erdiğinde silinir geçici dosya üzerinde tüfek çalıştırmak için tüfek (ranger dosya yöneticisinin bir parçası) kullanın. (ayarlamayı unutmayın $TERMCMD
)
# ~/.config/ranger/rifle.conf
...
!ext exe, mime octet-stream$, has gpg, flag t = () { rifle -f F "$1" } =(gpg -dq "$1")