Trong một số comment on another post, @JonathanLeffler đã tuyên bố rằng:Bash subshell/pipelines - phần nào đang thực hiện trong subshells?
{...} | somecommand được chạy trong một hệ vỏ con và không ảnh hưởng đến vỏ mẹ . Demo:
X=PQR; echo $X; { X=ABC; echo $X; } | cat; echo $X
(với sản lượng PQR, ABC, PQR trên ba dòng)
và thực sự:
[email protected]:tmp$X=PQR; echo $X; { X=ABC; echo $X; } | cat; echo $X
PQR
ABC
PQR
Tuy nhiên, man bash
nói rằng { .. }
làm không thực hiện trong một vỏ:
{ list; }
list is simply executed in the current shell environment. list must be
terminated with a newline or semicolon. This is known as a group command.
Vậy điều gì đang xảy ra ở đây? man bash
có sai không? Tôi biết rằng mỗi phần của một đường ống thực hiện trong một vỏ bọc con; nhưng tôi không thấy nó gây ra hành vi quan sát như thế nào. Ví dụ:
[email protected]:tmp$X=PQR; echo $X | sed; X=ABC; echo $X | sed; echo $X
PQR
ABC
ABC
Edited thêm:
Một vài người đã đề nghị sử dụng echo $$
để chứng minh rằng điều được (hoặc không) các bộ phận của một subshell. Điều này hoàn toàn không hữu ích, vì $$
được mở rộng trong giai đoạn mở rộng tham số, điều này xảy ra lâu trước khi bất kỳ lệnh nào được thực thi.
Như một ví dụ:
[email protected]:tmp$echo 1$$; ps; (echo 2$$; ps); echo 3$$; ps
11194
PID TTY TIME CMD
1194 ttys000 0:00.22 -bash
21194
PID TTY TIME CMD
1194 ttys000 0:00.22 -bash
7894 ttys000 0:00.00 -bash
31194
PID TTY TIME CMD
1194 ttys000 0:00.22 -bash
[email protected]:tmp$
Bạn có thể thấy rằng gọi thứ hai của ps
xảy ra bên trong một subshell, với pid 7894
; nhưng echo 2$$
vẫn cho thấy giá trị mà bash thay thế trong giai đoạn mở rộng biến, trước khi nó sinh ra các subshell
Đối với độ tương phản, và chứng minh rằng { .. }
không không spawn một subshell:
[email protected]:tmp$echo 1$$; ps; { echo 2$$; ps; }; echo 3$$; ps
11194
PID TTY TIME CMD
1194 ttys000 0:00.22 -bash
21194
PID TTY TIME CMD
1194 ttys000 0:00.22 -bash
31194
PID TTY TIME CMD
1194 ttys000 0:00.23 -bash
Chỉ cần để chứng minh rằng @nos là chính xác, hãy thêm một đường dẫn vào phần trên:
[email protected]:tmp$echo 1$$; ps; { echo 2$$; ps; } | sed ; echo 3$$; ps
11194
PID TTY TIME CMD
1194 ttys000 0:00.25 -bash
21194
PID TTY TIME CMD
1194 ttys000 0:00.25 -bash
7945 ttys000 0:00.00 -bash
7946 ttys000 0:00.00 sed
31194
PID TTY TIME CMD
1194 ttys000 0:00.25 -bash
Như dự kiến, vỏ sinh ra hai vỏ con, một cho mỗi bên của đường ống.
Tôi nghĩ rằng chúng tôi có một người chiến thắng. Nó không phải là '{..}' đang tạo ra subshell, đó là đường ống dẫn. Tôi thực tế đã ra ngay và nói điều đó ngay từ đầu. –
Bạn cần một khoảng trắng sau '{', ít nhất là trong phiên bản 'bash' của tôi. Cấu trúc – krlmlr
$ (cmd args) cũng tạo ra một subshell: 'echo $ (echo $ BASH_SUBSHELL)' –