su가 제공하는 셸에 인수를 전달합니다.

su가 제공하는 셸에 인수를 전달합니다.

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

상위 쉘에 대한 인수는 set4, 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
"$@"            $@              \$@             $@
"\$@"  

관련 정보