Bagaimana shell bisa tahu rumah?

25

Setiap shell memiliki variabel lingkungan yang diset $ HOME (mis /Users/lotolo. :) . Jika saya di bawah csh saya bisa unsetenv HOMEdan masih jika saya melakukannya cdsaya akan berada di rumah saya. Saya sudah menguji ini juga di bash ( unset HOME) dan itu perilaku yang sama. Jadi bagaimana shell tahu di mana rumah / user_user saya berada? Di mana ia membaca nilai-nilai itu?

Ini bukan duplikat karena pertanyaan saya bukan bagaimana saya tahu, tetapi bagaimana shell tahu HOME. Dan perilaku ini juga diperluas ke pengguna lain.

LotoLo
sumber
1
@StephenKitt, tidak bukan duplikat. Di sini kita berbicara tentang perilaku shell untuk direktori home dari pengguna saat ini.
Stéphane Chazelas
Dalam kasus sederhana dari /etc/passwd. Beberapa sistem dapat menyimpan informasi itu dalam LDAP, server NIS, dll.
Satō Katsura
1
Program (termasuk kerang) hanya memanggil getpwuid(3)atau serupa. Beberapa sistem dapat dikonfigurasikan untuk "rute-ulang" getpwuid(3)untuk mengambil informasi dari /etc/passwd, LDAP, NIS, NIS + dll.
Satō Katsura
@StephenKitt, lihat jawaban saya
Stéphane Chazelas
1
@ GAD3R, lihat diskusi di atas, StephenKitt sudah menunjuk ke duplikat yang sama (yang sejak ia ditarik kembali), tapi saya berpendapat di atas (dan lihat juga jawaban saya) bahwa itu bukan duplikat.
Stéphane Chazelas

Jawaban:

33

Dalam kasus cshdan tcsh, ia mencatat nilai $HOMEvariabel pada saat shell dimulai ( dalam $homevariabelnya seperti dicatat oleh @JdeBP ).

Jika Anda menghapusnya sebelum memulai csh, Anda akan melihat sesuatu seperti:

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

Untuk bash(dan kebanyakan kerang mirip Bourne), saya melihat perilaku yang berbeda dari milik Anda.

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

Konten $HOMEvariabel diinisialisasi oleh proses login berdasarkan informasi yang disimpan dalam database pengguna terhadap nama pengguna Anda .

Informasi tentang nama pengguna itu sendiri tidak selalu tersedia. Semua shell dapat mengetahui dengan pasti adalah userid dari proses yang mengeksekusinya dan beberapa pengguna (dengan direktori home berbeda) dapat berbagi userid yang sama.

Jadi, sekali $HOMEhilang tidak ada cara yang dapat diandalkan untuk mendapatkannya kembali.

Meminta basis data pengguna (dengan getpwxxx()API standar) untuk direktori home pengguna pertama yang memiliki cairan yang sama dengan yang menjalankan shell hanya akan menjadi perkiraan (belum lagi fakta bahwa basis data pengguna bisa saja berubah (atau rumah direktori didefinisikan sebagai nilai satu kali) sejak sesi login dimulai).

zsh adalah satu-satunya shell yang saya tahu yang melakukan itu:

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

Semua kerang lain yang saya coba mengeluhkan tentang HOME yang belum disetel atau digunakan /sebagai nilai rumah default.

Namun perilaku yang berbeda adalah fish, yang tampaknya menanyakan database untuk nama pengguna yang disimpan $USERjika ada atau melakukan getpwuid()jika tidak:

$ 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 ketika pengguna tidak ada ( 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 ''
Stéphane Chazelas
sumber
2
Saya kira kita bisa melaporkan masalah ini! Jawaban yang sangat bagus, terima kasih!
LotoLo
1
@LotoLo, ya, saya sibuk membangun dengan fishkepala dev git untuk melihat apakah ada bug di sana. Edit. Ya itu.
Stéphane Chazelas
Sekarang saya ingin tahu: Variabel lingkungan manakah yang membuat shell secara maksimal tidak ramah pengguna jika tidak disetel? PATH? TERM? USER?
user1024
Ada garis aneh di sini: "hanya akan menjadi perkiraan ..." Tanda kurung tidak berbaris dalam paragraf itu juga. Apa yang seharusnya?
muru
1
@uru Querying the user database... would only be...memang tidak begitu jelas
edc65
6

Jadi bagaimana shell bisa tahu di mana rumah / user_user saya berada?

Tidak. Anda tidak melakukan eksperimen dengan benar. Seperti yang dapat Anda lihat dari manual shell C, cdperintah berubah ke nilai homevariabel jika disediakan tanpa argumen. Jika variabel ini tidak disetel, itu tidak tahu ke mana harus mengubah direktori dan mencetak kesalahan:

mesin: ~> set home = /
mesin: / home / user> cd
mesin: ~> unset home
mesin: /> cd
cd: Tidak ada direktori home
mesin: /> 

Anda membatalkan variabel yang salah. Itu bukan HOME, variabel lingkungan, itu adalah homevariabel internal shell C (diinisialisasi dari nilai yang pertama ketika shell dijalankan, tetapi sebaliknya variabel independen dalam haknya sendiri).

JdeBP
sumber
tidak pada csh (setidaknya pada versi saya: "tcsh 6.18.01 (Astron) 2012-02-14 (x86_64-apple-darwin)") itu variabel HOME yang membawa nilai rumah. Tetapi seperti yang dikatakan @Stephane Chazelas, saya harus menghapus variabel sebelum meluncurkan shell karena akan menetapkan nilai HOME di awal.
LotoLo
Di atas adalah shell C, yang saya jalankan di mesin OpenBSD berguna, dan menunjukkan perilakunya. Ini bahkan bukan shell TENEX C (meskipun berperilaku sama).
JdeBP
Ya saya melihatnya ... saya mengetik cshtetapi ternyata itu aliastcsh
LotoLo
0

Sistem mengatur variabel HOME pada saat login menjadi pathname dari direktori home pengguna. Sudah diatur oleh

  • gdm, kdm atau xdm untuk sesi grafis.
  • login pada sesi konsol, telnet dan rlogin
  • sshd untuk koneksi SSH

Anda dapat mengubah nilainya tetapi perhatikan karena .bashrc, .profile, .xinitrc, dll tidak akan dibaca jika tidak ada di direktori home.

Dababi
sumber
Tapi saya bisa menghapusnya ($ HOME) ... kan? Dan bagaimana ia tahu di mana rumah pengguna lain?
LotoLo
1
Anda dapat memperbaruinya menggunakan usermod -d HOME_DIRperintah, saat pengguna baru dibuat. home default adalah / home / $ username dan ditentukan oleh program login.
Dababi