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. Forster 및 Johnathan 에게 감사드립니다 .


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.