Bạn có thể sử dụng sh -c
và exec
để có được lệnh PID ngay cả trước khi nó chạy.
Để bắt đầu myCommand
, để PID của nó được in trước khi bắt đầu chạy, bạn có thể sử dụng:
sh -c 'echo $$; exec myCommand'
Làm thế nào nó hoạt động:
Điều này bắt đầu một lớp vỏ mới, in ra bộ vỏ của lớp vỏ đó và sau đó sử dụng hàm exec
dựng sẵn để thay thế lớp vỏ bằng lệnh của bạn, đảm bảo nó có cùng bộ mã hóa. Khi shell của bạn chạy một lệnh với exec
nội dung, shell của bạn thực sự trở thành lệnh đó , chứ không phải là hành vi phổ biến hơn để lấy một bản sao mới của chính nó, có PID riêng và sau đó trở thành lệnh.
Tôi thấy điều này đơn giản hơn nhiều so với các lựa chọn thay thế liên quan đến thực thi không đồng bộ (với &
), kiểm soát công việc hoặc tìm kiếm với ps
. Các cách tiếp cận này đều ổn, nhưng trừ khi bạn có lý do cụ thể để sử dụng chúng - ví dụ, có lẽ lệnh đang chạy, trong trường hợp đó, việc tìm kiếm PID của nó hoặc sử dụng điều khiển công việc sẽ có ý nghĩa - tôi khuyên bạn nên xem xét cách này trước tiên. (Và tôi chắc chắn sẽ không xem xét việc viết một kịch bản phức tạp hoặc chương trình khác để đạt được điều này).
Câu trả lời này bao gồm một ví dụ về kỹ thuật này.
Các phần của lệnh đó đôi khi có thể được bỏ qua, nhưng không thường xuyên.
Ngay cả khi hệ vỏ bạn đang sử dụng là kiểu Bourne và do đó hỗ trợ exec
dựng sẵn với các ngữ nghĩa này, bạn thường không nên cố gắng sử dụng sh -c
(hoặc tương đương) để tạo quy trình vỏ mới, riêng biệt cho mục đích này, bởi vì:
- Khi shell đã trở thành
myCommand
, không có shell nào chờ chạy các lệnh tiếp theo. sh -c 'echo $$; exec myCommand; foo
sẽ không thể cố gắng chạy foo
sau khi thay thế bằng myCommand
. Trừ khi bạn đang viết một tập lệnh chạy lệnh này như là lệnh cuối cùng của nó, bạn không thể chỉ sử dụng echo $$; exec myCommand
trong trình bao nơi bạn đang chạy các lệnh khác.
- Bạn không thể sử dụng một subshell cho việc này.
(echo $$; exec myCommand)
về mặt cú pháp có thể đẹp hơn về mặt cú pháp sh -c 'echo $$; exec myCommand'
, nhưng khi bạn chạy $$
vào bên trong (
)
, nó sẽ cung cấp cho bộ vỏ cha mẹ chứ không phải của lớp vỏ con. Nhưng chính bộ vi xử lý của lớp con sẽ là bộ vi xử lý của lệnh mới. Một số shell cung cấp các cơ chế không di động của riêng chúng để tìm PID của lớp con, mà bạn có thể sử dụng cho việc này. Đặc biệt, trong Bash 4 , (echo $BASHPID; exec myCommand)
không hoạt động.
Cuối cùng, lưu ý rằng một số shell sẽ thực hiện tối ưu hóa khi chúng chạy lệnh như thể exec
(ví dụ, chúng sẽ bỏ qua trước) khi biết rằng shell sẽ không cần phải làm gì sau đó. Một số shell cố gắng thực hiện điều này bất cứ khi nào nó là lệnh cuối cùng được chạy, trong khi các shell khác sẽ chỉ thực hiện khi không có lệnh nào khác trước hoặc sau lệnh và những lệnh khác hoàn toàn không thực hiện. Hiệu quả là nếu bạn quên viết exec
và chỉ sử dụng sh -c 'echo $$; myCommand'
thì đôi khi nó sẽ cung cấp cho bạn đúng PID trên một số hệ thống có một số shell. Tôi khuyên bạn không nên dựa vào hành vi như vậy , và thay vào đó luôn luôn bao gồm cả exec
khi đó là những gì bạn cần.