Cách thích hợp để phân phối các tập lệnh shell


8

Cách thích hợp nhất để phân phối các kịch bản shell, nếu hành vi của shell có thể được sửa đổi setvà do đó không thể đoán trước được?

Ví dụ, rm *.txtsẽ không được thực thi như mong đợi trên các môi trường set -fđã được chạy. Làm cách nào để đảm bảo rm *.txtxóa tất cả các tệp văn bản trong thư mục hiện tại trong bất kỳ môi trường nào?

Làm thế nào để tôi chắc chắn rằng các kịch bản shell sẽ chạy như mong đợi trước khi phân phối chúng nói chung?


shell_state=$(set +o) ... kịch bản ...eval "$shell_state"
mikeerv

Bạn có thể chạy các lệnh đó ở đầu tập lệnh hoặc sửa đổi #!để chỉ định tùy chọn shell nào bạn muốn.
HalosGhost

Câu trả lời:


6

Các tập lệnh Shell thường được xử lý như thể chúng giống như bất kỳ loại tập tin thực thi nào khác, chẳng hạn như tệp nhị phân, tập lệnh Python, tập lệnh Perl hoặc bất kỳ loại tập lệnh nào khác. Họ có một shebang ở đầu chỉ đạo kernel thực thi chúng thông qua shell. Chúng được dự kiến ​​sẽ được gọi giống như bất kỳ lệnh nào khác.

Như vậy, một shell mới được khởi động mỗi khi script được gọi và bất kỳ cài đặt nào như set -fhiện diện trong shell gọi hoặc trong bất kỳ trường hợp shell nào khác trong hệ thống đều không liên quan.

Tất nhiên, người dùng có thể lấy tập lệnh của bạn thay vì chạy tập lệnh, ví dụ như thế này:

. /path/to/your/script

hoặc để thực thi nó trong trình bao có các cài đặt không mặc định như thế này:

sh -f /path/to/your/script

nhưng những cách đó không được coi là cách thông thường hoặc gọi kịch bản của bạn và những người dùng làm điều đó sẽ mong đợi bất cứ điều gì họ nhận được như là kết quả.

Lưu ý rằng có một số tập lệnh được dự định có nguồn gốc, không được thực thi, vì mục đích của chúng là nhằm thay đổi cwd hoặc đặt các biến môi trường phải được phản ánh trong môi trường của vỏ tìm nguồn, nhưng chúng là thiểu số và nó thường được thực hiện như một phần của giao thức đã thỏa thuận. Các tệp này có thể được coi là giống như "bổ trợ" cho bất kỳ hệ thống nào mà chúng mong đợi có nguồn gốc, không nhiều như các tập lệnh độc lập. Ví dụ: các tệp /etc/rc*.dcó tên kết thúc .shđược lấy từ hệ thống con tập lệnh khởi động, không được thực thi và được ghi lại rằng đây là điều sẽ xảy ra nếu bạn đặt một tệp có tên như vậy vào/etc/rc*.dvà khi nó được thực hiện nó có mục đích. Quy ước đặt tên các tệp dự định có nguồn gốc thay vì được thực hiện theo cách này cũng được tuân theo ở nơi khác, nhưng không phổ biến.

Đúng là các tệp dự định có nguồn gốc theo cách này phải quan tâm đến những cài đặt nào có thể có trong môi trường trình gọi của chúng có thể ảnh hưởng đến hành vi của trình bao, nhưng sau đó, giao thức đã thỏa thuận sẽ hứa hẹn một môi trường thực thi có thể dự đoán được.


1
zshcó một tính năng cho phép khôi phục các tùy chọn về một bộ biết trong ngữ cảnh cục bộ ( emulate -L zsh) được sử dụng rộng rãi trong tất cả các tiện ích mở rộng được vận chuyển với zsh và được viết dưới dạng mã zsh. Xem cách hệ thống hoàn thành bash thất bại thảm hại nếu bạn đặt một số tùy chọn như thế nào failglob.
Stéphane Chazelas

Một số shell đọc tệp tùy chỉnh của bạn ngay cả khi được gọi để giải thích các tập lệnh. Đó là lý do tại sao bạn thường sử dụng #! /bin/csh -fthay vì #! /bin/cshví dụ.
Stéphane Chazelas

@ StéphaneChazelas Haha, đúng vậy. Tất nhiên đó là một phần lý do tại sao sử dụng csh là một ý tưởng tồi , phải không? :-) Nhưng tôi đoán zsh cũng có dạng đó zshenv. Cẩn thận những gì bạn đưa vào zshenvvì lý do đó!
Celada

Nhân tiện, @ StéphaneChazelas, đây không phải là lần đầu tiên bạn dạy tôi điều gì đó mà tôi không biết ( emulate -Ltrong trường hợp này) bằng cách bình luận về một trong những câu trả lời của tôi và tôi đánh giá cao nó.
Celada

Chà, ~/.zshenv(nơi bạn muốn buộc cài đặt (thường là env vars) cho tất cả các zsh (tương tác hay không) được gọi dưới tên của bạn và thường không được sử dụng ngoại trừ để giải quyết một số vấn đề không phải zsh khác) tách biệt với ~/.zshrc(tương tác vỏ tùy biến), vì vậy, nó là một tính năng, không phải là một lỗi. (bạn có thể sử dụng zsh -f) Lỗi là khi một số shell bash không tương tác đọc ~/.bashrc(như trên ssh và bạn phải thêm mã để bảo vệ chống lại điều đó) hoặc một số bash tương tác (những cái đăng nhập) không đọc nó (và một lần nữa, bạn phải thêm mã vào ~/.bash_profileđể làm việc xung quanh nó).
Stéphane Chazelas
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.