web-dev-qa-db-ja.com

シェルはどのように家を知っていますか?

各シェルには環境変数$ HOMEが設定されています(例:/Users/lotolo)。私がcshの下にいる場合、私はunsetenv HOMEそして、もし私がやればcdは家にいます。私はこれをbash(unset HOME)と同じ動作です。それで、シェルはどのように私の/ other_userの家がどこにあるかを知っていますか?それらの値はどこで読み取られますか?

私の質問は[〜#〜] i [〜#〜]を知る方法ではないため、これは重複ではありませんが、シェルを知る方法HOME。また、この動作は他のユーザーにも拡張されます。

25
LotoLo

cshおよびtcshの場合、シェルが開始されたときの_$HOME_変数の値を記録します( _$home_変数に@JdeBP )で示されるように。

cshを開始する前に設定を解除すると、次のように表示されます。

_$ (unset HOME; csh -c cd)
cd: No home directory.
_

bash(および他のほとんどのBourneのようなシェル)については、あなたとは異なる動作が見られます。

_bash-4.4$ unset HOME; cd
bash: cd: HOME not set
_

_$HOME_変数の内容は、ユーザーに対してユーザーデータベースに保存されている情報nameに基づいて、ログインプロセスによって初期化されます。

ユーザー名自体に関する情報は常に利用できるとは限りません。シェルが確実に知ることができるのは、それを実行しているプロセスのユーザーIDだけであり、(ホームディレクトリが異なる)複数のユーザーが同じユーザーIDを共有できます。

したがって、_$HOME_がなくなると、確実に元に戻す方法はありません。

シェルを実行しているユーザーと同じuidを持つ最初のユーザーのホームディレクトリを(getpwxxx()標準APIを使用して)ユーザーデータベースにクエリするのは、概算にすぎません(ユーザーデータベースがログインセッションが開始されてから変更されている可能性があります(またはホームディレクトリが1回限りの値として定義されています)。

zshは、私が知っている唯一のシェルです。

_$ env -u HOME ltrace -e getpw\* zsh -c 'cd && pwd'
zsh->getpwuid(1000, 0x496feb, 114, 0x7f9599004697)      = 0x7f95992fddc0
/home/chazelas
+++ exited (status 0) +++
_

私が試した他のすべてのシェルは、設定されていないHOMEについて不満を言うか、デフォルトのホーム値として_/_を使用します。

しかし、別の動作はfishです。これは、存在する場合は_$USER_に格納されているユーザー名をデータベースに照会し、存在しない場合はgetpwuid()を実行するようです。

_$ env -u HOME USER=bin ltrace -e getpw\* fish -c 'cd;pwd'
fish->getpwnam("bin")  = 0x7fd2beba3d80
fish: Unable to create a configuration directory for fish. Your personal settings will not be saved. Please set the $XDG_CONFIG_HOME variable to a directory
where the current user has write access.
fish: Unable to create a configuration directory for fish. Your personal settings will not be saved. Please set the $XDG_CONFIG_HOME variable to a directory
where the current user has write access.
--- SIGCHLD (Child exited) ---
/bin
+++ exited (status 0) +++


$ env -u HOME -u USER ltrace -e getpw\* fish -c 'cd;pwd'
fish->getpwuid(1000, 0x7f529eb4fb28, 0x12d8790, 0x7f529e858697) = 0x7f529eb51dc0
fish->getpwnam("chazelas")                                      = 0x7f529eb51d80
--- SIGCHLD (Child exited) ---
--- SIGCHLD (Child exited) ---
/home/chazelas
+++ exited (status 0) +++
_

ユーザーが存在しない場合のSEGV( https://github.com/fish-Shell/fish-Shell/issues/3599 ):

_$ env -u HOME USER=foo fish -c ''
zsh: segmentation fault  env -u HOME USER=foo fish -c ''
_
33

それで、シェルはどのように私の/ other_userの家がどこにあるかを知っていますか?

そうではありません。実験が適切に行われていないだけです。 Cシェルのマニュアルからわかるように、cdコマンドは、引数を指定しないと、home変数の値に変わります。この変数が設定されていない場合、ディレクトリをどこに変更するかわからず、エラーが出力されます。

machine:〜> set home =/
 machine:/ home/user> cd 
 machine:〜> unset home 
 machine:/> cd 
 cd:いいえホームディレクトリ
 machine:/> 

間違った変数を設定解除した。環境変数HOMEではなく、Cシェルの内部変数homeです(シェルの起動時に前者の値から初期化されますが、それ以外はそれ自体が独立した変数です)。 。

6
JdeBP

システムは、ログイン時にHOME変数をユーザーのホームディレクトリのパス名に設定しました。によって設定されます

  • グラフィカルセッションの場合は、gdm、kdm、またはxdm。
  • コンソール、Telnet、rloginセッションでのログイン
  • sSH接続の場合はsshd

値は変更できますが、.bashrc、.profile、.xinitrcなどがホームディレクトリにない場合は読み取られないため、注意が必要です。

0
Dababi