Đây là một câu hỏi mà tôi sẽ gửi ở đây một vài tuần trước. Giống như terdon , tôi hiểu rằng a .bashrc
chỉ có nguồn gốc cho các vỏ Bash tương tác nên không cần phải .bashrc
kiểm tra nếu nó đang chạy trong một vỏ tương tác. Một cách khó hiểu, tất cả các bản phân phối tôi sử dụng (Ubuntu, RHEL và Cygwin) đều có một số loại kiểm tra (thử nghiệm $-
hoặc $PS1
) để đảm bảo trình bao hiện tại có tương tác. Tôi không thích lập trình sùng bái hàng hóa vì vậy tôi bắt đầu tìm hiểu mục đích của mã này .bashrc
.
Bash có một trường hợp đặc biệt cho đạn pháo từ xa
Sau khi nghiên cứu vấn đề, tôi phát hiện ra rằng vỏ từ xa được xử lý khác nhau. Mặc dù các shell Bash không tương tác thường không chạy ~/.bashrc
các lệnh khi khởi động, một trường hợp đặc biệt được tạo khi shell được gọi bởi trình nền shell từ xa :
Bash cố gắng xác định khi nào nó đang được chạy với đầu vào tiêu chuẩn của nó được kết nối với kết nối mạng, như khi được thực thi bởi trình nền shell từ xa, thường rshd
hoặc daemon shell an toàn sshd
. Nếu Bash xác định nó đang được chạy theo kiểu này, nó sẽ đọc và thực thi các lệnh từ ~ / .bashrc, nếu tệp đó tồn tại và có thể đọc được. Nó sẽ không làm điều này nếu được gọi là sh
. Các --norc
tùy chọn có thể được sử dụng để ngăn chặn hành vi này, và các --rcfile
tùy chọn có thể được sử dụng để buộc một tập tin được đọc, nhưng không phải rshd
và cũng không sshd
thường gọi vỏ với những tùy chọn hoặc cho phép họ được xác định.
Thí dụ
Chèn sau đây khi bắt đầu một điều khiển từ xa .bashrc
. (Nếu .bashrc
có nguồn gốc bởi .profile
hoặc .bash_profile
, tạm thời vô hiệu hóa điều này trong khi thử nghiệm):
echo bashrc
fun()
{
echo functions work
}
Chạy các lệnh sau cục bộ:
$ ssh remote_host 'echo $- $0'
bashrc
hBc bash
- Không
i
trong $-
chỉ ra rằng vỏ là không tương tác .
- Không hàng đầu
-
trong $0
chỉ ra rằng vỏ không phải là một vỏ đăng nhập .
Các hàm Shell được xác định trong điều khiển từ xa .bashrc
cũng có thể được chạy:
$ ssh remote_host fun
bashrc
functions work
Tôi nhận thấy rằng ~/.bashrc
là chỉ có nguồn gốc khi một lệnh được quy định như là đối số cho ssh
. Điều này có ý nghĩa: khi ssh
được sử dụng để bắt đầu một vỏ đăng nhập thông thường .profile
hoặc .bash_profile
được chạy (và .bashrc
chỉ có nguồn gốc nếu được thực hiện một cách rõ ràng bởi một trong những tệp này).
Lợi ích chính mà tôi có thể thấy là có .bashrc
nguồn gốc khi chạy lệnh từ xa (không tương tác) là các hàm shell có thể chạy được. Tuy nhiên, hầu hết các lệnh trong một điển hình .bashrc
chỉ có liên quan trong một vỏ tương tác, ví dụ, các bí danh không được mở rộng trừ khi vỏ đó tương tác.
Chuyển tập tin từ xa có thể thất bại
Đây thường không phải là vấn đề khi rsh
hoặc ssh
được sử dụng để bắt đầu một vỏ đăng nhập tương tác hoặc khi các vỏ không tương tác được sử dụng để chạy các lệnh. Tuy nhiên, nó có thể là một vấn đề cho các chương trình như rcp
, scp
và sftp
sử dụng vỏ từ xa để chuyển dữ liệu.
Hóa ra trình bao mặc định của người dùng từ xa (như Bash) được khởi động ngầm khi sử dụng scp
lệnh. Không có đề cập nào về điều này trong trang man - chỉ có một đề cập scp
sử dụng ssh
cho việc truyền dữ liệu của nó. Điều này có hậu quả là nếu .bashrc
chứa bất kỳ lệnh nào in ra đầu ra tiêu chuẩn, việc truyền tệp sẽ thất bại , ví dụ,
scp không có lỗi .
Xem thêm báo cáo lỗi Red Hat liên quan này từ 15 năm trước, scp bị phá vỡ khi có lệnh echo trong / etc / bashrc (cuối cùng đã bị đóng WONTFIX
).
Tại sao scp
và sftp
thất bại
SCP (Bản sao bảo mật) và SFTP (Giao thức truyền tệp an toàn) có các giao thức riêng cho các đầu cuối cục bộ và từ xa để trao đổi thông tin về (các) tệp được truyền. Bất kỳ văn bản bất ngờ nào từ đầu cuối đều bị hiểu sai là một phần của giao thức và quá trình chuyển không thành công. Theo một câu hỏi thường gặp từ Snail Book
Những gì thường xảy ra, tuy nhiên, được rằng có những báo cáo trong cả hai hệ thống hoặc các tập tin khởi động vỏ cho mỗi người dùng trên máy chủ ( .bashrc
, .profile
,
/etc/csh.cshrc
, .login
, vv) mà tin nhắn văn bản đầu ra trên đăng nhập, dự định sẽ được đọc bởi con người (như fortune
, echo "Hi there!"
, Vân vân.).
Mã như vậy chỉ nên tạo đầu ra trên thông tin đăng nhập tương tác, khi có
tty
gắn với đầu vào tiêu chuẩn. Nếu nó không thực hiện kiểm tra này, nó sẽ chèn các tin nhắn văn bản này vào nơi chúng không thuộc về: trong trường hợp này, làm ô nhiễm luồng giao thức giữa scp2
/ sftp
và sftp-server
.
Lý do các tập tin khởi động shell hoàn toàn có liên quan, đó là sshd
sử dụng trình bao của người dùng khi khởi động bất kỳ chương trình nào thay mặt người dùng
(sử dụng eg / bin / sh -c "lệnh"). Đây là một truyền thống Unix và có những lợi thế:
- Thiết lập thông thường của người dùng (bí danh lệnh, biến môi trường, ô, v.v.) có hiệu lực khi các lệnh từ xa được chạy.
- Thực tiễn phổ biến về việc đặt shell của tài khoản thành / bin / false để vô hiệu hóa nó sẽ ngăn chủ sở hữu chạy bất kỳ lệnh nào, vì vậy việc xác thực vẫn vô tình thành công vì một số lý do.
Chi tiết giao thức SCP
Đối với những người quan tâm đến các chi tiết về cách thức hoạt động của SCP, tôi đã tìm thấy thông tin thú vị trong cách thức giao thức SCP hoạt động bao gồm các chi tiết về Chạy scp với các cấu hình vỏ nói chuyện ở phía xa? :
Ví dụ, điều này có thể xảy ra nếu bạn thêm nó vào hồ sơ shell của mình trên hệ thống từ xa:
tiếng vang ""
Tại sao nó chỉ treo? Điều đó xuất phát từ cách thức scp
trong chế độ nguồn chờ xác nhận thông báo giao thức đầu tiên. Nếu nó không phải là nhị phân 0, nó hy vọng rằng đó là thông báo về sự cố từ xa và chờ thêm ký tự để tạo thông báo lỗi cho đến khi dòng mới xuất hiện. Vì bạn không in một dòng mới sau dòng đầu tiên, địa phương của bạn scp
chỉ ở trong một vòng lặp, bị chặn read(2)
. Trong khi đó, sau khi cấu hình shell được xử lý ở phía xa, scp
ở chế độ chìm được bắt đầu, nó cũng bị chặn read(2)
, chờ số 0 nhị phân biểu thị bắt đầu truyền dữ liệu.
Kết luận / TLDR
Hầu hết các câu lệnh trong một điển hình .bashrc
chỉ hữu ích cho một vỏ tương tác - không phải khi chạy các lệnh từ xa với rsh
hoặc ssh
. Trong hầu hết các tình huống như vậy, việc đặt các biến shell, bí danh và các hàm xác định là không mong muốn - và việc in bất kỳ văn bản nào thành tiêu chuẩn sẽ gây hại tích cực nếu chuyển các tệp bằng các chương trình như scp
hoặc sftp
. Thoát ra sau khi xác minh rằng trình bao hiện tại không tương tác là hành vi an toàn nhất cho .bashrc
.