"sudo" 대신 "sudo -i"를 사용하면 개행 문자가 제거되는 이유는 무엇입니까? [복사]

"sudo" 대신 "sudo -i"를 사용하면 개행 문자가 제거되는 이유는 무엇입니까? [복사]

아래 예를 무엇으로 설명할 수 있으며 곡예에 대한 과도한 언급 없이 이 문제를 해결하는 방법은 무엇입니까? $n실제 문제에 주의가 산만해지는 경우를 대비하여 여러 줄의 명령 문자열을 시뮬레이션하는 데 사용하고 있습니다 .

~$ n=$'\n'; sudo -i echo "line1${n}line2${n}"
line1line2
~$

하지만

~$ n=$'\n'; sudo echo "line1${n}line2${n}"
line1
line2

~$

답변1

strace에서 실행하면 sudo -i echo $'line1\nline2'Bash가 다음과 같이 시작되는 방법이 표시됩니다.

9183  execve("/bin/bash", ["-bash", "--login", "-c", "echo line1\\\nline2\\\n"], ...

이제 strace문자열을 표시할 때 특수 문자는 백슬래시 이스케이프와 함께 표시되므로 Bash가 실제로 인수로 얻는 것은 -c셸의 경우 연속된 줄을 표시하는 후행 백슬래시이며 백슬래시와 그 뒤의 백슬래시는 개행 문자가 제거됩니다.echo line1[backslash][newline]line2[backslash][newline]

아니요 -i, 셸을 거치지 않고 직접 sudo실행합니다 .echo

9189  execve("/bin/echo", ["echo", "line1\nline2\n"], ... 

여기서는 문자 그대로 개행 문자를 받아 echo인쇄 echo합니다.


여기서 아이디어는 sudo다음 사실을 수용하기 위해 이스케이프 쉘 레이어를 추가하는 것 입니다 sh -c.하나의sudo자체적으로 명령을 다른 매개변수로 사용하는 문자열입니다 .

다음 사례를 비교해 보세요.

sudo공백을 피하십시오(이것은 명령 이름일 뿐이며 매개변수는 없습니다!).

$ sudo -i 'echo foo'
-bash: echo foo: command not found

sudo백슬래시를 이스케이프 처리하면 실제로 작동합니다(Bash는 echo백슬래시를 처리하지 않습니다).

$ sudo -i echo 'foo\bar'
foo\bar

탭과 동일:

$ sudo -i echo $'foo\tbar'
foo     bar

여기에서는 백슬래시 주위에 추가 따옴표가 없으므로 Bash는 셸 명령줄을 처리할 때 이를 제거합니다( b셸에 대한 특수 문자가 아니며 따옴표가 필요하지 않습니다. 이는 기본적으로 와 동일합니다 bash -c 'echo foo"b"ar').

$ bash -c 'echo foo\bar'
foobar

문제는 백슬래시를 사용하여 줄 바꿈을 이스케이프 처리할 수 없다는 점이며 sudo이는 고려되지 않은 것 같습니다.

아무튼, 이런 문제는 필요한 명령어를 파일에 저장하고 스크립트로 실행해 보면 더 쉽게 참고할 수 있을 것 같습니다.

답변2

명령 구조를 변경할 수 있습니다.

echo "echo \"line1${n}line2${n}\"" | sudo -i bash -s

이렇게 하면 sudo논쟁이 보이지 않으므로 문제를 일으키지 않습니다.

관련 정보