私は次のように特定のユーザーから始めましたsu
。tmux
$ su - someuser -c tmux
ただし、これにより、次のエラーメッセージが表示されます。
tmux: need UTF-8 locale (LC_CTYPE) but have ANSI_X3.4-1968
このエラーは、LANG
環境変数が設定されていないために発生します。新しいものログインシェルこのviaは通常設定されますが、実際に使用が要求され、ログインシェルを作成しているように見えても、/etc/profile
through呼び出しはsu
使用されません。/etc/profile
su -
シェルを使用しているユーザーにはsomeuser
機能しませんbash
。ただし、dash
またはなどの他のシェルと組み合わせて使用できますzsh
。対話型bash
ログインシェルも期待どおりに機能します。
電話するときになぜbash
無視されますか?/etc/profile
非対話型通過するsu -
?
私の研究(以下)によると、問題は(および/または)コマンドラインオプションにハイフンを使用することが、他のシェルと比較してbash
ログインシェルを要求するときに異なる動作をすることです。$0
su
-l
--login
研究
(少し長いが、調査内容を文書として記録したかった。)
man su
この-c
引数が使用されることを説明します。
-c オプションを使用してコマンドをシェルに渡します。
そして-
議論
シェルをログインシェルで起動します。環境は実際のログインに似ています。
したがって、実際のログインに似た環境のログインシェルで実行する必要がありますsu - someuser -c cmd
。cmd
someuser
デモにはテストコマンドを使用できます。
$ testcmd='shopt -q login_shell || echo -n non-; echo login shell $0 $LANG'
su
ログインと非ログインのシェルに対して、以下を試してください。
$ su - someuser -c "$testcmd"
login shell -bash
$ su someuser -c "$testcmd"
non-login shell bash en_GB.UTF-8
ログインシェルの起動時に環境は構成されません(使用しないLANG
ため設定しません)。/etc/profile
環境は非ログインシェルを起動すると継承されるため、値は事前LANG
に消去され、示されているように起動シェルの環境から取得されます。
$ LANG= su someuser -c "$testcmd"
non-login shell bash
上記の例にはシェルがsomeuser
ありますbash
。 (単純なシンボリックリンクです)を使用してsh
同じ結果を得ることができますbash
。使用すると期待どおりに機能しますzsh
。
$ ztestcmd='[[ -o login ]] || echo -n non-; echo login shell $LANG'
$ LANG= su - someuser -s /bin/zsh -c "$ztestcmd"
Password:
login shell -zsh en_GB.UTF-8
$ LANG= su someuser -s /bin/zsh -c "$ztestcmd"
Password:
non-login shell zsh
su someuser -s /bin/zsh -c "$ztestcmd"
Password:
non-login shell zsh en_GB.UTF-8
でも動作します。したがって、問題はより深く掘り下げられるようdash
です。bash
bash
対話型シェルを起動すると、期待どおりに機能します。
$ su - someuser
$ LANG= shopt -q login_shell || echo -n non-; echo login shell $0 $LANG
login shell -bash en_GB.UTF-8
bash
したがって、対話型実行と非対話型実行su
は異なる動作をします。bash
直接創業はどうですか?
$ LANG= bash -c "$testcmd"
non-login shell bash
$ LANG= bash -l -c "$testcmd"
login shell bash en_GB.UTF-8
これは期待どおりに機能します。
GNU バッシュマニュアル状態それ
Bashが対話型ログインシェルまたはoptionsを含む非対話型シェルとして呼び出されると、
--login
まずファイルからコマンドを読み取り、実行します。/etc/profile
manによると、su
その-
オプションは使用されていませんが、--login
代わりに
-
シェルをログインシェルにするには、シェルのargv [0]を設定します。
以下を証明できます。
$ su - someuser -c 'echo $0'
Password:
-bash
私たちはこれを直接テストできます。先行ハイフンは$0
ログインシェルを提供します:
$ (LANG= exec -a '-' bash -c "$testcmd")
login shell -
だから先頭ハイフン$0
ログインシェルを作成しますが、bash
実行されない/etc/profile
これは、この方法で呼び出されると、そのオプションの動作と一致せず、-l
他のシェル(zsh
または)とも一致しませんdash
。また、インタラクションの開始時の独自の動作とも一致しません。
$ (LANG= exec -a '-' bash)
$ shopt -q login_shell || echo -n non-; echo login shell $0 $LANG
login shell - en_GB.UTF-8
残念ながら、これは上記の文書と矛盾しません。なぜなら、その使用を定義しないからです-l
。
答え1
コメントに記載されているとおりに正しく機能します。
もう一度考える文書:
Bashが対話型ログインシェルまたはoptionsを含む非対話型シェルとして呼び出されると、
--login
まずファイルからコマンドを読み取り、実行します。/etc/profile
/etc/profile
読み取りと実行として正しく解釈します。対話型ログインシェルまたは--login
オプションの非対話型シェル。$0
ハイフンで始まる非対話型ログインシェルとは言いません。
ただし、この動作は意図的に設計された動作であり、コンパイル時オプションのコメントを外すことでコンパイル時に変更できます。構成-top.h:
/* Define this to make non-interactive shells begun with argv[0][0] == '-'
run the startup files when not in posix mode. */
/* #define NON_INTERACTIVE_LOGIN_SHELLS */
しかし、実際にはそうではありませんが、なぜこの動作が実装されるのかについて疑問があります。IMHO、特に他のシェルのように実装されていない場合は、合理的に動作すると期待する方法です。
つまり、私の考えではないと思います。POSIX 標準シェル定義ログインシェルだから説明が可能だと思います。
元の問題に適用される回避策は次のとおりですbash
。
$ su - someuser -c 'bash -l -c tmux'