sudo를 사용하여 쓰기 권한이없는 위치로 출력을 리디렉션하려면 어떻게합니까?


881

우리의 개발 RedHat 리눅스 박스 중 하나에 sudo 액세스 권한을 부여 받았으며 일반적으로 쓰기 권한이없는 위치로 출력을 리디렉션 해야하는 경우가 종종 있습니다.

문제는이 고안된 예제가 작동하지 않는다는 것입니다.

sudo ls -hal /root/ > /root/test.out

나는 단지 응답을 받는다 :

-bash: /root/test.out: Permission denied

이 기능을 작동 시키려면 어떻게해야합니까?


1
chmod u + w 파일 이름 사용
Szabolcs Dombi

@DombiSzabolcs 먼저 sudo로 파일을 만든 다음 권한을 부여 하시겠습니까? 좋은 생각.
Jonathan

많은 경우에 "허가가 거부되는 이유는 무엇입니까?" 때로는 대답은 파일을 작성해야하고 root(이 경우에는 답을 읽으십시오) 매우 자주 파일을 다른 곳에서 직접 작성해야합니다.
tripleee 2018

1
이 답변으로 어려움을 겪은 후 마침내 임시 파일로 리디렉션하고 sudo를 대상으로 옮깁니다.
TingQian LI 2016 년

답변:


1232

쓰기 권한이없는 쉘이 경로 재 지정을 수행하므로 명령이 작동하지 않습니다 /root/test.out. sudo 출력의 리디렉션을 수행 하지 않습니다 .

여러 가지 솔루션이 있습니다.

  • sudo로 쉘을 실행하고 -c옵션 을 사용하여 명령을 제공하십시오 .

    sudo sh -c 'ls -hal /root/ > /root/test.out'
    
  • 명령으로 스크립트를 작성하고 sudo를 사용하여 해당 스크립트를 실행하십시오.

    #!/bin/sh
    ls -hal /root/ > /root/test.out
    

    를 실행하십시오 sudo ls.sh. Steve Bennett 's 참조임시 파일을 만들지 않으려면 답변을 .

  • 쉘을 sudo -s시작한 다음 명령을 실행하십시오.

    [nobody@so]$ sudo -s
    [root@so]# ls -hal /root/ > /root/test.out
    [root@so]# ^D
    [nobody@so]$
    
  • 사용 sudo tee( -c옵션을 사용할 때 많이 탈출 해야하는 경우 ) :

    sudo ls -hal /root/ | sudo tee /root/test.out > /dev/null
    

    가 화면에 출력되는 /dev/null것을 막으려면로 리디렉션 이 필요합니다 . 하려면 추가 하는 대신 출력 파일 (덮어 쓰는 ), 사용 또는 (마지막 하나에 고유 GNU의로 coreutils ).>>tee -atee --append

두 번째, 세 번째 및 네 번째 솔루션에 대해 Jd , Adam J. ForsterJohnathan 에게 감사드립니다 .


1
별도로 여기 STDERR 및 STDOUT을 리디렉션하는 방법을 알려주는 좋은 답이있다 : stackoverflow.com/questions/692000/...은 ... 기본적으로perl -e 'print "STDIN\n"; print STDERR "STDERR\n"; ' > >( tee stdout.log ) 2> >( tee stderr.log >&2 )
errant.info

2
셸 아웃 명령에서 변수를 사용하려면 (예 : 스크립트에서이를 사용하는 경우) 'sudo -E ...'를 수행해야합니다.
Urhixidur

3
화면에 출력을 반향시키는 것이 무해한 경우에는 티 출력을 / dev / null로 리디렉션하지 않아도됩니다. 예를 들어, 일반 명령의 출력이나 작은 텍스트 파일의 내용 만 처리 할 때.
thomasrutter

105

여기 누군가 방금 티를 제안했습니다.

sudo ls -hal /root/ | sudo tee /root/test.out > /dev/null

또한 액세스 권한이없는 디렉토리로 명령을 리디렉션하는 데 사용할 수도 있습니다. tee 프로그램은 사실상 "파일에 대한 에코"프로그램이기 때문에 작동하며 / dev / null 로의 경로 재 지정은 위의 원래 구성 예제와 동일하게 유지하기 위해 화면으로 출력하는 것도 중지하는 것입니다.


5
많은 경우에, 즉 일반 사용자가 명령을 수행 할 권한이 있고 "만"원하는 출력 파일에 쓸 수없는 경우 첫 번째 sudo(즉, 명령 자체의 경우)를 생략 할 수 있습니다.
Hagen von Eitzen

81

내가 알아 낸 속임수는

sudo ls -hal /root/ | sudo dd of=/root/test.out

16
sudo ddsudo tee /root/file > /dev/null위 의 예 보다 낫습니다 !
kristianlm

14
dd는 이상한 모호한 명령이 아닙니다. 두 블록 장치 사이에 버퍼링으로 대량의 데이터를 복사해야 할 때마다 사용됩니다. 구문은 실제로 매우 간단 dd합니다. 명령 이름이며 출력 파일이 무엇인지 of=/root/test.out알려주는 인수 dd입니다.
rhlee

14
@steve 당신이 무엇을 배울 때까지 모든 것이 '분명합니다'. of수단 출력 파일dd(주로 디스크에 이미지를 쓰기 위해) 리눅스와 OSX 모두에서 사용되는 매우 인기있는 도구입니다. 이것은 깔끔한 트릭입니다.
blockloop

12
dd아마 tee여기 와 마찬가지로 유용 합니다. 두 경우 모두 원래 의도 된 목적과 약간 다르지만 여전히 잘 알려져 있고 잘 문서화 된 목적으로 잘 알려진 공통 명령을 사용하고 있습니다. dd방대한 양의 데이터를 복사 하는 데 능숙 하지만 적은 양의 데이터는 사용하지 않습니다. 여기서 출력을 표준 출력으로 에코하지 않는 이점이 있습니다.
thomasrutter

26
당신이 단어를 입력 할 때마다 sudo dd다음 서로를, 당신은 매우 만들고 싶어 매우 있는지에 따라 인수가 올바른지 (특히 비 표준 구문을 고려). 그들은 아무것도 "디스크 구축함"이라고 부르지 않습니다 ...
ali_m

45

문제는 명령 이에서 실행 sudo되지만 리디렉션 이 사용자에서 실행 된다는 것 입니다. 이것은 쉘에 의해 수행되며 당신이 할 수있는 일은 거의 없습니다.

sudo command > /some/file.log
`-----v-----'`-------v-------'
   command       redirection

이것을 우회하는 일반적인 방법은 다음과 같습니다.

  • sudo에서 호출하는 스크립트로 명령을 래핑하십시오.

    명령 및 / 또는 로그 파일이 변경되면 스크립트에서이를 인수로 사용하도록 할 수 있습니다. 예를 들면 다음과 같습니다.

    sudo log_script command /log/file.txt
    
  • 쉘을 호출하고 명령 행을 매개 변수로 전달하십시오. -c

    이것은 특히 복합 명령 하나에 유용합니다. 예를 들면 다음과 같습니다.

    sudo bash -c "{ command1 arg; command2 arg; } > /log/file.txt"
    

23

주제에 대한 또 다른 변형 :

sudo bash <<EOF
ls -hal /root/ > /root/test.out
EOF

또는 물론 :

echo 'ls -hal /root/ > /root/test.out' | sudo bash

그들은 당신이 sudo또는 sh/에 대한 논쟁을 기억할 필요가 없다는 (작은) 장점을 가지고 있습니다.bash


18

티 옵션이 바람직한 이유에 대한 설명

출력을 작성하는 명령을 실행할 수있는 적절한 권한이 있다고 가정하면 명령의 출력을 티로 파이프하는 경우 sudo 및 티를 사용하여 티의 권한을 상승시켜 해당 파일에 쓰거나 추가 할 수 있습니다.

질문에 주어진 예에서 다음을 의미합니다.

ls -hal /root/ | sudo tee /root/test.out

몇 가지 더 실용적인 예 :

# kill off one source of annoying advertisements
echo 127.0.0.1 ad.doubleclick.net | sudo tee -a /etc/hosts

# configure eth4 to come up on boot, set IP and netmask (centos 6.4)
echo -e "ONBOOT=\"YES\"\nIPADDR=10.42.84.168\nPREFIX=24" | sudo tee -a /etc/sysconfig/network-scripts/ifcfg-eth4

이러한 각 예에서 권한이없는 명령의 출력을 가져 와서 일반적으로 루트 만 쓸 수있는 파일에 작성합니다.

출력을 생성하는 명령이 높은 권한으로 실행되지 않기 때문에 이런 식으로하는 것이 좋습니다. 여기서 중요한 것은 echo아니지만 source 명령이 완전히 신뢰할 수없는 스크립트 인 경우 중요합니다.

-a 옵션을 사용하여 >>대상 파일에 추가 (예 :)를 덮어 쓰지 않고 추가 (예 :) 할 수 있습니다 >.


죄송합니다. js3이지만 이미 제안되어 있으며 (2008 년), 두 번째로 높은 답변을 얻고 있습니다 : stackoverflow.com/a/82553/6910
Jonathan

2
네 말이 맞아, 조나단, 이것이 바람직한 옵션 인 이유를 확장하기 위해 대답을 업데이트 할 것입니다. 유용한 피드백에 감사드립니다.
jg3

17

sudo가 다음과 같이 쉘을 실행하도록하십시오.

sudo sh -c "echo foo > ~root/out"

11

이 문제를 해결하는 방법은 다음과 같습니다.

파일을 쓰거나 교체해야 할 경우 :

echo "some text" | sudo tee /path/to/file

파일에 추가해야하는 경우 :

echo "some text" | sudo tee -a /path/to/file

1
위의 답변과 어떻게 다른가요?
Jonathan

2
"실제적으로 다른"것은 아니지만 파일 교체와 추가 사이의 고유 한 사용법을 명확하게합니다.
jamadagni 2019

1
이것이 제가 치트 시트에 복사 한 답변입니다.
MortimerCat

5

스크립트 작성은 어떻습니까?

파일 이름 : myscript

#!/bin/sh

/bin/ls -lah /root > /root/test.out

# end script

그런 다음 sudo를 사용하여 스크립트를 실행하십시오.

sudo ./myscript

4

내가 이런 식으로해야 할 때마다 나는 뿌리가됩니다.

# sudo -s
# ls -hal /root/ > /root/test.out
# exit

아마도 가장 좋은 방법은 아니지만 작동합니다.


4

나는 이렇게 할 것입니다 :

sudo su -c 'ls -hal /root/ > /root/test.out'

2
쉘을 명시 적으로 지정할 필요가 없으므로 실제로 약간 깨끗해 보입니다.
Steve Bennett

1
하나의 작은 단점은 하나의 추가 프로세스 ( su)를 실행한다는 것입니다 . $ sudo su -c 'pstree -sp $$ >/dev/fd/1' init(1)───gnome-terminal(6880)───bash(6945)───sudo(401)───su(402)───bash(410)───pstree(411)
pabouk

3

죽은 말을이기는 것을 의미하지는 않지만 여기에 너무 많은 답변이 있습니다. 즉 , 화면에서 사본을 보지 않으려면 tee리디렉션 stdout해야 /dev/null합니다.

더 간단한 해결책은 cat다음과 같이 사용하는 것입니다.

sudo ls -hal /root/ | sudo bash -c "cat > /root/test.out"

리디렉션을 인용 부호 안에 넣는 방법에 주목 sudo하십시오.


이것은 잘 작동합니다. 왜 반대표가 하나 있었는지 이해할 수 없습니다. 공감.
Teemu Leisti

4
나는 그것이 훨씬 나아지지 않기 때문에 많은 사랑을 얻지 못한다고 생각합니다 sudo bash -c "ls -hal /root > /root/test.out". 티를 사용하면 쉘이 필요하지 않지만 고양이는 필요하지 않습니다.
Nick Russo

2

이것은 관련 답변을 기반으로합니다 tee. 일을 더 쉽게하기 위해 작은 스크립트를 작성하고 (나는 그것을 호출한다 suwrite) 허가 /usr/local/bin/+x받아 넣었다 .

#! /bin/sh
if [ $# = 0 ] ; then
    echo "USAGE: <command writing to stdout> | suwrite [-a] <output file 1> ..." >&2
    exit 1
fi
for arg in "$@" ; do
    if [ ${arg#/dev/} != ${arg} ] ; then
        echo "Found dangerous argument ‘$arg’. Will exit."
        exit 2
    fi
done
sudo tee "$@" > /dev/null

코드 의 USAGE 에 표시된 것처럼 출력을이 스크립트에 파이프하고 원하는 수퍼 유저가 액세스 할 수있는 파일 이름을 파이프하면됩니다 sudo.

echo test | suwrite /root/test.txt

이것은 간단한 래퍼이기 때문에 추가 할 tee수있는 tee의 -a옵션 도 허용 하며 동시에 여러 파일에 쓰기를 지원합니다.

echo test2 | suwrite -a /root/test.txt
echo test-multi | suwrite /root/test-a.txt /root/test-b.txt

또한 /dev/이 페이지의 의견 중 하나에서 언급 한 문제에 대한 장치 쓰기를 막는 간단한 보호 기능도 있습니다 .


1

어쩌면 일부 프로그램 / 경로에만 sudo 액세스 권한이 부여 되었습니까? 그런 다음 원하는 것을 할 수있는 방법이 없습니다. (어떻게 해킹하지 않는 한)

그렇지 않은 경우 bash 스크립트를 작성할 수 있습니다.

cat > myscript.sh
#!/bin/sh
ls -hal /root/ > /root/test.out 

ctrl+를 누릅니다 d.

chmod a+x myscript.sh
sudo myscript.sh

도움이 되길 바랍니다.


1
sudo at now  
at> echo test > /tmp/test.out  
at> <EOT>  
job 1 at Thu Sep 21 10:49:00 2017  

1
당신이있는 경우 sudo, 어쨌든 at유용하거나 필요하지 않습니다. sudo sh -c 'echo test >/tmp/test.out'훨씬 더 효율적이고 우아하게 똑같이 수행합니다 (그러나 여전히 root권한이 필요하지 않은 것을 실행 중이라는 결함이 여전히 있습니다 . 일반적으로 가능하면 권한있는 명령을 피해야합니다).
트리플 리
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.