ปิดไฟล์ descriptors ทั้งหมดใน bash


13

มีวิธีปิด descriptor ไฟล์ที่เปิดทั้งหมดโดยไม่ต้องมีรายการที่ชัดเจนของพวกเขามาก่อนหรือไม่?


4
ทั้งหมดที่อธิบายไฟล์? ทุกขั้นตอนมีบางอย่างที่เปิด
Warren Young

"ตัวอธิบายไฟล์ที่เปิดทั้งหมด" คืออะไร 0, 1 และ 2? หรือคุณมีอีกมากมาย ถ้าเป็นเช่นนั้นพวกเขามาจากไหน
U. Windl

ตัวอธิบายไฟล์ไม่ถูกปิดโดยอัตโนมัติเมื่อสคริปต์เสร็จสิ้นหรือไม่
jarno

คำตอบ:


15

หากต้องการตอบอย่างแท้จริงให้ปิดตัวอธิบายไฟล์ที่เปิดอยู่ทั้งหมดสำหรับbash:

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

อย่างไรก็ตามนี่ไม่ใช่ความคิดที่ดีเพราะจะปิดตัวอธิบายไฟล์พื้นฐานที่เชลล์ต้องการสำหรับอินพุตและเอาต์พุต หากคุณทำสิ่งนี้ไม่มีโปรแกรมใดที่คุณรันจะมีเอาต์พุตของพวกเขาปรากฏขึ้นที่เครื่อง (เว้นแต่พวกเขาจะเขียนลงในttyอุปกรณ์โดยตรง) หากข้อเท็จจริงในการปิดการทดสอบของฉันstdin( exec 0>&-) เพียงแค่ทำให้เชลล์แบบโต้ตอบออก

สิ่งที่คุณอาจต้องการทำจริงๆคือการปิดตัวอธิบายไฟล์ทั้งหมดที่ไม่ได้เป็นส่วนหนึ่งของการทำงานพื้นฐานของเชลล์ เหล่านี้เป็น 0 stdin, 1 stdoutและ stderr2 ที่ด้านบนของเชลล์นี้บางเชลล์ก็ดูเหมือนว่าไฟล์ descriptors อื่น ๆ เปิดอยู่ ในbashตัวอย่างเช่นคุณมี 255 (ยังสถานี I / O) และdashผมมี 10 ซึ่งจุดที่จะต้อง/dev/ttyมากกว่าที่เฉพาะเจาะจงtty/ ptsอุปกรณ์ปลายทางจะใช้ หากต้องการปิดทุกอย่างนอกเหนือจาก 0, 1, 2 และ 255 ในbash:

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

โปรดทราบด้วยว่าevalจำเป็นต้องใช้เมื่อเปลี่ยนเส้นทางตัวอธิบายไฟล์ที่มีอยู่ในตัวแปรถ้าไม่bashจะขยายตัวแปร แต่พิจารณาว่าเป็นส่วนหนึ่งของคำสั่ง (ในกรณีนี้มันจะลองexecคำสั่ง0หรือ1คำอธิบายไฟล์ใดก็ตามที่คุณพยายามปิด)

หมายเหตุ: การใช้ glob แทนlsเช่น ( /proc/$$/fd/*) ดูเหมือนว่าจะเปิดตัวอธิบายไฟล์เพิ่มเติมสำหรับ glob ดังนั้นจึงlsเป็นทางออกที่ดีที่สุดที่นี่

ปรับปรุง

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการพกพาของ/proc/$$/fdโปรดดูPortability ของการเชื่อมโยงอธิบายไฟล์ หาก/proc/$$/fdใช้งานไม่ได้แล้วลดลงในทดแทนสำหรับ$(ls /proc/$$/fd)ใช้lsof(ถ้าที่มีอยู่) $(lsof -p $$ -Ff | grep f[0-9] | cut -c 2-)จะเป็น


/procใช้งานได้กับ Linux เท่านั้น
chepner

4
@chepner คุณพูดถูกถ้าคุณพูด/proc/PID/fdแบบพกพาไม่ได้ แต่การบอกว่า/procใช้งานได้กับ Linux เท่านั้นไม่ใช่คำสั่งที่ถูกต้อง
แกรม

บางเว็บไซต์ใช้<&-แบบฟอร์มมันแตกต่าง / จำเป็นหรือไม่?
Lorenzo Pistone

@ LorenzoPistone ทิศทางไม่สร้างความแตกต่างเมื่อปิด descriptor ดังนั้นจึงสามารถใช้แบบฟอร์มใดก็ได้
แกรม

5

ในเวอร์ชันล่าสุดของ Bash (4.1 ขึ้นไป, ปี 2009 และใหม่กว่า) คุณสามารถระบุไฟล์ descriptor เพื่อปิดโดยใช้ตัวแปรเชลล์:

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

คุณลักษณะดังกล่าวอยู่ใน Korn shell แล้ว (ตั้งแต่ปี 1993?) แต่เห็นได้ชัดว่าใช้เวลาพอสมควรในการเจาะเข้าสู่ Bash


1

ล้าง descriptor ไฟล์ทั้งหมดยกเว้น i / o / e ของเชลล์ปัจจุบัน แต่ยังไม่รวมสิ่งที่จัดเตรียมไว้เป็นอาร์กิวเมนต์

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

อีกวิธีหนึ่งโดยไม่มี "eval" เลยคือการใช้แบบฟอร์ม:

$ 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

แต่นี่ไม่ได้ปิดตัวอธิบายไฟล์ทั้งหมด
G-Man กล่าวว่า 'Reinstate Monica'

จริง คุณจะต้องดำเนินการในวงอย่างที่อธิบายไว้ในคำตอบก่อนหน้า ... มันเป็นเพียงการชี้ให้เห็นข้อเท็จจริงที่ว่า "eval" ไม่ได้บังคับที่นี่และเราสามารถเก็บตรรกะเดียวกันเพื่อปิดมันมากกว่าที่จะเปิดมัน .. . หน้าคนจริงๆไม่ชัดเจนเกี่ยวกับเรื่องนี้ ...
เดวิด DG

0

ไม่เคอร์เนลสามารถปิดได้ครั้งละหนึ่ง FD เท่านั้นและ bash ไม่มี "คำสั่งกลุ่ม" สำหรับ FDs

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

ลบechoและ"หลังจากการทดสอบ

หากนี่ไม่ใช่สำหรับเชลล์เอง แต่เพื่อให้รันคำสั่งคุณสามารถใช้งานnohupได้


2
ไฟล์ descriptor ที่ใช้โดย>&-ไม่สามารถเป็นพารามิเตอร์ การเปลี่ยนเส้นทางจะถูกแยกวิเคราะห์ก่อนการขยายพารามิเตอร์
chepner

1
@chepner exec {fd}>&-ทำงานทุกวันนี้
jarno
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.