Sự khác biệt giữa Shell đăng nhập và Shell không đăng nhập?


318

Tôi hiểu sự khác biệt cơ bản giữa vỏ tương tác và vỏ không tương tác. Nhưng chính xác những gì phân biệt một vỏ đăng nhập từ một vỏ không đăng nhập?

Bạn có thể đưa ra ví dụ cho việc sử dụng shell tương tác không đăng nhập không?


45
Tôi nghĩ rằng câu hỏi được đặt ra tốt hơn là " Tại sao chúng ta nên / nên quan tâm để phân biệt các vỏ đăng nhập và không đăng nhập?" Nhiều nơi trên web đã cho chúng tôi biết sự khác biệt là , về các tệp khởi động mỗi lần đọc; nhưng không ai trong số họ dường như trả lời "tại sao" một cách thỏa đáng và thuyết phục. Ví dụ sử dụng các trường hợp mà bạn chắc chắn không muốn một hoặc hành vi khác sẽ là tuyệt vời.
Kal

2
@Kal Đây sẽ là một câu hỏi khác, vì không có câu trả lời nào ở đây thực sự bao gồm điều đó. Chỉnh sửa: Trên thực tế, đây là: TẠI SAO một vỏ đăng nhập trên một vỏ không đăng nhập ? .
Skippy le Grand Gourou

Câu trả lời:


304

Shell đăng nhập là quá trình đầu tiên thực thi theo ID người dùng của bạn khi bạn đăng nhập vào một phiên tương tác. Quá trình đăng nhập yêu cầu shell hoạt động như một shell đăng nhập với quy ước: truyền đối số 0, thường là tên của shell có thể thực thi được, với một -ký tự được đặt trước (ví dụ như -bashthông thường bash. Shell đăng nhập thường đọc một tệp những thứ như thiết lập các biến môi trường: /etc/profile~/.profilecho truyền thống Bourne vỏ, ~/.bash_profilebổ sung cho bash , /etc/zprofile~/.zprofilecho zsh , /etc/csh.login~/.logincho csh vv

Khi bạn đăng nhập trên bảng điều khiển văn bản hoặc thông qua SSH hoặc với su -, bạn sẽ nhận được vỏ đăng nhập tương tác . Khi bạn đăng nhập ở chế độ đồ họa (trên trình quản lý hiển thị X ), bạn không nhận được vỏ đăng nhập, thay vào đó bạn có trình quản lý phiên hoặc trình quản lý cửa sổ.

Rất hiếm khi chạy shell đăng nhập không tương tác , nhưng một số cài đặt X thực hiện điều đó khi bạn đăng nhập bằng trình quản lý hiển thị, để sắp xếp đọc các tệp hồ sơ. Các cài đặt khác (điều này phụ thuộc vào bản phân phối và trình quản lý hiển thị) đọc /etc/profilevà đọc ~/.profilerõ ràng hoặc không đọc chúng. Một cách khác để có được vỏ đăng nhập không tương tác là đăng nhập từ xa bằng lệnh được truyền qua đầu vào tiêu chuẩn không phải là thiết bị đầu cuối, ví dụ ssh example.com <my-script-which-is-stored-locally(trái ngược với ssh example.com my-script-which-is-on-the-remote-machine, chạy vỏ không đăng nhập, không tương tác).

Khi bạn khởi động một shell trong một thiết bị đầu cuối trong một phiên hiện có (màn hình, thiết bị đầu cuối X, bộ đệm thiết bị đầu cuối Emacs, một vỏ bên trong một thiết bị khác, v.v.), bạn sẽ nhận được một vỏ tương tác, không đăng nhập . Vỏ có thể đọc một tập tin cấu hình vỏ ( ~/.bashrccho bash gọi là bash, /etc/zshrc~/.zshrccho zsh, /etc/csh.cshrc~/.cshrccho csh, các tập tin được chỉ ra bởi ENVbiến cho vỏ POSIX / XSI tuân thủ như dấu gạch ngang, ksh và bash khi gọi như sh, $ENVnếu thiết lập và ~/.mkshrccho mksh, v.v.).

Khi shell chạy tập lệnh hoặc lệnh được truyền trên dòng lệnh của nó, đó là shell không tương tác, không đăng nhập . Các shell như vậy chạy mọi lúc: rất phổ biến là khi một chương trình gọi một chương trình khác, nó thực sự chạy một đoạn script nhỏ trong một shell để gọi chương trình khác đó. Một số shell đọc tệp khởi động trong trường hợp này (bash chạy tệp được chỉ định bởi BASH_ENVbiến, zsh chạy /etc/zshenv~/.zshenv), nhưng điều này rất nguy hiểm: shell có thể được gọi trong tất cả các loại ngữ cảnh và hầu như không có gì bạn có thể làm mà không thể phá hủy một số thứ.

Tôi đang đơn giản hóa một chút, xem hướng dẫn cho các chi tiết đẫm máu.


2
Bạn có thể cho ví dụ làm thế nào để chạy bashnhư một vỏ đăng nhập không tương tác?
Piotr Dobrogost

13
@PiotrDobrogostecho $- | bash -lx
Gilles

1
Tôi không biết điều này có đúng hay không, nhưng tôi muốn lưu ý rằng khi tôi mở một thiết bị đầu cuối mới (trên osx sử dụng cài đặt mặc định), tôi nhận được một vỏ đăng nhập mặc dù tôi không bao giờ nhập tên người dùng hoặc mật khẩu của mình.
Kevin Wheeler

4
@KevinWheeler Trên OSX, theo mặc định, ứng dụng Terminal chạy shell đăng nhập. (Như tôi giải thích, chương trình khởi động shell quyết định xem shell có hoạt động như shell đăng nhập hay không.) Đó không phải là cách thông thường để làm mọi việc.
Gilles

2
@IAmJulianAcosta Nếu FOOlà một biến môi trường (nghĩa là .profilechứa export FOO=something) thì nó có sẵn cho tất cả các quy trình con, bao gồm cả foo.sh. Nếu bạn đổi .profilethành export FOO=something_elsethì ./foo.shvẫn sẽ in somethingcho đến lần đăng nhập tiếp theo.
Gilles

48

Để biết nếu bạn đang ở trong vỏ đăng nhập:

prompt> echo $0
-bash # "-" is the first character. Therefore, this is a login shell.

prompt> echo $0
bash # "-" is NOT the first character. This is NOT a login shell.

Trong Bash, bạn cũng có thể sử dụng shopt login_shell:

prompt> shopt login_shell
login_shell     off

(hoặc ontrong một vỏ đăng nhập).

Thông tin có thể được tìm thấy trong man bash(tìm kiếm Invocation). Đây là một đoạn trích:

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

Bạn có thể tự kiểm tra điều này. Bất cứ khi nào bạn SSH, bạn đang sử dụng shell đăng nhập. Ví dụ:

prompt> ssh user@localhost
user@localhost's password:
prompt> echo $0
-bash

Tầm quan trọng của việc sử dụng shell đăng nhập là mọi cài đặt trong /home/user/.bash_profilesẽ được thực thi. Dưới đây là một chút thông tin nếu bạn quan tâm (từ man bash)

"Khi bash được gọi dưới dạng shell đăng nhập tương tác hoặc là vỏ không tương tác với tùy chọn --login, trước tiên, nó sẽ đọc và thực thi các lệnh từ tệp / etc / profile, nếu tệp đó tồn tại. Sau khi đọc tệp đó, nó sẽ tồn tại. tìm kiếm ~/.bash_profile, ~/.bash_login~/.profile, theo thứ tự đó, đọc và thực thi các lệnh từ lệnh đầu tiên tồn tại và có thể đọc được. Tùy chọn --noprofile có thể được sử dụng khi trình bao bắt đầu ngăn chặn hành vi này. "


23

Trong một vỏ đăng nhập , argv[0][0] == '-'. Đây là cách nó biết nó là một vỏ đăng nhập.

Và sau đó, trong một số tình huống, nó hoạt động khác nhau tùy thuộc vào trạng thái "vỏ đăng nhập" của nó. Ví dụ: shell, đó không phải là shell đăng nhập, sẽ không thực thi lệnh "logout".


4
Theo man bash, với sự nhấn mạnh được thêm vào, "Vỏ đăng nhập là một ký tự đầu tiên của đối số 0 là - hoặc bắt đầu bằng tùy chọn --login. "
Wildcard

18

Một shell bắt đầu trong một thiết bị đầu cuối mới trong GUI sẽ là một vỏ không đăng nhập tương tác. Nó sẽ lấy .bashrc của bạn, nhưng không phải .profile của bạn, chẳng hạn.


4

Tôi sẽ giải thích câu trả lời tuyệt vời của Gilles, kết hợp với phương pháp của Timothy để kiểm tra loại vỏ đăng nhập.

Nếu bạn muốn xem mọi thứ cho chính mình, hãy thử đoạn trích và kịch bản dưới đây.

Kiểm tra xem shell có (không) tương tác không

if tty -s; then echo 'This is interactive shell.'; else echo 'This is non-interactive shell.'; fi

Kiểm tra xem shell có (không) đăng nhập không

Nếu đầu ra echo $0bắt đầu bằng -, vỏ đăng nhập ( echo $0ví dụ đầu ra -bash:). Mặt khác, nó không phải là vỏ đăng nhập ( echo $0ví dụ đầu ra bash:).

if echo $0 | grep -e ^\- 2>&1>/dev/null; then echo "This is login shell."; else echo "This is non-login shell."; fi;

Hãy kết hợp cả hai ở trên với nhau để có được cả hai thông tin cùng một lúc:

THIS_SHELL_INTERACTIVE_TYPE='non-interactive'; 
THIS_SHELL_LOGIN_TYPE='non-login'; 
if tty -s; then THIS_SHELL_INTERACTIVE_TYPE='interactive'; fi; 
if echo $0 | grep -e ^\- 2>&1>/dev/null; then THIS_SHELL_LOGIN_TYPE='login'; fi;
echo "$THIS_SHELL_INTERACTIVE_TYPE/$THIS_SHELL_LOGIN_TYPE"

Kịch bản:

Phiên SSH điển hình không có tùy chọn đặc biệt

ssh ubuntu@34.247.105.87
Welcome to Ubuntu 16.04.5 LTS (GNU/Linux 4.4.0-1083-aws x86_64)

ubuntu@ip-172-31-0-70:~$ THIS_SHELL_INTERACTIVE_TYPE='non-interactive';
ubuntu@ip-172-31-0-70:~$ THIS_SHELL_LOGIN_TYPE='non-login';
ubuntu@ip-172-31-0-70:~$ if tty -s; then THIS_SHELL_INTERACTIVE_TYPE='interactive'; fi;
ubuntu@ip-172-31-0-70:~$ if echo $0 | grep -e ^\- 2>&1>/dev/null; then THIS_SHELL_LOGIN_TYPE='login'; fi;
ubuntu@ip-172-31-0-70:~$ echo "$THIS_SHELL_INTERACTIVE_TYPE/$THIS_SHELL_LOGIN_TYPE"

interactive/login

Chạy script hoặc thực thi rõ ràng thông qua shell mới

ubuntu@ip-172-31-0-70:~$  bash -c 'THIS_SHELL_INTERACTIVE_TYPE='non-interactive'; THIS_SHELL_LOGIN_TYPE='non-login'; if tty -s; then THIS_SHELL_INTERACTIVE_TYPE='interactive'; fi; if echo $0 | grep -e ^\- 2>&1>/dev/null; then THIS_SHELL_LOGIN_TYPE='login'; fi; 
echo "$THIS_SHELL_INTERACTIVE_TYPE/$THIS_SHELL_LOGIN_TYPE"'

interactive/non-login

Chạy tập lệnh cục bộ từ xa

ssh ubuntu@34.247.105.87 < checkmy.sh
Pseudo-terminal will not be allocated because stdin is not a terminal.
Welcome to Ubuntu 16.04.5 LTS (GNU/Linux 4.4.0-1083-aws x86_64)

non-interactive/login

Chạy một lệnh trên ssh từ xa

ssh ubuntu@34.247.105.87 'THIS_SHELL_INTERACTIVE_TYPE='non-interactive'; THIS_SHELL_LOGIN_TYPE='non-login'; if tty -s; then THIS_SHELL_INTERACTIVE_TYPE='interactive'; fi; if echo $0 | grep -e ^\- 2>&1>/dev/null; then THIS_SHELL_LOGIN_TYPE='login'; fi; echo "$THIS_SHELL_INTERACTIVE_TYPE/$THIS_SHELL_LOGIN_TYPE"'

non-interactive/non-login

Chạy một lệnh trên ssh từ xa với -tchuyển đổi

Bạn có thể yêu cầu rõ ràng shell tương tác khi bạn muốn chạy lệnh từ xa thông qua ssh bằng cách sử dụng -tchuyển đổi.

ssh ubuntu@34.247.105.87 -t 'THIS_SHELL_INTERACTIVE_TYPE='non-interactive'; THIS_SHELL_LOGIN_TYPE='non-login'; if tty -s; then THIS_SHELL_INTERACTIVE_TYPE='interactive'; fi; if echo $0 | grep -e ^\- 2>&1>/dev/null; then THIS_SHELL_LOGIN_TYPE='login'; fi; echo "$THIS_SHELL_INTERACTIVE_TYPE/$THIS_SHELL_LOGIN_TYPE"'

interactive/non-login

Lưu ý: Về chủ đề tại sao chạy lệnh từ xa không login shellcó thêm thông tin ở đây .

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.