cmd
두 줄의 텍스트를 실행 하고 출력합니다.
$ cmd
foo
bar
이것을 `/long/path/x.{load,conf}에 작성해야 합니다.
이 대상에 쓰려면 수동 작업이 불가능한 수퍼유저 권한이 필요합니다.
$ echo "foo" > /long/path/x.load
$ echo "bar" > /long/path/x.conf
~처럼"명령(sudo)이 시작되고 권한을 얻기 전에 리디렉션이 완료됩니다."
이를 감안할 때 다루기 힘든 텍스트 문자열에 대한 자리 표시자 foo
이므로 bar
이를 수행하는 좋은 방법은 무엇입니까?
실제로 저는 많은 두통을 일으키지 않는 해결책을 찾고 있습니다. 이는 일련의 지침 중 한 단계를 나타내고, 설명이 필요 없는 코드를 작성하는 것도 좋겠지만 항상 가능한 모든 방법에 관심이 있습니다. 작은 일을 하기 위해.
답변1
Awk의 리디렉션 연산자는 여기서 유용합니다. 이 주제에 대한 몇 가지 변형이 있습니다.
cmd | sudo awk '{print >"/long/path/x." (NR==1 ? "load" : "conf")}'
cmd | sudo x=/long/path/x awk 'NR==1 {print >ENVIRON["x"]".load"}
NR==2 {print >ENVIRON["x"]".conf"}'
cmd | sudo awk 'FNR==1 && NR!=1 {exit} {print >ARGV[NR-1]}' - /long/path/x.{load,conf}
첫 번째는 가장 짧고 간단합니다. 각 줄은 연산자 뒤에 오는 표현식을 평가하여 결정된 파일 이름으로 인쇄됩니다 >
. 현재 줄 번호 NR
는 파일 이름을 계산하는 데 사용됩니다. 표현식의 연결은 awk의 문자열 연결 연산자입니다.
답변2
사람들은 보통 이렇게 합니다 tee
:
cmd | sudo tee /long/path/x.{load,conf}
tee
명명된 모든 출력 파일에 입력 복사본을 씁니다. 마찬가지로 exec
중괄호 확장의 인수가 생성되기 전에 리디렉션이 발생합니다. 따라서 위 코드는 제대로 작동하고 결과 파일 이름과 표준 출력을 즉시 작성해야 합니다.
tee
데이터가 복사되는 동안 터미널에 기록된 내용을 보고 싶지 않은 경우 표준 출력을 다음으로 리디렉션할 수 있습니다. /dev/null
이는 sudo
해당 리디렉션을 방해하지 않습니다.
기록된 대로 tee
출력 파일은 기록되기 전에 잘립니다. 추가하려면 -a
보류 스위치를 추가하고 tee
이름이 지정된 모든 출력 파일의 끝에 입력 데이터를 복사하면 됩니다.
물론, 각 행을 다른 위치에 쓰는 것은 약간 어렵습니다. 그러나 의식 명령을 sed
제공합니다 . w
이것을 -e
표현식 인수와 결합하면 중괄호 확장을 사용하여 전체 스크립트를 작성할 수 있습니다 sed
.
cmd | sudo sed -e'$x;/./w '/long/path/x.{load,conf}$'\n1x'
... w
첫 번째 줄을 첫 번째 매개변수 파일에 쓰고 두 번째 줄을 두 번째 매개변수 파일에 씁니다. e의 변경은 x
단순히 첫 번째 줄과 두 번째 줄 사이의 스크립트 균형을 조정하여 sed
두 줄이 한 줄당 두 파일에 기록되는 것을 방지합니다.
나는 이것을 다음과 같이 테스트했다.
printf %s\\n 1 2 |
sed -e'$x;/./w '/tmp/{1,2}$'\n$!x'
...그리고 도망쳤어요...
head /tmp/[12]
...인쇄...
==> /tmp/1 <==
1
==> /tmp/2 <==
2
답변3
명령부터 파일 설정 cmd
까지 모든 것을 스크립팅하는 솔루션을 원하는지 잘 모르겠지만 해당 파일 설정에 따라 여전히 sudo를 사용하여 수행할 수 있지만 리디렉션해야 합니다..load
.conf
스뚜드주문하다:
$ sudo sh -c "echo 'foo' > /long/path/x.load"
$ sudo sh -c "echo 'bar' > /long/path/x.conf"
여기서는 sudo
더 높은 권한을 얻은 다음 sh
셸을 실행합니다. 그러면 주어진 명령이 해석되고 해당 순간에만 리디렉션이 발생하여 권한 문제가 발생하지 않습니다.
우연히 이 스크립트를 작성해야 하는 경우 특정 요구 사항에 따라 다음과 같이 보일 수 있습니다.
cmd | {
read line
sudo sh -c "echo '$line' > /long/path/x.load"
read line
sudo sh -c "echo '$line' > /long/path/x.conf"
}