Tại sao bash thậm chí phân tích cú pháp / chạy công cụ đặt trong biến môi trường?


9

Các shellshock lỗi trong bash làm việc bằng cách biến môi trường. Thành thật mà nói tôi đã ngạc nhiên bởi thực tế là có một tính năng như:

"truyền các định nghĩa hàm thông qua env vars"

Do đó, câu hỏi này trong khi có thể không được xây dựng hoàn hảo là hỏi ví dụ hoặc trường hợp cần có tính năng này?

Tặng kem. Các shell khác zsh, dash, vv cũng có tính năng này?


Nó sử dụng các lọ env để truyền các định nghĩa hàm. Bạn có ý nghĩa gì với "Tại sao nó không chỉ đơn giản là giữ các biến môi trường có sẵn / có thể truy cập được?" ?
Anthon

@Anthon Cảm ơn bạn đã bình luận. Có lẽ tôi nên rõ ràng hơn và viết lại. Vì lý do gì cần thiết để có thể truyền các định nghĩa hàm thông qua env vars?
nhân

1
Tôi không chắc chắn 100% nhưng tôi nghĩ rằng đó là cách mà GNU parallelcó được các định nghĩa hàm được phân phối nếu nó gọi nhiều trường hợp bash. Nếu không theo cách đó, nó sẽ phải ghi những thứ đó vào một tệp, rằng mỗi cá thể được gọi sẽ đọc và sau đó bạn phải xử lý các vấn đề như khi tệp đó có thể được gỡ bỏ.
Anthon

2
này đề có một số lịch sử với nó. chức năng xuất khẩu, mặc dù, là điên rồ . nếu bạn muốn một shell mới kế thừa các lệnh thực thi shell cũ, bạn sẽ .dotlấy cùng một tệp mà shell cũ đã làm. đó là cách nó được thực hiện - và điều đó có ý nghĩa - hoặc bạn cung cấp shell mới cho tệp làm đầu vào khi execing. một khi nó đọc trong một lần tập tin được lưu trữ bởi kernel.
mikeerv

@mikeerv Tôi có hiểu đúng không, rằng một phần lớn của shellshock có liên quan đến tính năng này không phải là quá nhiều thiết yếu?
nhân

Câu trả lời:


4

Khi một tập lệnh gọi một tập lệnh khác, các biến của tập lệnh mẹ có thể được xuất ra và sau đó chúng sẽ hiển thị trong tập lệnh con. Xuất các hàm là một khái quát rõ ràng: xuất hàm từ cha mẹ, làm cho nó hiển thị ở trẻ.

Môi trường là cách thuận tiện duy nhất mà một quá trình có thể truyền dữ liệu tùy ý cho con của nó. Dữ liệu phải được sắp xếp thành các chuỗi không chứa byte rỗng, điều này không gây khó khăn cho các hàm shell. Có các phương pháp tiềm năng khác, chẳng hạn như khối bộ nhớ dùng chung hoặc tệp tạm thời được truyền qua bộ mô tả tệp, nhưng chúng có thể gây ra sự cố với các chương trình trung gian không biết phải làm gì với chúng hoặc sẽ đóng chúng. Các chương trình dự kiến ​​sẽ chạy trong một môi trường có chứa các biến mà họ không biết hoặc không quan tâm, vì vậy họ sẽ không ghi đè hoặc xóa chúng.

Việc lựa chọn sử dụng tên hàm làm tên của biến môi trường là một điều lạ. Đối với một điều, nó có nghĩa là một biến xuất khẩu đụng độ với một hàm xuất cùng tên.

Các chức năng xuất khẩu là một tính năng cũ. Các chức năng đã được thêm vào trình bao Bourne trong SVR2 và các chức năng được xuất trong trình bao Phiên bản 8 được phát hành cùng năm (1984). Trong shell đó, các biến và hàm sử dụng cùng một không gian tên. Tôi không biết làm thế nào chức năng xuất khẩu làm việc. Các gia truyền vỏ được dựa trên một biến thể Bourne trong đó có chức năng nhưng không xuất chúng.

ATT ksh được cho là hỗ trợ xuất các chức năng, nhưng nhìn vào nguồn hoặc chơi với nó, tôi không thể thấy rằng nó hoạt động, kể từ ksh93u.

env -i /usr/bin/ksh -c 'f=variable; f () { echo function; }; typeset -fx f; /usr/bin/env; ksh -c f'
_=*25182*/usr/bin/env
PWD=/home/gilles
SHLVL=1
A__z="*SHLVL
ksh: f: not found

Bản sao miền công cộng của Ksh (pdksh, mksh), dash và zsh không hỗ trợ chức năng xuất.


1
cảm ơn bạn! Vì vậy, không có chức năng xuất khẩu, chức năng tính năng bị mất, nhưng có một số shell như dash, zsh và pdksh, v.v ... thiếu tính năng này, tôi có đọc đúng không?
nhân

Nhưng khi tôi xuất một hàm trong bash, nó sẽ chuyển thành một biến như thế nào BASH_FUNC_f%%=() { echo hi }. Tại sao bash phân tích các biến môi trường khác? Tại sao nó thậm chí còn phân tích cú pháp BASH_FUNC_g%%khi tôi chỉ gọi f? (Rõ ràng, tiền vỏ, biến môi trường chỉ được gọi fhoặc g- nhưng tôi vẫn tự hỏi tại sao gsẽ bị phân tách nếu tôi không gọi gtrong kịch bản của mình)
Biến thái

@Met Nó phải xem xét tất cả các biến môi trường để tìm ra biến nào là định nghĩa hàm. Nó có thể ghi nhớ thực tế đó và tránh phân tích mã của hàm cho đến lần đầu tiên cần, nhưng đó sẽ là độ phức tạp bổ sung để thu được rất ít. Thật dễ dàng hơn khi chỉ có một loại hàm chứ không phải hai ("hàm bình thường" và "hàm từ một biến môi trường cần một chút phân tích cú pháp").
Gilles 'SO- ngừng trở nên xấu xa'

Không rõ ràng. Tôi đề nghị rằng điều hiển nhiên cần làm là, khi tôi chạy một cái gì đó được gọi f, (1) kiểm tra hàm shell được gọi f, (2) kiểm tra biến môi trường được gọi fvà thử phân tích nó, (3) kiểm tra mỗi PATHthành phần cho một thực thi được gọi f. Làm thế nào có thể phân tích mọi biến môi trường như mã shell, khi khởi động shell, có vẻ như là một thiết kế ít phức tạp hơn?
Biến thái

@Metamorphic Bạn đang đề xuất thêm một bước nữa phải được thực hiện trên mỗi lệnh. Bạn cũng phải thêm một bước nữa khi xác định hoặc xác định hàm (sau unset -f foo, bash không được tìm định nghĩa hàm cho foomôi trường nữa), khi liệt kê các hàm (bạn xử lý như thế nào declare -fngoài việc đọc tất cả các biến môi trường?) và bất cứ điều gì khác tôi không nghĩ đến. Thiết kế của bạn chỉ có vẻ dễ dàng hơn vì bạn đã bỏ qua phần lớn. Ngược lại, làm mọi thứ khi khởi động là một đoạn mã duy nhất và sau đó mọi thứ chỉ hoạt động.
Gilles 'SO- ngừng trở nên xấu xa'
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.