Tại sao liên kết mềm này không hoạt động như mong đợi?


11
bash4.3 # pwd
/bin
bash4.3 # ll sh
lrwxrwxrwx. 1   root    root    4   May 17 22:22 sh -> bash
bash4.3 # ll bash
-rwxr-xr-x. 1   root    root    1072056 May 17 22:22 bash
bash4.3 # bash
bash4.3 # sh
sh-4.3#

Hệ điều hành của tôi là fedora 24 (Phiên bản Gnome mặc định).

Từ ví dụ, chúng ta có thể biết: dưới /bin, bashlà một tệp thực thi nhị phân; shlà một liên kết mềm đến bash.

Vì vậy, theo hiểu biết của tôi, type bash and press enternên có kết quả chính xác như type sh and press enter.

Khi tôi type bash and press enter, tôi nhận được [root@localhost bin]#như mong đợi.

Tuy nhiên, nếu tôi type sh and press enter, tôi ngạc nhiên nhận được sh-4.3#.

Nguyên nhân là gì?


Văn bản có thể dễ dàng được sao chép vào trình chỉnh sửa SE vì hình ảnh khá khó chịu, vì vậy vui lòng không làm điều này. Thay vào đó, chọn văn bản trong thiết bị đầu cuối của bạn và nhấn CTRL-SHIFT-C.
con mèo

Câu trả lời:


25

Đó là một tính năng tài liệu.

Nếu bạn chạy bash thông qua một liên kết tượng trưng có tên sh, bash sẽ bắt đầu ở shchế độ tương thích.

Từ man bash:

Nếu bash được gọi với tên sh, nó sẽ cố gắng bắt chước hành vi khởi động của các phiên bản lịch sử của sh càng gần càng tốt, đồng thời tuân thủ tiêu chuẩn POSIX. Khi được gọi dưới dạng vỏ đăng nhập tương tác hoặc vỏ không tương tác với tùy chọn --login, trước tiên, nó sẽ cố gắng đọc và thực thi các lệnh từ / etc / profile và ~ / .profile, theo thứ tự đó. Tùy chọn --noprofile có thể được sử dụng để ức chế hành vi này. Khi được gọi dưới dạng shell tương tác với tên sh, bash tìm biến ENV, mở rộng giá trị của nó nếu nó được xác định và sử dụng giá trị mở rộng làm tên của tệp để đọc và thực thi. Do shell được gọi là sh không cố đọc và thực thi các lệnh từ bất kỳ tệp khởi động nào khác, nên tùy chọn --rcfile không có hiệu lực. Một vỏ không tương tác được gọi với tên sh không cố đọc bất kỳ tệp khởi động nào khác. Khi được gọi là sh, bash sẽ chuyển sang chế độ posix sau khi các tệp khởi động được đọc.

Làm thế nào để một chương trình biết tên đã được sử dụng để bắt đầu nó?

Nếu nó là chương trình ac, nó có thể kiểm tra argv[0]. Nếu nó là một kịch bản shell hoặc perl, nó có thể kiểm tra $0.

Ví dụ, hãy xem xét kịch bản shell đơn giản này:

$ cat utc
#!/bin/sh
case "${0##*/}" in
        utc) date -u ;;
        et) TZ=US/Eastern date ;;
esac

$0là tên mà kịch bản được gọi bởi. ${0##*/}là tên mà đoạn script được gọi với bất kỳ tên thư mục nào bị xóa.

Hãy tạo liên kết tượng trưng này:

ln -s utc et

Vì vậy, utcetcả hai đều chạy cùng thực thi nhưng chúng cung cấp kết quả khác nhau. Khi chạy như utc, nó xuất ra thời gian phổ quát. Khi chạy như et, là đầu ra theo giờ miền Đông Hoa Kỳ. Ví dụ:

$ utc
Wed Jul 20 18:14:18 UTC 2016
$ et
Wed Jul 20 14:14:20 EDT 2016

4
Có thể muốn thêm làm thế nào điều này là có thể, vì OP hy vọng các cuộc gọi là giống hệt nhau. ( argv[0], obvs)
Các cuộc đua nhẹ nhàng trong quỹ đạo

@LightnessRacesinOrbit Ý kiến ​​hay. Tôi đã thêm một ví dụ.
John1024

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.