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?
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?
Câu trả lời:
Để 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 tty
trự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 stdout
và 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 bash
Ví dụ, bạn có 255 (còn đối với thiết bị đầu cuối I / O) và trong dash
tôi có 10, mà điểm đến /dev/tty
chứ không phải là cụ tty
/ pts
thiế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 eval
là 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à bash
sẽ 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 exec
lệnh 0
hoặc 1
hoặ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 ls
có vẻ như là giải pháp tốt nhất ở đây.
Để 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/$$/fd
khô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-)
.
/proc
chỉ có sẵn trong Linux.
/proc/PID/fd
nó không phải là rất di động. Nhưng nói rằng /proc
chỉ có sẵn trong Linux không phải là một tuyên bố chính xác.
<&-
hình thức, nó có khác / cần thiết không?
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.
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
}
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
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
và "
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
.
>&-
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ố.
exec {fd}>&-
hoạt động.