suが提供するシェルに引数を渡す


8

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

私が期待したこと(2番目のコマンドの出力は異なります):

[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

おそらくそれほど問題ではありません。しかし、そこで何が起こっているのでしょうか?2番目と3番目のバリアントは適切な方法のようですが、いずれかが機能しません。4番目のものは信頼できないようです。のオプション-として扱うことができsuます。


それは奇妙だ。私はあなたが期待する結果を正確に得ます(そして私はそれらの期待にも同意します)。つまり、2回目の呼び出しの場合、「1 2 3」が出力として得られます。bash 4.2.45ソースと宛先の両方のアカウントで使用しています。
Krzysztof Adamski 14

回答:


9

何が起こっているかというと、シェルに指定する最初の引数は$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

strace行を生成します。

[pid  9609] execve("/bin/bash", ["bash", "-c", "echo $0; echo \"$*\"", "1", "2", "3"], [/* 27 vars */] <unfinished ...>

したがって、どういうわけか、この場合、おそらくバグ(または少なくとも文書化されていない動作)が原因で、bashに渡さずsuに余分な--ものを飲み込んでいるようです。ただし、次の2つ以上の--引数がなくなることはありません。

# su graeme -c 'echo $0; echo "$*"' -- -- -- 1 2 3
--
1 2 3

私が理解していること。私はそうします:su - yuri -c 'echo "$*"' -- -- 1 2 3シェルはおそらくを取得しますが-- 1 2 3、出力のみ2 3です。それも意味がありますか?
x-yuri 14

そして、私がするときbash -c 'echo $*' -- 1 2 3、それ1 2 3は期待通りに出力します。
x-yuri 2014

@ x-yuri、更新。これはsuバグのようです。
Graeme 14

5

実際、@ 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

シェルに供給する値がすでにある場合は、--3回する必要はありません。シェルパラメータは使用可能です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}rootread executeexec/dev/fd/${num}

su -c '. /dev/fd/'${num} ${num}<<SCRIPT 

2つのヒアドキュメントを使用すると、エスケープに役立ちます。すべての場合に何が起こるかを次に示します。

設定されていません <<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
''              $@              "$@"            $@
\$@             $@              "\$@"

SET "$@"、IN<<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
"$@"            $@              \$@             $@
"\$@"  

問題は、最初のスクリプトが私に与えることです"8 9\n4 5 6\n"。私が実行しているよdebian 6bash-4.1.5su
x-yuri 2014

@ x-yuri-そして、2番目は、すべての引用の混乱を回避しますか?
mikeserv 2014

それから実行するrootと、次のようになります-su: /dev/fd/4: Permission denied。ところで、それがどういう意味か知っていますか?それ以外の場合は、ユーザーの言うとおりに出力されますが、質問には対応しません。質問は--およびの使用について-です。
x-yuri

@ x-yuriつまりchown /dev/fd/4、必要な期間だけ、またはを使用する必要があるということchgrpです。現在、テストする時間はあまりありません。しかし、それは要点を少し外れたものであり、テールエンドで引数を渡す必要がない他の場合と同様に、引用を処理するだけです。今見ますか?
mikeserv 2014

suredirectedを使用できないという問題を省略した場合stdinでも、引数を渡す方がコマンドに注入するよりも優れています。後者の場合、それらをエスケープする必要があるためです。
x-yuri 2014
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.