Tại sao echo một shell được xây dựng trong lệnh?


34
$ which echo
echo: shell built-in command.
$ which ls
/bin/ls
$ which cat
/bin/cat

Tại sao tiếng vang không phải là một tiện ích độc lập như ls, ps, catvv? Tại sao nó là vỏ cụ thể? Bất kỳ lý do tốt?


5
Hãy nhớ rằng đây là vỏ cụ thể. ZSH xây dựng nó trong, BASH thì không.
tsvallender

21
@tsv: echochắc chắn nhất một nội dung Bash. Trên thực tế, đó là một nội dung trong mọi vỏ hiện đại chính.
Tạm dừng cho đến khi có thông báo mới.

Câu trả lời:


71

Có hai lớp dựng sẵn:

  1. Một số lệnh phải được tích hợp vào chính chương trình shell vì chúng không thể hoạt động nếu chúng ở bên ngoài.

    cdlà một thứ như vậy vì nếu nó ở bên ngoài, nó chỉ có thể thay đổi thư mục của chính nó; nó không thể ảnh hưởng đến thư mục làm việc hiện tại của shell. (Xem thêm: Tại sao cdkhông phải là một chương trình? )

  2. Các lớp lệnh khác được xây dựng vào vỏ hoàn toàn cho hiệu quả.

    Các trang người đàn ông có một phần trên builtins đó đề cập đến , và như ví dụ về các lệnh trong lớp này.dash printfechotest

Các hệ thống Unix luôn bao gồm các tệp thực thi riêng cho các lệnh trong lớp thứ hai đó. Các tệp thực thi riêng biệt này vẫn có sẵn trên mọi hệ thống Unix mà tôi đã sử dụng, mặc dù chúng cũng được tích hợp vào mọi vỏ bạn có thể sử dụng. ( POSIX thực sự yêu cầu những thực thi này phải có mặt.)

Tôi tin rằng echođã được tích hợp vào hệ vỏ trong AT & T Unix System V Release 3.1. Tôi dựa trên sự so sánh của hai phiên bản hướng dẫn sử dụng khác nhau cho các hệ thống Unix dòng AT & Ts 3B1 . Ai đó đã quét các phiên bản 1986 của các hướng dẫn này và đưa chúng lên mạng ; những cái này tương ứng với bản phát hành gốc của SVR3. Bạn có thể thấy điều đó echokhông có trong danh sách ở trang 523 của Hướng dẫn sử dụng UNIX System V, Tập II , nơi bạn mong đợi nếu lệnh được tích hợp vào trình bao. Trong bản sao giấy địa phương của tôi về hướng dẫn sử dụng SVR3.1 từ năm 1987, echo được liệt kê trong phần này của hướng dẫn.

Tôi khá chắc chắn rằng đây không phải là một sáng tạo CSRG của Berkeley mà AT & T đã mang về nước. 4.3BSD ra đời cùng năm với SVR3, 1986, nhưng nếu bạn xem trang chủ sh.1 của 4.3BSD , bạn sẽ thấy rằng echonó không nằm trong danh sách các lệnh tích hợp của phần "Lệnh đặc biệt". Nếu CSRG làm điều này, điều đó khiến chúng tôi muốn có một nguồn tài liệu để chứng minh điều đó.

Tại thời điểm này, bạn có thể tự hỏi liệu có echođược tích hợp vào vỏ sớm hơn SVR3.1 hay không và thực tế điều này chỉ đơn giản là không được ghi nhận cho đến lúc đó. Mã nguồn Unix-SVR3 AT & T mới nhất có sẵn cho tôi là trong tarball PDP-11 System III , trong đó bạn sẽ tìm thấy mã nguồn vỏ Bourne. Bạn sẽ không tìm thấy echotrong bảng lệnh dựng sẵn /usr/src/cmd/sh/msg.c. Dựa trên dấu thời gian trong tệp đó, điều đó chứng tỏ rằng echochắc chắn không có trong vỏ năm 1980.


Câu đố

Cùng một thư mục cũng chứa một tệp được gọi là builtin.ckhông chứa bất cứ điều gì về câu hỏi này, nhưng chúng tôi thấy nhận xét thú vị này:

/*      
    builtin commands are those that Bourne did not intend
    to be part of his shell.
    Redirection of i/o, or rather the lack of it, is still a
    problem..
*/      

Trên trang 385 của SysV UM, Vol II mà bạn đã đề cập, có printlệnh dựng sẵn cho ksh được cho là hoạt động như thế nào echo. Lệnh này cũng có trong một cái gì đó giống như AT & T Unix SVR4 2.1 i386 từ ISC. print "\012"mang lại kết quả tương tự như tiếng vang. Tự hỏi tại sao ksh có in và không tích hợp echo? Dù sao thực sự thú vị.

Có bao nhiêu viên đá quý như vậy từ một vài năm trước đang lẻn chờ đợi để được khai quật bởi một chỉnh sửa vào năm 2016? +1
iruvar

+1. Cảm ơn. Bạn có thể cung cấp các nguồn (tài liệu tham khảo) cho mục đích tạo một lệnh dựng sẵn, cho việc đọc / học (có hệ thống) của tôi không?
Tim

Tôi muốn tìm một số tài liệu tham khảo, hướng dẫn hoặc tiêu chuẩn để đọc hoặc tìm hiểu một cách có hệ thống. Tôi đã cố gắng tra cứu nó trong hướng dẫn tham khảo bash và thông số kỹ thuật POSIX. Nhưng tôi không thể tìm thấy nó. Tôi không chắc chắn nếu tôi nhớ họ.
Tim

@Tim: Vì điều này và các câu trả lời khác ở đây giải thích, một số lệnh phải được tích hợp vào trình bao hoặc chúng không thể thực hiện công việc của chúng. Tất cả những người khác là hoàn toàn tùy chọn . Thực chất đó là những gì đoạn trích nguồn vỏ Bourne của tôi nói ở trên, trên thực tế. Vì việc xây dựng các lệnh như vậy vào hệ vỏ là tùy chọn, một lý do có thẩm quyền chỉ có thể đưa ra ý kiến ​​của một người thực hiện.
Warren Young

19

Có một lý do thứ ba để một số lệnh được tích hợp sẵn: Chúng có thể được sử dụng khi chạy các lệnh bên ngoài là không thể.

Đôi khi một hệ thống trở nên hỏng đến mức lslệnh không hoạt động. Trong một số trường hợp, một echo *vẫn sẽ làm việc.

Một ví dụ khác (quan trọng hơn!) Là kill: Nếu một hệ thống hết PID miễn phí, thì không thể chạy được /bin/kill(vì nó cần một PID :-), nhưng tích hợp killsẽ hoạt động.

Btw., whichLà một lệnh bên ngoài (ít nhất nó không phải là nội bộ trong bash), vì vậy nó không thể liệt kê các lệnh nội bộ. Ví dụ:

$ which echo
/bin/echo
$ type -a echo
echo is a shell builtin
echo is /bin/echo

Đừng quên rằng hầu hết tất cả các tệp thực thi bên ngoài đều dựa vào các tệp thư viện. Đôi khi thảm họa xảy ra và những thư viện đó không thể được tải (lời khuyên: KHÔNG BAO GIỜ xảy ra ldconfigtrừ khi bạn biết CHÍNH XÁC những gì bạn đang làm). Ngoài ra, điều gì sẽ xảy ra nếu bạn thổi bay / bin của bạn, hoặc tệ hơn là phân vùng / sbin của bạn, nhưng vẫn có một vỏ được tải?
LawrenceC

Nếu bạn hết PID, có thể khó tìm ra loại PID nào bạn muốn tiêu diệt. Bạn không thể chạy một pslệnh, vì vậy bạn sẽ phải tìm các PID theo cách thủ công thông qua /proc.
kasperd

Mặc dù trên (ít nhất) CentOS whichlà một bí danh bash chạy alias | /usr/bin/which --read-alias ...để bên ngoài which có thể xác định các bí danh (nhưng vẫn không phải là nội trang). Tôi không thể quyết định xem xét điều này xuất sắc hay biến thái.
dave_thndry_085

Tại thời điểm lệnh ls không hoạt động nữa, tôi nghĩ bạn nên gắn ổ đĩa làm nô lệ thay vì khởi động / chính và sửa cấu trúc tệp theo cách đó. Tôi không chắc chắn làm thế nào bạn có thể khắc phục mức độ hỏng hệ thống đó bằng tiếng vang trừ khi bạn lặp lại> vào một tệp và sẽ mất nhiều thời gian để khắc phục. Cấp cho bạn có thể viết một tập lệnh bash đó là để sửa cấu trúc hệ thống.
jonnyjandles

13

Theo tài liệu tham khảo Bash , đó là về sự tiện lợi.

Shell cũng cung cấp một tập hợp nhỏ các lệnh tích hợp (dựng sẵn) thực hiện chức năng không thể hoặc bất tiện để có được thông qua các tiện ích riêng biệt. Ví dụ, cd, break, continue và exec) không thể được thực hiện bên ngoài shell vì chúng trực tiếp thao tác với shell. Lịch sử, getopts, kill hoặc pwd, trong số những thứ khác, có thể được triển khai trong các tiện ích riêng biệt, nhưng chúng thuận tiện hơn để sử dụng như các lệnh dựng sẵn. Tất cả các nội dung shell được mô tả trong các phần tiếp theo.

Các chi tiết Bash Scripting Guide có một lời giải thích chi tiết hơn:

"Nội dung là một lệnh có trong bộ công cụ Bash, được xây dựng theo nghĩa đen. Đây là vì lý do hiệu năng - nội dung thực thi nhanh hơn các lệnh bên ngoài, thường yêu cầu hủy bỏ 1 quy trình riêng biệt - hoặc vì một công cụ cụ thể cần trực tiếp truy cập vào bên trong vỏ. "

Cũng lưu ý rằng echokhông tồn tại như một tiện ích độc lập trên một số hệ thống. Đây là những gì tôi có trên hệ thống Darwin của mình (MacOSX 10.5.8 - Leopard)

$ uname -a
Darwin host.foo.org 9.8.0 Darwin Kernel Version 9.8.0: Wed Jul 15 16:55:01 PDT 2009; root:xnu-1228.15.4~1/RELEASE_I386 i386
$ bash --version
GNU bash, version 3.2.17(1)-release (i386-apple-darwin9.0)
Copyright (C) 2005 Free Software Foundation, Inc.
$ which echo
/bin/echo

echocũng có sẵn dưới dạng dựng sẵn, nhưng rõ ràng các tập lệnh của tôi sử dụng / bin / echo trên máy Mac của tôi và sử dụng hàm dựng sẵn Bash trên hầu hết các hệ thống Linux & FreeBSD của tôi. Nhưng điều đó dường như không quan trọng, bởi vì các kịch bản vẫn hoạt động tốt ở mọi nơi.


3
Nói về shell-in, bạn nên sử dụng "type" thay vì "which".
Teddy

Cảm ơn @Teddy. Tôi đã bắt đầu làm điều đó, khi tôi nhớ. Cuộc sống tốt hơn nhiều nhờ type.
Stefan Lasiewski

6

Để bổ sung cho câu trả lời của bhm, giả sử /binđã vô tình bị xóa khỏi câu trả lời của bạn PATH. Bạn muốn có thể echo $PATHtìm ra điều đó, phải không?


2

Mặc dù hầu hết các shell bao gồm một tích hợp sẵn echohiện nay, GNU CoreUtils cũng bao gồm một triển khai độc lập của nó:

$ which echo
/bin/echo
$ dpkg -S /bin/echo
coreutils: /bin/echo

Có vẻ như bạn chưa cài đặt GNU Coreutils (hầu hết các hệ điều hành máy chủ và máy tính để bàn dựa trên linux đều được cài đặt theo mặc định, nhưng nhúng linux hoặc UNIX khác có thể sử dụng các bộ sưu tập tiện ích shell thay thế).

BTW: nếu bạn nhìn vào Busybox , bạn sẽ thấy rằng ls, pscatcũng được tích hợp trong các lệnh có (hoặc ít nhất có thể, nó được sử dụng cho các hệ thống embeded và tất cả mọi thứ không cần thiết có thể được bỏ qua).


3
Các bài kiểm tra của người đăng ban đầu không ủng hộ giả thuyết /bin/echokhông tồn tại. Họ chỉ cho thấy rằng nội dung được ưu tiên hơn bất kỳ echochương trình nào trong PATH.
Warren Young

1

Đây là lý do thực sự tại sao echonên là một vỏ dựng sẵn:

Giả sử bạn có mật khẩu $PASSWORD. Làm thế nào để bạn viết nó vào một tập tin ./password? Đương nhiên hầu hết các lập trình viên sẽ viết:

echo "$PASSWORD" >./password

Tuy nhiên, nếu echokhông phải là shell dựng, mật khẩu sẽ bị rò rỉ cho tất cả người dùng thông qua psthông tin.

Tất nhiên, nếu bạn muốn khéo léo về nó, bạn có thể tìm cách lưu trữ mật khẩu mà không cần echokhai thác một số tính năng shell khác:

cat >./password <<EOF
${PASSWORD}
EOF

Tuy nhiên, việc tích hợp echosẵn là một dây an toàn quan trọng vì cách rõ ràng nhất để lưu mật khẩu vào tệp cũng hoạt động.


3
Trong khi một tác dụng phụ hữu ích tôi thấy rất nghi ngờ rằng đây là lý do.
cắm vào

@DepressionDaniel: Điều gì làm bạn sao lưu? Đâu là tài liệu tham khảo bạn sử dụng để hỗ trợ câu trả lời của bạn?
đùa
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.