![su가 제공하는 셸에 인수를 전달합니다.](https://linux55.com/image/52558/su%EA%B0%80%20%EC%A0%9C%EA%B3%B5%ED%95%98%EB%8A%94%20%EC%85%B8%EC%97%90%20%EC%9D%B8%EC%88%98%EB%A5%BC%20%EC%A0%84%EB%8B%AC%ED%95%A9%EB%8B%88%EB%8B%A4..png)
man su
설명하다:
You can use the -- argument to separate su options from the arguments
supplied to the shell.
man bash
설명하다:
-- A -- signals the end of options and disables further option
processing. Any arguments after the -- are treated as filenames
and arguments. An argument of - is equivalent to --.
이제 살펴보겠습니다:
[root ~] su - yuri -c 'echo "$*"' -- 1 2 3
2 3
[root ~] su - yuri -c 'echo "$*"' -- -- 1 2 3
2 3
[root ~] su - yuri -c 'echo "$*"' -- - 1 2 3
1 2 3
[root ~] su - yuri -c 'echo "$*"' - 1 2 3
1 2 3
내가 예상한 것(두 번째 명령의 출력이 다름):
[root ~] su - yuri -c 'echo "$*"' -- 1 2 3
2 3
[root ~] su - yuri -c 'echo "$*"' -- -- 1 2 3
1 2 3
[root ~] su - yuri -c 'echo "$*"' -- - 1 2 3
1 2 3
[root ~] su - yuri -c 'echo "$*"' - 1 2 3
1 2 3
어쩌면 큰 문제가 아닐 수도 있습니다. 그런데 거기서 무슨 일이 일어났나요? 두 번째와 세 번째 변형이 좋은 것 같지만 그 중 하나가 작동하지 않습니다. 네 번째 옵션은 신뢰성이 낮아서 옵션 -
으로 사용할 수 있습니다 .su
답변1
쉘에 제공하는 첫 번째 인수는 인수입니다 $0
(보통 이는 쉘의 이름이 됩니다). 이렇게 하면 을 제외한 모든 매개변수가 포함 echo $*
되지 $*
않습니다 $0
.
예:
# su - graeme -c 'echo "\$0 - $0"; echo "\$* - $*"' -- sh 1 2 3
$0 - sh
$* - 1 2 3
고쳐 쓰다
다음 명령을 실행합니다.
strace -f su graeme -c 'echo $0; echo "$*"' -- -- 1 2 3
추적선을 생성합니다.
[pid 9609] execve("/bin/bash", ["bash", "-c", "echo $0; echo \"$*\"", "1", "2", "3"], [/* 27 vars */] <unfinished ...>
따라서 이 경우에는 버그(또는 적어도 문서화되지 않은 동작)로 인해 추가 콘텐츠를 bash 에 전달하지 않고 su
삼키는 것처럼 보입니다. --
그러나 두 개 이상의 --
인수를 사용하지 않습니다.
# su graeme -c 'echo $0; echo "$*"' -- -- -- 1 2 3
--
1 2 3
답변2
실제로 @Graeme의 답변과 귀하의 질문은 쉘이 이러한 부작용을 처리하는 방법을 나타냅니다. 이 부작용 "$@positional $*parameters".
은 호출 시 쉘에 의해 인수에 할당되고 나중에 내장 set
유틸리티를 사용하여 할당됩니다. "$*"
각 위치를 첫 번째 문자로 분리하거나 "$IFS"
각 "$@"
위치를 참조하고 모든 위치를 결합하여 언제든지 호출할 수 있습니다."$IFS."
man set
NAME
set — set or unset options and positional parameters
SYNOPSIS
set [−abCefhmnuvx] [−o option] [argument...]
set [+abCefhmnuvx] [+o option] [argument...]
set −− [argument...]
set −o
set +o
쉘에 입력할 값이 이미 있다면 --
세 번 입력할 필요가 없습니다. 쉘 인수는 set
호출 시간뿐만 아니라 언제든지 언제든지 가능합니다.($0 및 -i 제외):
su - mikeserv -c 'set -- "$*" ; echo "$*" ;
set -- 4 5 6 ; echo "$*"' -- -- 7 8 9
7 8 9
4 5 6
이러한 모든 쉘 참조는 혼란스러울 수 있습니다. 이렇게 하면 상황이 약간 단순화됩니다.
( set -- 4 5 6
su - mikeserv 4<<-\CMD /dev/fd/4 "$@"
echo $0 "$*"
set -- "$*"
echo "$*"
set -- 7 8 9
echo "$*"
CMD
)
/dev/fd/4 4 5 6
4 5 6
7 8 9
상위 쉘에 대한 인수는 set
4, 5 및 6이며 su
호출 하위 쉘에 위치적으로 전달 됩니다.parameter "$@array".
위 명령을 어떻게 실행했는지 참고하세요 ( subshell )
. 현재 쉘 환경을 엉망으로 만들고 싶지 않았기 때문에 이 작업을 수행했습니다. 변경하고 싶지 않은 내용을 실수로 변경할 수도 있기 때문입니다.set.
리디렉션 관련:
첫째, Unix 시스템은 파일 권한, 파일 내용, 파일 속성 등의 파일과 함께 작동합니다. 어떤 방식으로든 사용하는 모든 데이터 개체는(그리고 적어도 내 생각에는 그래야 한다)파일로 처리됩니다. 리디렉션은 파일을 가리킵니다. 그 이상은 아닙니다. A는 <<HERE-DOCUMENT
파일을 인라인으로 설명한 다음 리디렉션합니다. 쉘 확장은 해석되거나 해석되지 않습니다.
질문자는 아래 댓글에서 사용자로서 이 방법을 사용하려고 하면 root
권한 오류가 발생한다고 언급했습니다. 내가 응답했을 때 나는 그에게 chown
또는 특수 chgrp
파일을 제안했지만 /dev/fd/${num}
그것이 최선의 접근 방식은 아닐 수도 있습니다. 이런 문제가 생긴 이유는 허가를 root
받았기 때문인데 read
,아니요 execute
권한. exec
전화 통화를 피하는 것만으로도 이 문제를 쉽게 해결할 수 있습니다 . /dev/fd/${num}
명령줄에서 직접 파일을 호출하는 대신 다음을 수행합니다.
su -c '. /dev/fd/'${num} ${num}<<SCRIPT
두 개의 heredoc을 사용하면 탈출에 도움이 될 수 있습니다. 각 경우에 발생하는 상황은 다음과 같습니다.
설정 없음<<HEREDOC
sh 3<<\CMD /dev/fd/3
( echo 'without set "$@" or \$@ in here-doc' ; echo
set -- '1 "2" 3' 4 "5 6"
su - mikeserv 4<<-UNQUOTED 5<<-\PREQUOTED /dev/fd/4
echo UNQUOTED; echo $0 "$*"
printf "%s\\t\\t%s\\t\\t%s\\t\\t%s\\n" $(printf "'%s' " "$@") \\
$@ '$@' "$@" '"$@"' "'$@'" \$@ '\$@' "\$@" '"\$@"'
. /dev/fd/5
UNQUOTED
echo PREQUOTED ; echo $0 "$*"
printf "%s\t\t%s\t\t%s\t\t%s\n" $(printf "'%s' " "$@") \
$@ '$@' "$@" '"$@"' \$@ '\$@' "\$@" '"\$@"'
PREQUOTED
)
CMD
산출
without set "$@" or \$@ in here-doc
UNQUOTED
/dev/fd/3 1 2 3 4 5 6
1 "2" 3 4 5 6 1
2 3 4 5
6 1 "2" 3 4 5 6 1 2 3 4 5 6 "1 "2" 3 4 5 6"
'1 2 3 4 5 6' $@ "$@"
PREQUOTED
/dev/fd/5
'' $@ "$@" $@
\$@ $@ "\$@"
설정 "$@"
하다<<HEREDOC
sh 3<<\CMD /dev/fd/3
( echo 'set "$@" and \$@ in here-doc' ; echo
set -- '1 "2" 3' 4 "5 6"
su - mikeserv 4<<-UNQUOTED 5<<-\PREQUOTED /dev/fd/4
set -- "$@" "\$@"
echo UNQUOTED; echo $0 "$*"
printf "%s\\t\\t%s\\t\\t%s\\t\\t%s\\n" $(printf "'%s' " "$@") \\
$@ '$@' "$@" '"$@"' "'$@'" \$@ '\$@' "\$@" '"\$@"'
. /dev/fd/5
UNQUOTED
set -- "$@" "\$@"
echo PREQUOTED ; echo $0 "$*"
printf "%s\t\t%s\t\t%s\t\t%s\n" $(printf "'%s' " "$@") \
$@ '$@' "$@" '"$@"' \$@ '\$@' "\$@" '"\$@"'
PREQUOTED
)
CMD
산출
set "$@" and \$@ in here-doc
UNQUOTED
/dev/fd/3 1 2 3 4 5 6
1 "2" 3 4 5 6 1
2 3 4 5
6 1 "2" 3 4 5 6 1 2 3 4 5 6 "1 "2" 3 4 5 6"
'1 2 3 4 5 6' 1 2 3 4 5 6 $@ 1 2 3 4 5 6
"$@"
PREQUOTED
/dev/fd/5 1 2 3 4 5 6 $@
'1 2 3 4
5 6' '$@' 1 2 3 4 5 6
$@ $@ 1 2 3 4 5 6 $@
"$@" $@ \$@ $@
"\$@"
설정 "$@"
등<<HEREDOC
sh 3<<\CMD /dev/fd/3
( echo 'set "$@" and \$@ AND additional parameters in here-doc' ; echo
set -- '1 "2" 3' 4 "5 6"
su - mikeserv 4<<-UNQUOTED 5<<-\PREQUOTED /dev/fd/4
set -- "$@" "\$@" '7 "8" 9' 10 "11 12"
echo UNQUOTED; echo $0 "$*"
printf "%s\\t\\t%s\\t\\t%s\\t\\t%s\\n" $(printf "'%s' " "$@") \\
$@ '$@' "$@" '"$@"' "'$@'" \$@ '\$@' "\$@" '"\$@"'
. /dev/fd/5
UNQUOTED
set -- "$@" "\$@" '13 "14" 15' 16 "17 18"
echo PREQUOTED ; echo $0 "$*"
printf "%s\t\t%s\t\t%s\t\t%s\n" $(printf "'%s' " "$@") \
$@ '$@' "$@" '"$@"' \$@ '\$@' "\$@" '"\$@"'
PREQUOTED
)
CMD
산출
set "$@" and \$@ AND additional parameters in here-doc
UNQUOTED
/dev/fd/3 1 2 3 4 5 6
1 "2" 3 4 5 6 1
2 3 4 5
6 1 "2" 3 4 5 6 1 2 3 4 5 6 "1 "2" 3 4 5 6"
'1 2 3 4 5 6' 1 2 3 4 5 6 7 "8" 9 10
11 12 $@ 1 2 3 4 5 6 7 "8" 9
10 11 12 "$@"
PREQUOTED
/dev/fd/5 1 2 3 4 5 6 7 "8" 9 10 11 12 $@ 13 "14" 15 16 17 18
'1 2 3 4
5 6' '7 "8"
9' '10' '11 12'
'$@' '13 "14" 15'
'16' '17 18' 1 2 3 4 5 6
7 "8" 9 10 11 12 $@
13 "14" 15 16 17 18 $@
1 2 3 4 5 6 7 "8" 9 10 11 12
$@ 13 "14" 15 16 17 18
"$@" $@ \$@ $@
"\$@"