Đóng tất cả các mô tả tập tin trong bash


11

Có cách nào để đóng tất cả các mô tả tập tin mở, mà không có một danh sách rõ ràng về chúng trước?


4
Tất cả tập tin mô tả? Mỗi quá trình có một số mở.
Warren Young

"Tất cả các mô tả tập tin mở" là gì? 0, 1 và 2? Hay bạn có nhiều hơn nữa? Nếu vậy, họ đến từ đâu?
U. Windl

Không phải các mô tả tập tin tự động đóng khi kịch bản kết thúc?
jarno

Câu trả lời:


14

Để trả lời theo nghĩa đen, để đóng tất cả các mô tả tệp đang mở cho bash:

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

Tuy nhiên, đây thực sự không phải là một ý tưởng hay vì nó sẽ đóng các mô tả tệp cơ bản mà trình bao cần cho đầu vào và đầu ra. Nếu bạn làm điều này, không có chương trình nào bạn chạy sẽ có đầu ra của chúng được hiển thị trên thiết bị đầu cuối (trừ khi chúng ghi ttytrực tiếp vào thiết bị). Nếu thực tế trong các thử nghiệm của tôi đóng stdin( exec 0>&-) chỉ khiến một vỏ tương tác thoát ra.

Những gì bạn thực sự có thể đang tìm cách làm là để đóng tất cả các mô tả tệp không phải là một phần của hoạt động cơ bản của shell. Đây là 0 cho stdin, 1 cho stdoutvà 2 cho stderr. Trên đầu trang này, một số shell dường như cũng có các mô tả tệp khác được mở theo mặc định. Trong bashVí dụ, bạn có 255 (còn đối với thiết bị đầu cuối I / O) và trong dashtôi có 10, mà điểm đến /dev/ttychứ không phải là cụ tty/ ptsthiết bị nhà ga đang sử dụng. Để đóng mọi thứ ngoài 0, 1, 2 và 255 trong bash:

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

Cũng lưu ý rằng evallà cần thiết khi chuyển hướng mô tả tập tin chứa trong một biến, nếu không nói là bashsẽ mở rộng biến nhưng xem xét nó một phần của lệnh (trong trường hợp này nó sẽ cố gắng execlệnh 0hoặc 1hoặc bất cứ tập tin mô tả bạn đang cố gắng đóng).

LƯU Ý: Cũng sử dụng toàn cầu thay vì ls(ví dụ /proc/$$/fd/*) dường như mở một mô tả tệp bổ sung cho toàn cầu, vì vậy lscó vẻ như là giải pháp tốt nhất ở đây.

Cập nhật

Để biết thêm thông tin về tính di động của /proc/$$/fd, vui lòng xem Tính di động của các liên kết mô tả tệp . Nếu /proc/$$/fdkhông có sẵn, thì việc thay thế cho $(ls /proc/$$/fd), bằng cách sử dụng lsof(nếu có sẵn) sẽ là $(lsof -p $$ -Ff | grep f[0-9] | cut -c 2-).


/procchỉ có sẵn trong Linux.
chepner

4
@chepner bạn sẽ đúng nếu bạn nói rằng /proc/PID/fdnó không phải là rất di động. Nhưng nói rằng /procchỉ có sẵn trong Linux không phải là một tuyên bố chính xác.
Graeme

Một số trang web sử dụng các <&-hình thức, nó có khác / cần thiết không?
Lorenzo Pistone

@LorenzoPistone, hướng không tạo ra sự khác biệt khi đóng mô tả, vì vậy một trong hai hình thức có thể được sử dụng.
Graeme

5

Trong các phiên bản gần đây của Bash (4.1 trở đi, năm 2009 trở đi), bạn có thể chỉ định bộ mô tả tệp để đóng bằng biến shell:

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

Tính năng này đã có trong Korn shell (từ năm 1993?) Nhưng rõ ràng phải mất một thời gian để tìm đường đến Bash.


1

Xóa tất cả các mô tả tệp ngoại trừ i / o / e của shell hiện tại, nhưng cũng loại trừ các mô tả được cung cấp dưới dạng đối số

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

Một cách khác mà không có "eval" nào cả, là sử dụng mẫu:

$ 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

Nhưng điều này không đóng tất cả các mô tả tập tin.
G-Man nói 'Phục hồi Monica'

Thật. Bạn sẽ phải thực hiện theo một vòng lặp như được giải thích trong các câu trả lời trước đó ... Nó chỉ để chỉ ra một thực tế là "eval" không bắt buộc ở đây và chúng ta có thể giữ logic tương tự để đóng nó hơn là mở nó .. Các trang của người đàn ông thực sự không rõ ràng về điều này ...
David DG

0

Không. Hạt nhân chỉ có thể đóng một FD mỗi lần và bash không có "lệnh nhóm" cho FD.

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

Loại bỏ echo"sau khi thử nghiệm.

Nếu đây không phải là cho chính shell mà là một lệnh được chạy thì bạn có thể sử dụng nohup.


2
Bộ mô tả tập tin được sử dụng bởi >&-không thể là một tham số; chuyển hướng được phân tích cú pháp trước khi mở rộng tham số.
chepner

1
@chepner hiện nay exec {fd}>&-hoạt động.
jarno
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.