새 배포판으로 업그레이드한 후 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/stdout
username2
또 다른 해결 방법은 스크립트를 참조하지 않도록 수정하는 것입니다 /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`