bash에서 모든 파일 설명자를 닫습니다.


13

사전에 명시적인 목록없이 모든 열린 파일 디스크립터를 닫을 수있는 방법이 있습니까?


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, 2입니다 stderr. 이 외에도 일부 셸은 기본적으로 다른 파일 설명자를 열어 놓은 것 같습니다. 에서는 bash, 예를 들어, 255 (또한, 단자 I / O에 대해) 이상에서이 dash에 I가있는 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또는 어느 파일 기술자 닫으 노력하고있다).

참고 :ls (예 :) 대신 glob를 사용하면 glob에 /proc/$$/fd/*대한 추가 파일 디스크립터가 열려있는 ls것 같습니다.

최신 정보

이식성에 대한 자세한 내용 은 파일 디스크립터 링크의 이식성을/proc/$$/fd 참조하십시오 . 경우 교체에 사용할 수없는 후, 드롭 인 사용은, (즉, 사용할 수있는 경우)이 될 것이다 ./proc/$$/fd$(ls /proc/$$/fd)lsof$(lsof -p $$ -Ff | grep f[0-9] | cut -c 2-)


/procLinux에서만 사용할 수 있습니다.
chepner

4
@chepner /proc/PID/fd는 휴대 성이 좋지 않다고 말하면 맞을 것입니다 . 그러나 /procLinux에서만 사용할 수 있다고 말하는 것은 올바른 진술 이 아닙니다 .
Graeme

일부 웹 사이트는 <&-양식을 사용합니다 .
Lorenzo Pistone

@LorenzoPistone은 설명자를 닫을 때 방향이 다르지 않으므로 두 형식 중 하나를 사용할 수 있습니다.
Graeme

5

최신 버전의 Bash (4.1 이상, 2009 년 이후) 에서는 셸 변수를 사용하여 닫을 파일 설명자를 지정할 수 있습니다 .

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

이 기능은 이미 Korn 쉘에 있었지만 (1993 년 이후) Bash로 들어가는 데 시간이 걸렸습니다.


1

현재 쉘의 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-남자 '는 분석 재개 모니카'말한다

과연. 이전 답변에서 설명한 것처럼 루프에서 실행해야합니다 ... 여기에서 "eval"이 필수가 아니며 그것을 여는 것과 동일한 논리를 유지하여 닫을 수 있다는 사실을 지적했습니다. 매뉴얼 페이지는 실제로 명확하지 않습니다 ...
David DG

0

커널은 한 번에 하나의 FD 만 닫을 수 있으며 bash에는 FD에 대한 "그룹 명령"이 없습니다.

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

echo"테스트 후를 제거하십시오 .

이것이 쉘 자체가 아니라 명령이 실행되는 경우 사용할 수 있습니다 nohup.


2
로 사용되는 파일 디스크립터 >&-는 매개 변수가 될 수 없습니다. 매개 변수 확장 전에 리디렉션이 구문 분석됩니다.
chepner

1
@chepner는 요즘 exec {fd}>&-작동합니다.
jarno
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.