나는 종종 이것을 사용하여 tee /proc/self/fd/2
stdout 및 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/2
sudo -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/x
Linux 또는 Cygwin과 동일 dup(x)
하며 해당 파일 설명자에서 열린 파일을 가리키는 "마법의" 기호 링크일 뿐이므로 파일을 여는 것은 전혀 동일하지 않습니다.>&x
sh
/dev/fd/x
/proc/self/fd/x
dup()
귀하의 경우와 같이 쓰기 위해 열 수 있는 권한이 없는 파일에서 fd 2가 열리거나 소켓으로 전혀 열 수 없을 가능성이 높습니다(일반적으로 systemd
stderr이 소켓에 의해 시작된 프로세스 journald
).
쓰기 권한이 있는 일반 파일이라도 해당 파일을 처음부터 열어서 잘라내기 때문에 잘못되었거나 잘못되었습니다 tee /proc/self/fd/2
. tee /dev/fd/2
Even 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
됩니다 .test
tee
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
대신 사용할 수 있습니다 .bash
tee
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
텍스트 생성기는 항상 사용 가능합니다. 표준 버퍼 필요한 경우 행 버퍼링을 조정하고 결과를 즉시 표시할 수 있습니다.