Sự khác biệt giữa .bashrc và .bash_profile


450

Sự khác biệt giữa những gì .bashrc.bash_profilevà cái nào tôi nên sử dụng?



Nếu bạn muốn một lời giải thích đầy đủ hơn cũng có liên quan .profile, hãy xem câu hỏi này: superuser.com/questions/789448/
mẹo

Câu trả lời này cũng bao gồm một số khía cạnh stackoverflow.com/questions/415403/ từ
Serge Voronezhskiy

Câu trả lời:


518

Theo truyền thống, khi bạn đăng nhập vào hệ thống Unix, hệ thống sẽ bắt đầu một chương trình cho bạn. Chương trình đó là một vỏ, tức là một chương trình được thiết kế để bắt đầu các chương trình khác. Đó là shell dòng lệnh: bạn bắt đầu một chương trình khác bằng cách nhập tên của nó. Shell mặc định, shell Bourne, đọc các lệnh từ ~/.profilekhi nó được gọi là shell đăng nhập.

Bash là một vỏ giống như Bourne. Nó đọc các lệnh từ ~/.bash_profilekhi nó được gọi là shell đăng nhập và nếu tệp đó không tồn tại, nó sẽ cố đọc ~/.profilethay thế.

Bạn có thể gọi shell trực tiếp bất cứ lúc nào, ví dụ bằng cách khởi chạy trình giả lập thiết bị đầu cuối bên trong môi trường GUI. Nếu shell không phải là shell đăng nhập, nó không đọc được ~/.profile. Khi bạn bắt đầu bash dưới dạng shell tương tác (nghĩa là không chạy script), nó sẽ đọc ~/.bashrc(ngoại trừ khi được gọi là shell đăng nhập, thì nó chỉ đọc ~/.bash_profilehoặc ~/.profile.

Vì thế:

  • ~/.profile là nơi đặt nội dung áp dụng cho toàn bộ phiên của bạn, chẳng hạn như các chương trình bạn muốn bắt đầu khi đăng nhập (nhưng không phải chương trình đồ họa, chúng đi vào một tệp khác) và định nghĩa biến môi trường.

  • ~/.bashrclà nơi để đặt những thứ chỉ áp dụng cho bash chính nó, chẳng hạn như định nghĩa bí danh và hàm, tùy chọn shell và cài đặt nhanh chóng. (Bạn cũng có thể đặt các ràng buộc chính ở đó, nhưng đối với bash chúng thường đi vào ~/.inputrc.)

  • ~/.bash_profilecó thể được sử dụng thay thế ~/.profile, nhưng nó chỉ được đọc bằng bash chứ không phải bởi bất kỳ shell nào khác. (Đây là chủ yếu là một mối quan tâm nếu bạn muốn tập tin khởi tạo của bạn để làm việc trên nhiều máy tính và vỏ đăng nhập của bạn không bash trên tất cả trong số họ.) Đây là một nơi hợp lý để bao gồm ~/.bashrcnếu vỏ là tương tác. Tôi đề nghị các nội dung sau trong ~/.bash_profile:

    if [ -r ~/.profile ]; then . ~/.profile; fi
    case "$-" in *i*) if [ -r ~/.bashrc ]; then . ~/.bashrc; fi;; esac
    

Trên các đơn vị hiện đại, có thêm một sự phức tạp liên quan đến ~/.profile. Nếu bạn đăng nhập trong môi trường đồ họa (nghĩa là, nếu chương trình nơi bạn nhập mật khẩu của bạn đang chạy ở chế độ đồ họa), bạn sẽ không tự động nhận được vỏ đăng nhập đọc ~/.profile. Tùy thuộc vào chương trình đăng nhập đồ họa, trên trình quản lý cửa sổ hoặc môi trường máy tính để bàn mà bạn chạy sau đó và cách phân phối của bạn định cấu hình các chương trình này, bạn ~/.profilecó thể hoặc không thể đọc được. Nếu không, thường sẽ có một nơi khác mà bạn có thể xác định các biến và chương trình môi trường để khởi chạy khi đăng nhập, nhưng không may là không có vị trí chuẩn.

Lưu ý rằng bạn có thể thấy ở đây và có các khuyến nghị để đặt định nghĩa biến môi trường vào ~/.bashrchoặc luôn khởi chạy shell đăng nhập trong thiết bị đầu cuối. Cả hai đều là những ý tưởng tồi. Vấn đề phổ biến nhất với một trong những ý tưởng này là các biến môi trường của bạn sẽ chỉ được đặt trong các chương trình được khởi chạy qua thiết bị đầu cuối, không phải trong các chương trình được khởi động trực tiếp bằng biểu tượng hoặc menu hoặc phím tắt.

¹ Để hoàn chỉnh, theo yêu cầu: nếu .bash_profilekhông tồn tại, bash cũng cố gắng .bash_logintrước khi giảm trở lại .profile. Hãy quên nó tồn tại.


11
+1 cho bài viết tốt. CSONG cảm ơn bạn đã thêm phần về "đồ họa đăng nhập và vỏ đăng nhập" ... Tôi gặp vấn đề mà tôi nghĩ ~ / .profile sẽ LUÔN thực thi cho đồ họa / shell ... nhưng nó không thực thi khi người dùng đăng nhập thông qua đăng nhập đồ họa. Cảm ơn bạn đã giải quyết bí ẩn đó.
Trevor Boyd Smith

4
@Gilles: Bạn có thể giải thích chi tiết hơn, với các ví dụ, tại sao chạy shell đăng nhập trong mỗi thiết bị đầu cuối là một ý tưởng tồi? Đây chỉ là một vấn đề với máy tính để bàn Linux? (Tôi tập hợp rằng trên OS X Terminal luôn chạy shell đăng nhập và tôi chưa bao giờ nhận thấy bất kỳ tác dụng phụ nào (mặc dù tôi thường sử dụng iTerm). Nhưng sau đó tôi không thể nghĩ ra nhiều biến môi trường mà tôi quan tâm bên ngoài một thiết bị đầu cuối. (Có thể HTTP_PROXY?))
iconoclast

2
@Brandon Nếu bạn chạy shell đăng nhập trong mọi thiết bị đầu cuối, điều đó sẽ ghi đè các biến môi trường được cung cấp bởi môi trường. Trong các tình huống hàng ngày, bạn có thể thoát khỏi nó, nhưng nó sẽ đến và cắn bạn sớm hay muộn, khi bạn muốn thiết lập các biến khác nhau trong một thiết bị đầu cuối (giả sử, để thử một phiên bản khác của chương trình): chạy một shell đăng nhập sẽ ghi đè cài đặt cục bộ của bạn.
Gilles

4
Câu lệnh ~/.bash_profilecó thể được sử dụng thay thế ~/.profile, nhưng bạn cũng cần bao gồm ~/.bashrcnếu shell tương tác. là sai lệch vì đây là những vấn đề trực giao. Không có vấn đề nếu bạn sử dụng ~/.bash_profilehoặc ~/.profilebạn phải bao gồm ~/.bashrctrong cái bạn sử dụng nếu bạn muốn cài đặt từ đó có hiệu lực trong vỏ đăng nhập.
Piotr Dobrogost

3
@Gilles Chắc chắn, nhưng cách đặt câu trong câu trả lời cho thấy rằng nhu cầu bao gồm ~/.bashrccó liên quan đến việc chọn ~/.bash_profilethay vì ~/.profileđiều đó không đúng. Nếu ai đó bao gồm ~/.bashrcbất kỳ loại tập lệnh nào có nguồn gốc tại thời điểm đăng nhập (thì đây là ~/.bash_profilehoặc ~/.profile) là vì anh ta muốn cài đặt ~/.bashrcđược áp dụng cho trình vỏ đăng nhập giống như cách họ đang áp dụng cho trình bao không đăng nhập.
Piotr Dobrogost

53

Từ bài viết ngắn này

Theo trang bash man, .bash_profile được thực thi cho các shell đăng nhập, trong khi .bashrc được thực thi cho các shell không đăng nhập tương tác.

Một vỏ đăng nhập hoặc không đăng nhập là gì?

Khi bạn đăng nhập (ví dụ: nhập tên người dùng và mật khẩu) qua bàn điều khiển, hoặc ngồi vật lý ở máy khi khởi động hoặc từ xa qua ssh: .bash_profile được thực thi để định cấu hình mọi thứ trước dấu nhắc lệnh ban đầu.

Nhưng, nếu bạn đã đăng nhập vào máy của mình và mở một cửa sổ đầu cuối mới (xterm) bên trong Gnome hoặc KDE, thì .bashrc được thực thi trước dấu nhắc lệnh của cửa sổ. .bashrc cũng được chạy khi bạn bắt đầu một cá thể bash mới bằng cách gõ / bin / bash trong một thiết bị đầu cuối.


12
Cập nhật nhẹ: 'Đã thực hiện' có lẽ là một thuật ngữ hơi sai lệch, cả hai đều có nguồn gốc. Âm thanh được thực hiện như là nó chạy như một kịch bản, fork / exec yadda yadda. Nó chạy trong ngữ cảnh của shell hiện tại Quan trọng hơn, .bashrc được chạy thường xuyên hơn. Nó được chạy trên mọi tập lệnh bash, và nếu bạn không có .bash_profile. Ngoài ra, tùy thuộc vào cách bạn thiết lập xterms của mình, bạn có thể tạo một vỏ mà nguồn .bash_profile
Rich Homolka

36

Quay trở lại những ngày xưa, khi giả không phải là giả và thực tế, tốt, được gõ và UNIX được truy cập bởi các modem rất chậm, bạn có thể thấy mỗi chữ cái được in lên màn hình của bạn, hiệu quả là tối quan trọng. Để giúp hiệu quả phần nào, bạn đã có một khái niệm về một cửa sổ đăng nhập chính và bất kỳ cửa sổ nào khác mà bạn đã sử dụng để thực sự hoạt động. Trong cửa sổ chính của bạn, bạn muốn thông báo cho bất kỳ thư mới nào, có thể chạy một số chương trình khác trong nền.

Để hỗ trợ điều này, các shell đã lấy một tệp .profilecụ thể trên 'shell đăng nhập'. Điều này sẽ làm đặc biệt, một khi thiết lập phiên. Bash đã mở rộng phần này để xem xét .bash_profile trước khi .profile, bằng cách này bạn có thể đặt bash chỉ những thứ trong đó (vì vậy họ không làm hỏng vỏ Bourne, v.v., cũng nhìn vào .profile). Các shell khác, không đăng nhập, sẽ chỉ nguồn tệp RC, .bashrc (hoặc .kshrc, v.v.).

Đây là một chút lỗi thời. Bạn không đăng nhập vào shell chính nhiều như bạn đăng nhập vào trình quản lý cửa sổ gui. Không có cửa sổ chính nào khác với bất kỳ cửa sổ nào khác.

Đề nghị của tôi - đừng lo lắng về sự khác biệt này, nó dựa trên một phong cách sử dụng unix cũ hơn. Loại bỏ sự khác biệt trong các tập tin của bạn. Toàn bộ nội dung của .bash_profile phải là:

[ -f $HOME/.bashrc ] && . $HOME/.bashrc

Và đặt mọi thứ bạn thực sự muốn đặt vào .bashrc

Hãy nhớ rằng .bashrc có nguồn gốc cho tất cả các hệ vỏ, tương tác và không tương tác. Bạn có thể rút ngắn nguồn tìm nguồn cho các shell không tương tác bằng cách đặt mã này ở gần đầu .bashrc:

[[ $- != *i* ]] && return


6
Đây là một ý tưởng tồi, xem câu trả lời của tôi . Cụ thể, các biến môi trường của bạn sẽ chỉ được đặt trong các chương trình được khởi chạy qua thiết bị đầu cuối, không phải trong các chương trình được bắt đầu trực tiếp bằng biểu tượng hoặc menu hoặc phím tắt.
Gilles

4
@Gilles Tôi không hiểu tại sao bạn yêu cầu điều này. Với .$HOME/.bashrcnhư Rich đã trình bày ở trên, cài đặt trong .bashrcsẽ có sẵn trong shell đăng nhập và do đó, môi trường máy tính để bàn cũng vậy. Ví dụ, trên hệ thống Fedora của tôi, gnome-sessionđược bắt đầu như -$SHELL -c gnome-sessionvậy, cũng .profileđược đọc.
Mikel

2
@PiotrDobrogost Ồ, vâng, có một vấn đề khác với câu trả lời của Rich. Bao gồm .bashrctrong .profilethường không hoạt động, bởi vì .profilecó thể được thực thi bởi /bin/shvà không bash (ví dụ trên Ubuntu để đăng nhập đồ họa theo mặc định) và vỏ đó có thể không tương tác (ví dụ: đăng nhập đồ họa).
Gilles

3
@Gilles re: "bao gồm .bashrc trong .profile" hoàn toàn không phải là những gì được đề xuất (thực tế hoàn toàn ngược lại). Câu trả lời đã được chỉnh sửa (nó không xuất hiện như vậy) hoặc ý kiến ​​của bạn không phù hợp với những gì đang được nói.
michael

2
Nói chung, +1, nhưng tôi sẽ thêm vào đề xuất "ngắn mạch ... cho các vỏ không tương tác" ("gần đầu .bashrc: [[ $- != *i* ]] && return"); Tôi thích một số trong số tôi .bashrcđược thực thi ngay cả đối với các shell không tương tác, cụ thể là đặt env vars, khi phát hành ssh hostname {command}, để các lệnh từ xa được thực thi chính xác (mặc dù shell không tương tác). Nhưng các thiết lập khác sau này .bashrcnên được bỏ qua. Tôi thường kiểm tra TERM = câm và / hoặc không đặt, và sau đó bảo lãnh sớm.
michael

18

Có một cái nhìn vào bài viết blog tuyệt vời này của ShreevatsaR . Đây là một trích xuất, nhưng đi đến bài đăng trên blog, nó bao gồm một lời giải thích cho các thuật ngữ như "vỏ đăng nhập", biểu đồ dòng chảy và một bảng tương tự cho Zsh.

Đối với Bash, họ làm việc như sau. Đọc xuống cột thích hợp. Thực thi A, rồi B, rồi C, v.v ... B1, B2, B3 có nghĩa là nó chỉ thực thi đầu tiên trong số các tệp được tìm thấy.

+----------------+-----------+-----------+------+
|                |Interactive|Interactive|Script|
|                |login      |non-login  |      |
+----------------+-----------+-----------+------+
|/etc/profile    |   A       |           |      |
+----------------+-----------+-----------+------+
|/etc/bash.bashrc|           |    A      |      |
+----------------+-----------+-----------+------+
|~/.bashrc       |           |    B      |      |
+----------------+-----------+-----------+------+
|~/.bash_profile |   B1      |           |      |
+----------------+-----------+-----------+------+
|~/.bash_login   |   B2      |           |      |
+----------------+-----------+-----------+------+
|~/.profile      |   B3      |           |      |
+----------------+-----------+-----------+------+
|BASH_ENV        |           |           |  A   |
+----------------+-----------+-----------+------+
|                |           |           |      |
+----------------+-----------+-----------+------+
|                |           |           |      |
+----------------+-----------+-----------+------+
|~/.bash_logout  |    C      |           |      |
+----------------+-----------+-----------+------+

Thay vì đăng cùng một câu trả lời cho nhiều câu hỏi, nó được ưu tiên nếu bạn có thể điều chỉnh câu trả lời của mình theo nhu cầu cụ thể của người hỏi. Nếu câu trả lời hoàn toàn giống nhau cho cả hai câu hỏi thì bạn nên đăng một câu trả lời duy nhất và bỏ phiếu để đóng các câu hỏi khác dưới dạng trùng lặp với bản gốc.
Mokubai

1
@Mokubai Câu hỏi khác đã được đánh dấu là một bản sao của câu hỏi này.
Flimm

@ElipticalView: bằng cách đặt thành không làm gì, bạn đang đề cập đến dòng : [ -z "$PS1" ] && return? Bảng trong câu trả lời của tôi là đưa ra danh sách các tập lệnh do Bash điều hành bất kể nội dung của tập lệnh là gì, nếu tập lệnh có dòng [ -z "$PS1" ] && return, tất nhiên sẽ có hiệu lực, nhưng tôi không nghĩ điều đó có nghĩa là tôi nên thay đổi bàn.
Flimm

5

NHẬN XÉT TỐT HƠN CHO NGƯỜI ĐẦU / ETC / HỒ SƠ

Dựa trên câu trả lời tuyệt vời của Flimm ở trên, tôi đã đưa ra nhận xét mới này ở phần đầu của hồ sơ Debian / etc / của tôi, (bạn có thể cần điều chỉnh nó cho bản phân phối của mình.) :

# For BASH: Read down the appropriate column. Executes A, then B, then C, etc.
# The B1, B2, B3 means it executes only the first of those files found.  (A)
# or (B2) means it is normally sourced by (read by and included in) the
# primary file, in this case A or B2.
#
# +---------------------------------+-------+-----+------------+
# |                                 | Interactive | non-Inter. |
# +---------------------------------+-------+-----+------------+
# |                                 | login |    non-login     |
# +---------------------------------+-------+-----+------------+
# |                                 |       |     |            |
# |   ALL USERS:                    |       |     |            |
# +---------------------------------+-------+-----+------------+
# |BASH_ENV                         |       |     |     A      | not interactive or login
# |                                 |       |     |            |
# +---------------------------------+-------+-----+------------+
# |/etc/profile                     |   A   |     |            | set PATH & PS1, & call following:
# +---------------------------------+-------+-----+------------+
# |/etc/bash.bashrc                 |  (A)  |  A  |            | Better PS1 + command-not-found 
# +---------------------------------+-------+-----+------------+
# |/etc/profile.d/bash_completion.sh|  (A)  |     |            |
# +---------------------------------+-------+-----+------------+
# |/etc/profile.d/vte-2.91.sh       |  (A)  |     |            | Virt. Terminal Emulator
# |/etc/profile.d/vte.sh            |  (A)  |     |            |
# +---------------------------------+-------+-----+------------+
# |                                 |       |     |            |
# |   A SPECIFIC USER:              |       |     |            |
# +---------------------------------+-------+-----+------------+
# |~/.bash_profile    (bash only)   |   B1  |     |            | (doesn't currently exist) 
# +---------------------------------+-------+-----+------------+
# |~/.bash_login      (bash only)   |   B2  |     |            | (didn't exist) **
# +---------------------------------+-------+-----+------------+
# |~/.profile         (all shells)  |   B3  |     |            | (doesn't currently exist)
# +---------------------------------+-------+-----+------------+
# |~/.bashrc          (bash only)   |  (B2) |  B  |            | colorizes bash: su=red, other_users=green
# +---------------------------------+-------+-----+------------+
# |                                 |       |     |            |
# +---------------------------------+-------+-----+------------+
# |~/.bash_logout                   |    C  |     |            |
# +---------------------------------+-------+-----+------------+
#
# ** (sources !/.bashrc to colorize login, for when booting into non-gui)

Và ghi chú này ở đầu của mỗi tệp thiết lập khác để tham chiếu đến nó:

# TIP: SEE TABLE in /etc/profile of BASH SETUP FILES AND THEIR LOAD SEQUENCE

Đáng chú ý tôi nghĩ là / Debian / profile của Debian theo các nguồn mặc định (bao gồm) /etc/bash.bashrc (đó là khi /etc/bash.bashrc tồn tại). Vì vậy, tập lệnh đăng nhập đọc cả hai tập tin / etc, trong khi không đăng nhập chỉ đọc bash.bashrc.

Cũng cần lưu ý rằng /etc/bash.bashrc được đặt thành không làm gì khi nó không chạy tương tác. Vì vậy, hai tập tin này chỉ dành cho các kịch bản tương tác.


4

Bản thân logic cấu hình của bash không phức tạp và được giải thích trong các câu trả lời khác trong trang này, trên serverfault và trong nhiều blog. Tuy nhiên, vấn đề là các bản phân phối Linux tạo ra bash , ý tôi là sự phức tạp và nhiều cách họ định cấu hình bash theo mặc định. http://mywiki.wooledge.org/DotFiles đề cập ngắn gọn về một số những điều kỳ quặc này. Đây là một dấu vết mẫu trên Fedora 29, nó cho thấy tập tin nào nguồn (các) tập tin khác và theo thứ tự cho một kịch bản rất đơn giản: kết nối từ xa với ssh và sau đó bắt đầu một chuỗi con khác:

ssh fedora29
 └─ -bash # login shell
      ├── /etc/profile
      |    ├─ /etc/profile.d/*.sh
      |    ├─ /etc/profile.d/sh.local
      |    └─ /etc/bashrc
      ├── ~/.bash_profile
      |    └─ ~/.bashrc
      |          └─ /etc/bashrc
      |
      |
      └─ $ bash  # non-login shell
            └─ ~/.bashrc
                 └─ /etc/bashrc
                       └─ /etc/profile.d/*.sh

Logic phức tạp nhất của Fedora là trong /etc/bashrc. Như đã thấy ở trên /etc/bashrclà một tập tin bash tự nó không biết, ý tôi là không trực tiếp. Các /etc/bashrcxét nghiệm của Fedora cho dù:

  • nó được cung cấp bởi một vỏ đăng nhập,
  • nó có nguồn gốc từ một vỏ tương tác,
  • nó đã có nguồn gốc

... Và sau đó làm những điều hoàn toàn khác nhau tùy thuộc vào những điều đó.

Nếu bạn nghĩ rằng có thể nhớ biểu đồ ở trên thì quá tệ vì nó gần như không đủ: biểu đồ này chỉ mô tả chỉ một kịch bản, những điều hơi khác nhau xảy ra khi chạy các tập lệnh không tương tác hoặc bắt đầu một phiên đồ họa. Tôi đã bỏ qua ~/.profile. Tôi đã bỏ qua bash_completioncác tập lệnh. Vì lý do tương thích ngược, hãy gọi bash /bin/shthay vì thay /bin/bashđổi hành vi của nó. Còn zsh và các shell khác thì sao? Và tất nhiên các bản phân phối Linux khác nhau làm những việc khác nhau, ví dụ Debian và Ubuntu đi kèm với một phiên bản không chuẩn của bas h, nó có các tùy chỉnh dành riêng cho Debian. Nó đáng chú ý tìm kiếm một tập tin bất thường:/etc/bash.bashrc. Ngay cả khi bạn dính vào một bản phân phối Linux duy nhất, nó có thể phát triển theo thời gian. Đợi đã: chúng tôi thậm chí chưa từng chạm vào macOS, FreeBSD, ... Cuối cùng, chúng ta hãy suy nghĩ cho người dùng bị mắc kẹt với những cách thậm chí sáng tạo hơn mà quản trị viên của họ đã cấu hình hệ thống họ phải sử dụng.

Khi dòng thảo luận không bao giờ kết thúc về chủ đề này chứng minh, đó là một nguyên nhân đã mất. Miễn là bạn chỉ muốn thêm các giá trị mới, một số "thử và sai" có xu hướng là đủ. Thú vui thực sự bắt đầu khi bạn muốn sửa đổi trong một (người dùng) tệp một cái gì đó đã được xác định trong một tệp khác (trong / etc). Sau đó, hãy chuẩn bị để dành một chút thời gian để thiết kế một giải pháp sẽ không bao giờ có thể mang theo được.

Để có một chút thú vị cuối cùng, đây là "biểu đồ nguồn" cho cùng một kịch bản đơn giản trên Clear Linux kể từ tháng 6 năm 2019:

ssh clearlinux
 └─ -bash # login shell
      ├── /usr/share/defaults/etc/profile
      |    ├─ /usr/share/defaults/etc/profile.d/*
      |    ├─ /etc/profile.d/*
      |    └─ /etc/profile
      ├── ~/.bash_profile
      |
      |
      └─  $ bash   # non-login shell
           ├─ /usr/share/defaults/etc/bash.bashrc
           |      ├─ /usr/share/defaults/etc/profile
           |      |    ├─ /usr/share/defaults/etc/profile.d/*
           |      |    ├─ /etc/profile.d/*
           |      |    └─ /etc/profile
           |      └─ /etc/profile
           └─ ~/.bashrc
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.