Bash içindeki tüm dosya tanımlayıcılarını kapat


13

Önceden açık bir liste olmadan tüm açık dosya tanımlayıcılarını kapatmanın bir yolu var mı?


4
Hangi dosya tanımlayıcıların hepsi ? Her sürecin bir kısmı açık.
Warren Young

"Tüm açık dosya tanımlayıcıları" nedir? 0, 1 ve 2? Yoksa daha neler var? Eğer öyleyse, nereden geldiler?
U. Windl

Komut dosyası bittiğinde dosya tanımlayıcıları otomatik olarak kapanmıyor mu?
jarno

Yanıtlar:


15

Kelimenin tam anlamıyla cevaplamak için aşağıdakiler için tüm açık dosya tanımlayıcılarını kapatın bash:

for fd in $(ls /proc/$$/fd); do
  eval "exec $fd>&-"
done

Ancak bu gerçekten iyi bir fikir değildir, çünkü kabuğun girdi ve çıktı için ihtiyaç duyduğu temel dosya tanımlayıcılarını kapatacaktır. Bunu yaparsanız, çalıştırdığınız programların hiçbiri çıktılarını terminalde göstermez ( ttycihaza doğrudan yazmadıkları sürece ). Eğer testlerimde gerçeği closing stdin( exec 0>&-) sadece interaktif bir kabuk çıkmak neden olur.

Aslında yapmak isteyebileceğiniz şey, kabuğun temel işleminin bir parçası olmayan tüm dosya tanımlayıcılarını kapatmaktır. Bunlar için 0 stdin, 1 için stdoutve 2 için stderr. Bunun üzerine bazı kabuklar varsayılan olarak açık olan diğer dosya tanımlayıcılarına sahip gibi görünüyor. Olarak bash, örneğin, 255 (aynı zamanda, terminal I / O için) ve var dashI olan 10, puan /dev/ttyyerine belirli daha tty/ ptscihazın uç kullanıyor. 0, 1, 2 ve 255 dışında her şeyi kapatmak için bash:

for fd in $(ls /proc/$$/fd); do
  case "$fd" in
    0|1|2|255)
      ;;
    *)
      eval "exec $fd>&-"
      ;;
  esac
done

Ayrıca Not evalbir değişken içerdiği dosya tanımlayıcısı yönlendirme yaparken değilse, gerekli bashdeğişkeni genişletmek ancak komuta parçası bunu dikkate alacaktır (bu durumda çalışacaklarını execkomuta 0veya 1veya hangisi dosya tanıtıcı size yakın çalıştığınız).

NOT: Ayrıca ls(örneğin /proc/$$/fd/*) yerine bir glob kullanmak glob için ekstra bir dosya tanımlayıcı açmak lsgibi görünüyor , bu yüzden burada en iyi çözüm gibi görünüyor.

Güncelleme

Taşınabilirliği hakkında daha fazla bilgi için /proc/$$/fdlütfen Dosya tanımlayıcı bağlantılarının taşınabilirliği konusuna bakın . Kullanılamıyorsa /proc/$$/fd, (varsa) $(ls /proc/$$/fd)kullanarak, yerine bir damla lsofolur $(lsof -p $$ -Ff | grep f[0-9] | cut -c 2-).


/procyalnızca Linux altında kullanılabilir.
chepner

4
@ chepner /proc/PID/fdçok taşınabilir olmadığını söyleseydin haklısın . Ancak bunun /procsadece Linux altında mevcut olduğunu söylemek doğru bir ifade değildir .
Graeme

Bazı web siteleri <&-formu kullanıyor, farklı / gerekli mi?
Lorenzo Pistone

@LorenzoPistone, bir tanımlayıcıyı kapatırken yön hiçbir fark yaratmaz, bu nedenle her iki form da kullanılabilir.
Graeme

5

Bash son sürümlerinde (daha sonra 4.1 ve sonrası, 2009 yılı ve) size olabilir bir kabuk değişkeni kullanarak kapatmak için dosya tanımlayıcısı belirtin:

for fd in $(ls /proc/$$/fd/); do
    [ $fd -gt 2 ] && exec {fd}<&-
done

Özellik zaten Korn kabuğundaydı (1993'ten beri?) Ama görünüşe göre Bash'a girmesi biraz zaman aldı.


1

Geçerli kabuğun i / o / e dışındaki tüm dosya tanımlayıcılarını temizler, ancak bağımsız değişken olarak sağlananları da hariç tutar

clear_fds() {
for fd in $(compgen -G "/proc/$BASHPID/fd/*"); do
    fd=${fd/*\/}
        if [[ ! " $* " =~ " ${fd} " ]]; then
            case "$fd" in
                0|1|2|255)
                ;;
                *)
                    eval "exec $fd>&-"
                    ;;
            esac
        fi
done
}

0

Hiç "eval" olmadan başka bir yolu, formu kullanmaktır:

$ exec {var_a}>> file.txt
$ echo $var_a
10
$ ls -l /proc/self/fd/10
l-wx------ 1 0 0 64 Dec 11 18:32 /proc/self/fd/10 -> /run/user/0/tmp/file.txt
$ echo "aaaaa" >&$var_a
$ cat file.txt
aaaaa
$ exec {var_a}>&-
$ ls /proc/self/fd/10
ls: cannot access '/proc/self/fd/10': No such file or directory

Ancak bu, tüm dosya tanımlayıcılarını kapatmaz .
G-Man,

Aslında. Önceki yanıtlarda anlatıldığı gibi bir döngüde yürütmeniz gerekecek ... Sadece "eval" in burada zorunlu olmadığını ve onu açmak için aynı mantığı tutabileceğimizi göstermekti. Adam sayfaları bu konuda net değil ...
David DG

0

Hayır. Çekirdek aynı anda yalnızca bir FD'yi kapatabilir ve bash'ın FD'ler için "grup komutları" yoktur.

for fd in $(ls -1 /proc/27343/fd); do echo exec $fd">&"-; done

Testten sonra echove "testini kaldırın .

Bu, kabuğun kendisi için değil, bir komutun çalıştırılması içinse kullanabilirsiniz nohup.


2
Tarafından kullanılan dosya tanımlayıcı >&-bir parametre olamaz; yeniden yönlendirme, parametre genişletmeden önce ayrıştırılır.
chepner

1
@ chepner bugünlerde exec {fd}>&-çalışıyor.
jarno
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.