
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番目のバリエーションは良いようですが、そのうちの1つは機能しません。 4番目のオプションは信頼性が低いため、オプション-
として使用できます。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
シェルに入力する値がすでにある場合は、--
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
親シェルの引数は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
2つの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
"$@" $@ \$@ $@
"\$@"