Vỏ đăng nhập được xác định ở đâu?


16

Tôi đã đọc sự khác biệt giữa sudo -i/-s đây . Sau khi sử dụng lệnh shopt, lưu ý rằng tất cả ( sudo su/sudo -i/sudo -s) $SHELLđều cung cấp kết quả giống nhau, nhưng shoptkết quả lệnh khác nhau.

Vì vậy, vỏ đăng nhập và không đăng nhập được định nghĩa như thế nào?

Từ đâu shoptcó được kết quả?

Tại sao nó không liên quan đến $SHELL?

sudo su

givinv@87-109:~$ sudo su
root@87-109:/home/givinv# 
root@87-109:/home/givinv# 
root@87-109:/home/givinv# shopt -q login_shell && echo 'Login shell' || echo 'No login shell'
No login shell
root@87-109:/home/givinv# echo $SHELL
/bin/bash
root@87-109:/home/givinv# 
root@87-109:/home/givinv# exit
givinv@87-109:~$ 

sudo -i

givinv@87-109:~$ sudo -i
root@87-109:~# 
root@87-109:~# shopt -q login_shell && echo 'Login shell' || echo 'No login shell'
Login shell
root@87-109:~# echo $SHELL
/bin/bash
root@87-109:~# 

sudo -s

root@87-109:~# sudo -s
root@87-109:~# shopt -q login_shell && echo 'Login shell' || echo 'No login shell'
No login shell
root@87-109:~# echo $SHELL
/bin/bash
root@87-109:~# 

7
Một vấn đề là "shell shell" có hai nghĩa: 1. Đây là một thể hiện của shell bắt đầu theo một cách cụ thể thực hiện những việc cụ thể (như đọc .profilehoặc tương đương) và 2. Đó là shell được cho là bắt đầu khi đăng nhập cho một người dùng, như được định nghĩa trong /etc/passwdhoặc tương đương. $SHELLchứa cái sau, shoptkết quả đầu ra của bạn đối phó với cái trước. Thông thường, khi shell trong (2) được bắt đầu khi đăng nhập, nó được bắt đầu theo cách cụ thể cần thiết cho (1), do đó kết hợp các ý nghĩa.
muru

1
Giải thích của @muru là một cách tốt. ví dụ: nếu bạn SSH vào máy tính của mình từ một máy từ xa. / usr / sbin / sshd trên hệ thống của bạn sẽ rẽ nhánh được xác định bởi $SHELL(và kết nối nó với thiết bị đầu cuối giả), lần lượt được xác định trong mục nhập / etc / passwd của bạn. shell này là shell đăng nhập và có thể được kiểm tra if [[ -o login ]]; then echo "I am a login shell"; fi. là một vỏ đăng nhập, nó sẽ thực hiện các tác vụ phù hợp với phiên mới. ví dụ: nguồn ~/.zprofilehoặc tương tự có thể đặt các biến môi trường và bất kỳ mã shell tùy chỉnh nào bạn có thể muốn chạy tại thời điểm này
the_velour_fog

Câu trả lời:


17

TL; DR :

  • Trường hợp đăng nhập được xác định? Trong /etc/passwd.
  • sudo su/ sudo su -/ sudo -i/ sudo -sgiống nhau? Không, tất cả chúng sinh ra một cái vỏ nhưng khác nhau và trong các bối cảnh khác nhau.
  • Không gì $SHELLlàm gì? Chỉ cần nói với shell mặc định của bạn, giống như trong /etc/passwd.

Trả lời thực tế :

Trước hết, điều quan trọng cần đề cập shoptlà đặc thù của bash. Chẳng hạn, tôi là mkshngười dùng shell, và nó không có shopt, giống như kshkhông.

Tiếp theo, chính xác những gì login_shellđược cho là đại diện? Từ man bash:

login_shell

Shell đặt tùy chọn này nếu nó được bắt đầu như một shell đăng nhập

Đó là điểm mấu chốt. sudo -i, như bạn đã biết từ câu trả lời trước mà bạn đã đọc, được cho là mô phỏng đăng nhập ban đầu. Đó là lý do tại sao shoptbáo cáo login_shell on cho tùy chọn này. Hãy nghĩ về điều này như thể sudo -ibuộc shell phải đi qua các tệp được cho là chỉ xuất hiện trong quá trình đăng nhập (không được lấy nguồn từ các shell tương tác).

Trong các trường hợp khác, bạn đã chạy một thể hiện của shell, vì vậy nó không thể là shell đăng nhập ở vị trí đầu tiên và mục đích của các tùy chọn là khác nhau. sudo -schỉ đọc $SHELL(có nghĩa là đại diện cho vỏ mặc định của bạn như được đặt trong /etc/passwd) và chạy nó với đặc quyền gốc. Đây là tương đương với làm sudo $SHELLhoặc sudo mkshhoặc sudo bash(tùy bạn tình cờ sử dụng).

Hãy nhớ rằng tôi đã đề cập rằng tôi là mkshngười dùng? Hãy xem này:

$ bash --posix
bash-4.3$ sudo -s
[sudo] password for xieerqi: 

DIR:/xieerqi|01:53|skolodya@ubuntu:
$ id 
uid=0(root) gid=0(root) groups=0(root)

DIR:/xieerqi|01:53|skolodya@ubuntu:
$ echo $-
imsU

Những gì bạn thấy là sudo -snhảy từ vỏ bashcủa tôi mksh, với dấu nhắc đặc trưng mà tôi đã đặt cho nó. Và tất nhiên, vì nó không phải là một hành động đăng nhập, vì bashnó sẽ báo cáo rằng shell được sinh ra như là một thể hiện shell không đăng nhập. Tuy nhiên, trong trường hợp của tôi, bạn thấy rằng $-không có một chữ cái nào lở đó, nó sẽ ở đó nếu đó là một ví dụ shell đăng nhập.

Cuối cùng, ý tưởng tương tự áp dụng cho sudo susudo su -. Sau đó, một trường hợp sinh ra vỏ đăng nhập (nghĩa là các tệp cụ thể được yêu cầu để đăng nhập sẽ chạy) và trước đây chỉ sinh ra các vỏ tương tác (nghĩa là các tệp đăng nhập không chạy).

bash-4.3$ sudo su
[sudo] password for xieerqi: 
root@eagle:/home/xieerqi# shopt login_shell
login_shell     off
root@eagle:/home/xieerqi# exit
bash-4.3$ sudo su -
[sudo] password for xieerqi: 
$ shopt login_shell
login_shell     on

Vì vậy, về mặt kỹ thuật, shopt login_shellkhông có liên quan đến $SHELLbất cứ điều gì. Hãy nghĩ về nó theo cách này: mục đích của nó là chỉ ra cách bash chạy. $SHELLđược cho là chỉ phản ánh những gì bạn đã chỉ định /etc/passwd.

Đối với sự khác biệt giữa shell đăng nhập và shell không đăng nhập, nó đã được giải thích bởi Gilles rất được tôn trọng trên unix.stackexchange.com trong câu trả lời này .


Thêm niềm vui

Đây là một cái gì đó thú vị mà bạn có thể thử. Như bạn có thể đã biết, một vỏ đăng nhập sẽ chạy .profile(và .bashrcvì Ubuntu .profile được cấu hình để làm như vậy ), nhưng địa ngục không đăng nhập sẽ chỉ chạy .bashrctệp. Vì vậy, chúng tôi có thể kiểm tra echoxem lệnh nào trong số các lệnh này chạy shell đăng nhập và lệnh nào không, và chúng tôi mong đợi hai dòng echocho shell đăng nhập và chỉ một dòng cho không đăng nhập.

$ echo "echo 'hi,i am .profile'"  >> .profile
$ echo "echo 'hi, i am .bashrc'" >> .bashrc
$ sudo -i
hi, i am .bashrc
hi,i am .profile
$ sudo su
hi, i am .bashrc
root@eagle:~# sudo su -
hi, i am .bashrc
hi,i am .profile
$ sudo -s
hi, i am .bashrc
root@eagle:~# 

Một cách thích hợp, những người có hai dòng đầu ra sẽ được login_shellđặt thành on.


Cảm ơn bạn @Serg và @Zanna. Bây giờ về $SHELLlogin_shell/non-login_shellđã làm rõ. Nhưng từ đâu shoptcó được thông tin chi tiết? Có phải từ echo $0đâu không?
prado

1
@prado Tôi sẽ nói có, vì ký tự đầu tiên $0được sử dụng để chỉ định xem shell có phải là shell đăng nhập hay không, vì vậy nếu shoptkiểm tra biến đó - chắc chắn, nó hoàn toàn chấp nhận được. Tuy nhiên, có lẽ nhiều hơn đáp ứng mắt. shoptcó lẽ Đối với câu hỏi này, tôi không có câu trả lời khó, vì tôi không rành về mã nguồn của bash.
Sergiy Kolodyazhnyy

@prado Bash có thể được bắt đầu như một vỏ đăng nhập bằng cách có ký tự đầu tiên là $ 0 -hoặc bằng cách sử dụng -ltùy chọn.
muru

@prado bạn có thể đọc về lời mời và các tùy chọn của bash trong trang man. ví dụ phần SHELL BUILTIN COMMAND cho biết login_shell The shell sets this option if it is started as a login shell (see INVOCATION above). The value may not be changed.như vậy shopt login_shellcó vẻ là một bash cách cho phép bạn tìm hiểu - lập trình làm thế nào để biết làm thế nào nó đã được bắt đầu. một cách khác sẽ là[[ -o login ]]
the_velour_fog

11

Như @Serg giải thích trong câu trả lời này về cách cho biết bạn đang chạy shell nào , SHELLbiến chỉ là shell mặc định của người dùng hiện tại như được đọc từ /etc/passwd:

$ grep zanna /etc/passwd
zanna:x:1000:1000:Zanna,,,:/home/zanna:/bin/bash

Vì vậy, nếu tôi echo $SHELLsẽ luôn luôn trở lại /bin/bash:

$ zsh
% echo $SHELL
/bin/bash

Cho dù vỏ có phải là vỏ đăng nhập hay không, là ion sh ell opt được xác định tại thời điểm vỏ được bắt đầu. Chương trình shell lưu trữ thông tin này cùng với tất cả các cài đặt và biến khác. Các shoptlệnh cung cấp một cách để xem thông tin này và nếu có thể cho các tùy chọn trong câu hỏi, để thiết lập hoặc unset nó (đây không phải là trường hợp cho login_shellmà, tất nhiên, phụ thuộc vào quá trình sử dụng để bắt đầu vỏ)

Các sudotùy chọn của chương trình xác định cách các loại vỏ gốc khác nhau sẽ được bắt đầu:

nhập mô tả hình ảnh ở đây


1
Lời giải thích hay. Tôi nghĩ rằng bạn đã giải thích những gì shoptlogin_shellđược cho là đại diện tốt hơn nhiều trong câu trả lời của tôi.
Sergiy Kolodyazhnyy

@Serg cảm ơn :) Tôi nghĩ rằng lời giải thích của bạn kỹ lưỡng hơn :)
Zanna

3

man bash:

Một shell đăng nhập là một cái mà ký tự đầu tiên của đối số 0 là một -hoặc một bắt đầu với --logintùy chọn.

man login:

Giá trị cho $HOME, $SHELL[...] được đặt theo các trường thích hợp trong mục nhập mật khẩu.

Nói ngắn gọn:

  • Shell là shell đăng nhập nếu nó được gọi là shell đăng nhập.
  • Ví dụ, biến môi trường $SHELLđược đặt bởi loginhoặc bởi chương trình gọi su. Vỏ tự nó không đặt nó.
  • shopt hiển thị các tùy chọn vỏ hiện đang có hiệu lực.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.