bash: /dev/stderr: 권한이 거부되었습니다.

bash: /dev/stderr: 권한이 거부되었습니다.

새 배포판으로 업그레이드한 후 bash스크립트에서 오류가 발생하기 시작했습니다.

bash: /dev/stderr: Permission denied

이전 버전에서 Bash는내부 인정이 파일 이름(그래서 이 질문은 중복되지 않습니다.이것) 그리고옳은 일을 해라(tm)그러나 이제 이 기능은 작동이 중지되었습니다. 스크립트를 다시 성공적으로 실행하려면 어떻게 해야 합니까?

스크립트를 실행하는 사용자를 그룹에 추가하려고 시도했지만 tty아무런 차이가 없었습니다(로그아웃했다가 다시 로그인한 후에도).

문제 없이 명령줄에서 이를 재현할 수 있습니다.

$ echo test > /dev/stdout
bash: /dev/stdout: Permission denied
$ echo test > /dev/stderr
bash: /dev/stderr: Permission denied
$ ls -l /dev/stdout /dev/stderr
lrwxrwxrwx 1 root root 15 May 13 02:04 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 May 13 02:04 /dev/stdout -> /proc/self/fd/1
$ ls -lL /dev/stdout /dev/stderr
crw--w---- 1 username tty 136, 1 May 13 05:01 /dev/stderr
crw--w---- 1 username tty 136, 1 May 13 05:01 /dev/stdout
$ echo $BASH_VERSION
4.2.24(1)-release

이전 시스템(Ubuntu 10.04):

$ echo $BASH_VERSION
4.1.5(1)-release

답변1

내 생각엔 이건 아닌 것 같아완전히배쉬 문제.

댓글에서 이 작업을 수행한 후 이 오류가 발생했다고 말씀하셨습니다.

sudo su username2

. 으로 로그인하면 username이것이 su문제의 원인입니다.

/dev/stdout/proc/self/fd/1, 심볼릭 링크(예: 심볼릭 링크)입니다 /dev/pts/1. /dev/pts/1는 가 소유하고 쓸 수 있는 의사 터미널입니다. username이 소유권은 username로그인 시 부여됩니다. 이렇게 하면 sudo su username2의 소유권은 /dev/pts/1변경되지 않으며 username2쓰기 권한도 없습니다.

나는 이것이 실수라고 생각한다. /dev/stdout ~해야 한다실제로 이는 표준 출력 스트림의 별칭이지만 여기서는 echo hello제대로 작동하지만 echo hello > /dev/stdout실패하는 상황을 볼 수 있습니다.

username2한 가지 해결 방법은 그룹의 구성원이 되는 것입니다 . 그러나 이렇게 하면 쓰기 권한이 tty부여됩니다.username2어느tty, 이것은 바람직하지 않을 수 있습니다.

username2또 다른 해결 방법은 을 사용하는 대신 계정에 로그인하여 가 소유한 새로 할당된 의사 터미널을 가리키는 것 su입니다 . 이는 실용적이지 않을 수 있습니다./dev/stdoutusername2

또 다른 해결 방법은 스크립트를 참조하지 않도록 수정하는 것입니다 /dev/stdout. /dev/stderr예를 들어 다음과 같습니다.

echo OUT > /dev/stdout
echo ERR > /dev/stderr

그래서:

echo OUT
echo ERR 1>&2

info bash내 시스템의 bash 문서에 그렇게 나와 있고 /dev/stdout리디렉션 /dev/stderr에 사용될 때 특별한 처리가 있음에도 불구하고 내 시스템인 Ubuntu 12.04, bash 4.2.24에서 이 현상이 나타납니다. 그러나 Bash가 이러한 이름을 특별히 처리하지 않더라도 여전히 표준 I/O 스트림에 대해 동등한 이름으로 사용되어야 합니다. (POSIX에서는 이에 대해 언급하지 않으므로 /dev/std{in,out,err}버그라고 말하기는 어렵습니다.)

이전 버전의 bash를 보면 문서에 따르면 /dev/stdout파일 존재 여부에 관계없이 et al이 특별히 취급될 것임을 암시합니다. 이 기능은 bash 2.04에 도입되었으며 NEWS해당 버전에 대한 설명서는 다음과 같습니다.

이제 리디렉션 코드는 파일 시스템에 존재하는지 여부에 관계없이 /dev/fd/N, /dev/stdin, /dev/stdout 및 /dev/stderr 등 여러 파일 이름을 구체적으로 처리합니다.

그런데 소스코드( )를 확인해보면 redir.c특별한 핸들링이 활성화되어 있는 것을 알 수 있습니다.오직기호가 정의되어 있는지 여부 HAVE_DEV_STDIN(bash가 소스에서 빌드될 때 결정됨)

내가 아는 한,아니요Bash의 배포 버전에는 이미 /dev/stdout일부 배포판에서 패치를 적용하지 않는 한 et al에 대한 무조건적인 특수 처리 기능이 있습니다.

그래서 (내가 시도하지 않은) 또 다른 해결 방법은배쉬 소스redir.c, 특수 처리가 무조건적으로 이루어지도록 수정 /dev/*하고 시스템과 함께 제공된 버전 대신 다시 빌드한 버전을 사용하십시오. 그러나 이는 과잉일 수 있습니다.

요약:

/dev/stdout나와 같은 귀하의 운영 체제는 및 에 대한 소유권과 권한을 제대로 처리하지 않습니다 /dev/stderr. 세게 때리다아마도이러한 이름은 리디렉션에서 특별히 처리되지만 실제로는 파일이 존재하지 않는 경우에만 수행됩니다. /dev/stdout언제 제대로 작동하는지 여부는 중요하지 않습니다 /dev/stderr. 이 문제는 su다른 계정을 사용하거나 한 계정에 방금 로그인한 경우 권한이 올바른 경우 에만 발생합니다 .

답변2

동일한 줄을 사용자가 그대로 볼 수 있는 콘솔(또는 리디렉션된 경우 로그 파일)로 이동하기를 원하기 때문에,그리고이를 구문 분석하는 필터에 somecommand | tee /dev/stderr | myfilter.

sudo이 문제는 사용자가 -ing 후에 내 스크립트를 실행하려고 시도할 때 발생합니다.

해결책 /dev/stderr은 쓰기 가능한지 확인하는 것입니다.

  • 관련 없는 sudo,또는
  • 표준 오류가 파일로 리디렉션되는 경우

그래서 이것이 내가 한 일입니다:

if [ -w /dev/stderr ]
then
        STDERR=/dev/stderr
else
        STDERR=/dev/tty # The only reason is that stderr is a link to console
fi
...
somecommand | tee $STDERR | myfilter

답변3

실제로 그 이유는 udev가 tty 장치에서 권한을 0620으로 구체적으로 설정하고 su는 소유권이나 권한을 변경하지 않으며 변경해서도 안 되기 때문입니다. 내 생각에는 이것이 /dev/std*를 이식할 수 없는 상황에 처하게 한다고 생각합니다.

간단한 해결책은 "mesg y"를 /etc/profile(또는 사용하고 싶은 최상위 프로필)에 넣는 것입니다. 이렇게 하면 tty 장치의 권한이 0622로 변경됩니다. 나는 이것을 별로 좋아하지 않지만 udev 규칙을 변경하는 것보다 낫습니다.

답변4

이는 이상적이지는 않지만 문제가 발생한 후 문제를 해결하려면 다음을 수행하세요.

sudo chown -v $USER `tty`

관련 정보