Một subshell bắt đầu như một bản sao gần như giống hệt của quá trình shell ban đầu. Trong mui xe, shell gọi fork
hệ thống gọi 1 , tạo ra một quy trình mới có mã và bộ nhớ là bản sao 2 . Khi subshell được tạo, có rất ít sự khác biệt giữa nó và cha mẹ của nó. Đặc biệt, chúng có cùng các biến. Ngay cả $$
biến đặc biệt cũng giữ cùng một giá trị trong các lớp con: đó là ID tiến trình của shell gốc. Tương tự $PPID
là PID của cha mẹ của vỏ ban đầu.
Một vài shell thay đổi một vài biến trong subshell. Bash thiết lập BASHPID
cho PID của quá trình shell, thay đổi trong các lớp con. Bash, zsh và mksh sắp xếp $RANDOM
để mang lại các giá trị khác nhau trong cha mẹ và trong lớp con. Nhưng ngoài các trường hợp đặc biệt tích hợp như thế này, tất cả các biến có cùng giá trị trong lớp con như trong vỏ ban đầu, cùng trạng thái xuất, cùng trạng thái chỉ đọc, v.v. Tất cả các định nghĩa hàm, định nghĩa bí danh, tùy chọn vỏ và các cài đặt khác cũng được kế thừa.
Một subshell được tạo bởi (…)
có cùng mô tả tập tin như người tạo nó. Một số phương tiện khác để tạo các lớp con sửa đổi một số mô tả tệp trước khi thực thi mã người dùng; ví dụ, phía bên trái của một đường ống chạy trong một khung con 3 với đầu ra tiêu chuẩn được kết nối với đường ống. Subshell cũng bắt đầu với cùng một thư mục hiện tại, cùng mặt nạ tín hiệu, v.v ... Một trong vài trường hợp ngoại lệ là các subshell không kế thừa các bẫy tùy chỉnh: các tín hiệu bị bỏ qua ( ) vẫn bị bỏ qua trong subshell, nhưng các bẫy khác ( TÍN HIỆU ) được đặt lại đến hành động mặc định 4 .trap '' SIGNAL
trap CODE
Do đó, một subshell khác với việc thực thi một tập lệnh. Một kịch bản là một chương trình riêng biệt. Chương trình riêng biệt này có thể ngẫu nhiên cũng là một tập lệnh được thực hiện bởi cùng một trình thông dịch như cha mẹ, nhưng sự trùng hợp này không cung cấp cho chương trình riêng biệt bất kỳ khả năng hiển thị đặc biệt nào về dữ liệu nội bộ của cha mẹ. Các biến không xuất là dữ liệu nội bộ, do đó, khi trình thông dịch cho tập lệnh shell con được thực thi , nó không nhìn thấy các biến này. Các biến được xuất, tức là biến môi trường, được truyền đến các chương trình đã thực hiện.
Do vậy:
x=1
(echo $x)
in 1
bởi vì lớp vỏ là một bản sao của vỏ sinh ra nó.
x=1
sh -c 'echo $x'
tình cờ chạy shell như một tiến trình con của shell, nhưng x
trên dòng thứ hai không có nhiều kết nối với x
dòng thứ hai hơn trong
x=1
perl -le 'print $x'
hoặc là
x=1
python -c 'print x'
1 Một ngoại lệ là ksh93
lớp vỏ trong đó việc rèn được tối ưu hóa và hầu hết các tác dụng phụ của nó được mô phỏng.
2 Về mặt ngữ nghĩa, chúng là bản sao. Từ góc độ thực hiện, có rất nhiều chia sẻ đang diễn ra.
3 Đối với phía bên tay phải, nó phụ thuộc vào vỏ.
4 Nếu bạn kiểm tra điều này, lưu ý rằng những thứ như$(trap)
có thể báo cáo các bẫy của vỏ ban đầu. Cũng lưu ý rằng nhiều vỏ có lỗi trong các trường hợp góc liên quan đến bẫy. Ví dụ ninjalj lưu ý rằng kể từ bash 4.3, bash -x -c 'trap "echo ERR at \$BASH_SUBSHELL \$BASHPID" ERR; set -E; false; echo one subshell; (false); echo two subshells; ( (false) )'
chạy ERR
bẫy từ lớp con được lồng trong trường hợp hai lớp vỏ con, nhưng không phải ERR
bẫy từ lớp con trung gian - set -E
tùy chọn nên truyền báERR
bẫy tất cả các lớp con nhưng lớp con trung gian được tối ưu hóa và do đó không có để chạy ERR
bẫy của nó .
x=out; (x=in; echo $x)
)