/proc/self/fd/2는 `sudo -u other_user`에서 액세스할 수 없습니다.

/proc/self/fd/2는 `sudo -u other_user`에서 액세스할 수 없습니다.

나는 종종 이것을 사용하여 tee /proc/self/fd/2stdout 및 stderr에 무언가를 표시하고 stdout에 대한 모든 출력을 유지하면서 stdout을 캡처합니다.

예를 들어 다음과 같습니다 do.sh.

STD_OUT_STR=$(CMD ARGS ... 2>&1 | tee /proc/self/fd/2)
# handle STD_OUT_STR ...
...

이것은 매우 잘 작동합니다.

예를 들어,

./do.sh

기본적으로 다음과 같이 작동합니다.

bash -c 'echo hi | tee /proc/self/fd/2'

산출

hi
hi

그러나 어느 날 나는 그것을 실행 sudo -u A_USER ./do.sh했지만 실패했습니다.

sudo -u A_USER ./do.sh'

기본적으로 다음과 같이 실행됩니다.

sudo -u A_USER bash -c 'echo hi | tee /proc/self/fd/2'

산출

tee: /proc/self/fd/2: Permission denied
hi

지금까지는 다음 해결 방법을 따라야 합니다.

sudo -u A_USER bash -c 'echo hi | tee >(cat >&2)'

나는 이것이 보안상의 이유라는 것을 이해합니다. 현재 사용자의 pty는 다른 사용자와 공유되지 않습니다.

sudo -u A_USER프로세스에 해당 pty에 대한 액세스 권한을 부여하는 옵션이 있는지 궁금합니다 .

편집: do.sh 스크립트 안에 넣어야 합니다 . 즉, do.sh 외부에 tee /proc/self/fd/2넣을 수 없으므로 도움이 되지 않습니다.tee /proc/self/fd/2sudo -u A_USER bash -c '...' | tee ...

답변1

sudo -u A_USER bash -c 'cmd | tee /dev/fd/2'

또는:

sudo -u A_USER sh -c 'cmd | tee /dev/fd/2'

bash와 관련된 내용이 없으므로 시스템에서 작동합니다.밖의리눅스나 시그윈.

그러나 대부분의 시스템에서 열기는 /dev/fd/xLinux 또는 Cygwin과 동일 dup(x)하며 해당 파일 설명자에서 열린 파일을 가리키는 "마법의" 기호 링크일 뿐이므로 파일을 여는 것은 전혀 동일하지 않습니다.>&xsh/dev/fd/x/proc/self/fd/xdup()

귀하의 경우와 같이 쓰기 위해 열 수 있는 권한이 없는 파일에서 fd 2가 열리거나 소켓으로 전혀 열 수 없을 가능성이 높습니다(일반적으로 systemdstderr이 소켓에 의해 시작된 프로세스 journald).

쓰기 권한이 있는 일반 파일이라도 해당 파일을 처음부터 열어서 잘라내기 때문에 잘못되었거나 잘못되었습니다 tee /proc/self/fd/2. tee /dev/fd/2Even tee -a /proc/self/fd/2은 잘못되었습니다(실제로는 더 좋지만). 잘림이 너무 많아 파일 끝에서 쓰기가 완료되기 때문에 stderr이 다른 방식으로 열려 있는 경우에만 작동합니다.추가의모델.

예를 들어 다음과 같습니다.

(
  echo test | tee -a /proc/self/fd/2
  echo hi >&2
) 2> file
$ cat file
hi
t

출력은 를 통해 기록 hi됩니다 .testtee

Linux/Cygwin에서 /dev/fd/x/ /proc/self/fd/x(또는 /dev/stdout, /dev/stderr) 사용은 해당 fd가 찾을 수 없는 파일(예: 파이프 또는 tty 장치)에 열려 있는 경우에만 허용되지만, 그런 경우에도 여기에서 이러한 권한 문제와 같은 문제가 발생할 수 있습니다.

tee >(cat >&2)은 쉘을 파이프에 열려 있는 어딘가로 변환하고 tee /proc/self/fd/somefd파이프 somefd는 사용자가 파이프에 작성하여 생성했기 때문에 권한 문제는 없지만 bash 쉘에서 이 작업을 수행하는 것은 여전히 ​​잘못된 것입니다. 특히 그렇지 않은 bash와 같습니다. 그 과정을 기다리세요 cat.

뒤쪽에:

(bash -c 'echo test | tee >(cat>&2)'; echo hi >&2) 2> file

때로는 다음 file이 포함되는 경우도 있습니다.

hi
tee

이전에 첫 번째 항목을 bash반환하고 cat성공적으로 작성 test하고 echo출력 했기 때문입니다 .hi

여기서는 다음과 같이 파일 대신 여러 파일 설명자를 사용하는 zsh대신 사용할 수 있습니다 .bashtee

sudo -u A_USER zsh -c 'echo hi >&1 >&2'

fd(여기서는 1/stdout)가 출력을 위해 여러 번 리디렉션되면 서비스를 수행하는 내부 프로세스로 연결되는 파이프로 리디렉션됩니다.

sudo -u A_USER zsh -c 'echo hi | tee >(cat >&2)'

이는 위의 bash 경고 없이 작동하지만 zsh에는 기능이 내장되어 있으므로 이러한 tee경고는 필요하지 않습니다.cat

zsh셸에서 호출하는 경우 USER_A 대신 호출하는 사용자가 내부 제공을 완료하도록 할 수 있습니다.

sudo -u A_USER sh -c 'echo hi' >&1 >&2

Linux/Cygwin에서 비교할 것입니다.

sudo -u A_USER sh -c 'echo hi' | tee -a /dev/fd/2

그 자체보다

sudo -u A_USER sh -c 'echo hi' | tee /dev/fd/2

(라이센스 문제도 해결했지만) 위에 언급된 이유 때문입니다.

권한 문제를 해결하기 위해 stderr를 파이프로 변환하는 솔루션은 sh(프로세스 대체를 사용할 수 없음) +를 사용하여 수동으로 수행하는 것입니다.tee

sudo sh -c '
  {
    {
      cmd |
        tee /dev/fd/2
    } 2>&1 >&3 3>&- |
      cat >&2 3>&-
  } 3>&1'

내부 명령 그룹 내에서 stderr은 cat공유되는 파이프가 되지만 stderr을 그대로 둘 cmd수도 있습니다 cmd.

sudo sh -c '
  {
    {
      cmd 3>&- |
        tee /dev/fd/3
    } 3>&1 >&4 4>&- |
      cat >&2 4>&-
  } 4>&1'

cmd | tee >(cat >&2)여기에서 cat적절한 기다림이 주어졌음 에도 불구하고 이것이 귀하의 상황에 더 가깝습니다 .

답변2

그냥 있는 그대로 달리세요 tee.

다음 명령을 고려하십시오.

$ sudo -u A_USER bash -c 'ls -l *.txt  2>&1'

표준 출력으로 텍스트 줄을 보냅니다.

tee다른 사용자로 실행할 필요가 없습니다 . 이 줄을 가지고 자신처럼 처리하십시오. sudo나중에 파이프라인에서 이러한 권한이 정말로 필요한 경우 다시 호출하세요.

$ sudo -u A_USER bash -c 'ls -l *.txt  2>&1' | tee /proc/self/fd/2 | awk '{sum += $5}  END {print sum}' 

문제가 발생하면 스크립트는 항상 파일 시스템에 쓴 다음 다른 프로세스의 텍스트 파일에 쓸 수 있습니다 cat.tail -f

텍스트 생성기는 항상 사용 가능합니다. 표준 버퍼 필요한 경우 행 버퍼링을 조정하고 결과를 즉시 표시할 수 있습니다.

관련 정보