Systemd và quá trình sinh sản


14

Đừng thường đăng bài ở đây nhưng tôi đang xé toạc cái này ra. Tôi có một tập lệnh Python sẽ khởi động khi nó khởi chạy và chịu trách nhiệm bắt đầu một loạt các quy trình khác. Kịch bản này đã từng được khởi chạy khi khởi động thông qua sysvinit, nhưng gần đây tôi đã nâng cấp lên Debian Jessie vì vậy đã điều chỉnh nó để khởi chạy qua systemd.

Thật không may, tôi đang gặp phải một vấn đề mà tôi không thể giải quyết được. Khi bạn khởi chạy tập lệnh trực tiếp trong trình bao người dùng, nó sẽ khởi chạy chính xác các quy trình con của nó và khi tập lệnh thoát ra, các quy trình con sẽ mồ côi và tiếp tục chạy.

Khi được khởi chạy Via systemd, nếu tiến trình cha mẹ thoát ra, tất cả trẻ em cũng thoát ra (Chà, Màn hình mà chúng khởi chạy trong trạng thái chết và xuất hiện dưới dạng Chết ???)

Lý tưởng nhất là tôi cần có khả năng khởi động lại tập lệnh gốc mà không giết tất cả các tiến trình con, có thiếu điều gì không?

Cảm ơn!

[Unit]
Description=Server commander
After=network.target

[Service]
User=serveruser
Type=forking
PIDFile=/var/Server/Server.pid

ExecStart=/var/Server/Server.py
ExecStop=/bin/kill -s TERM $MAINPID

[Install]
WantedBy=multi-user.target

Chỉnh sửa: Tôi có thể có liên quan để chỉ ra rằng tập lệnh Python về cơ bản là một 'bộ điều khiển' cho các quy trình con của nó. Nó khởi động và dừng máy chủ trong màn hình gnu theo yêu cầu từ máy chủ trung tâm. Nó thường luôn luôn chạy, nó không sinh ra các dịch vụ và thoát. Tuy nhiên, có một số trường hợp tôi muốn có thể tải lại tập lệnh mà không giết các tiến trình con, ngay cả khi điều đó có nghĩa là các tiến trình đó bị mồ côi thành pid 1. Trên thực tế, sẽ không có vấn đề gì nếu tập lệnh Python bắt đầu xử lý như một quá trình cha mẹ, nếu điều đó thậm chí có thể.

Một lời giải thích tốt hơn về cách thức hoạt động của nó:

  • Systemd sinh ra /Server.py
  • Server.py giả mạo và ghi tệp pid cho Systemd
  • Sau đó, Server.py sinh ra các quy trình máy chủ trong màn hình gnu dựa trên hướng dẫn của nó
  • Server.py tiếp tục chạy để thực hiện bất kỳ khởi động lại nào được yêu cầu từ máy chủ

Khi khởi chạy mà không có Systemd, Server.py có thể được khởi động lại và màn hình gnu mà nó khởi chạy không bị ảnh hưởng. Khi khởi chạy với Systemd, khi Server.py tắt, thay vì các quá trình màn hình đó bị mồ côi đến pid 1, chúng sẽ bị giết.


1
Thật khó để cung cấp một giải pháp mà không có Server.pymã và mô tả về cách thức dịch vụ được đưa ra (nếu họ rẽ nhánh). Tuy nhiên, nói chung, đây là một vấn đề không phù hợp giao thức sẵn sàng .
intelfx

BTW, ExecStop=không cần thiết. Hành động mặc định của systemd khi dừng là để giết các tiến trình. Bạn có thể muốn xem tài liệu KillMode=hướng dẫn.
intelfx

1
Và, cuối cùng ... Nếu không có giao thức sẵn sàng phù hợp (một trong simplehoặc forking, thực tế), biện pháp cuối cùng sẽ là Type=oneshot, RemainAfterExit=yesKillMode=control-group.
intelfx

@intelfx Về cơ bản, tập lệnh Python khởi chạy một máy chủ trong màn hình bằng Sub Process.call. Nó phức tạp hơn thế bởi vì tập lệnh nhận các lệnh từ nơi khác cho nó biết màn hình nào sẽ bắt đầu và màn hình nào không. Những màn hình nào khả dụng cũng là động do đó tại sao chúng không thể là dịch vụ hệ thống theo cách riêng của chúng. Lý tưởng nhất là tôi không muốn systemd coi các màn hình này là một phần của dịch vụ, nhưng hiện tại chúng bị bỏ trong cùng một nhóm quy trình và chết với chủ nếu nó được khởi động lại.
Bottswana

Linh cảm của tôi là systemd không "xử lý" một quy trình kiểm soát như thế (nó chỉ tìm kiếm PID lúc bắt đầu, không nhận ra những cái sau này ...): |
rogerdpack

Câu trả lời:


9

Tôi đã cố gắng khắc phục điều này đơn giản bằng cách đặt KillMode để xử lý thay vì nhóm điều khiển (mặc định). Cảm ơn tất cả


Điều đó có vẻ giống như một công việc xung quanh hơn là một bản sửa lỗi, hãy xem các câu trả lời khác ... nếu bạn làm điều này và thực hiện "dừng hệ thống" thì nó sẽ không giết chết các tiến trình con mà chúng vẫn sẽ chạy [?] ngoài sự giám sát của systemctl?
rogerdpack

5

Tôi có một tập lệnh Python sẽ khởi động khi nó khởi chạy và chịu trách nhiệm bắt đầu một loạt các quy trình khác.

Điều đó chỉ ra rằng bạn đang làm sai. Nhiều hơn trong này trong một khoảnh khắc.

khi tập lệnh thoát ra, các tiến trình con sẽ mồ côi và tiếp tục chạy.

Đây không phải là hành vi đúng. Nếu quy trình "chính" - trong trường hợp này là đứa trẻ mà bạn đã rẽ nhánh, vì bạn đã chỉ định Type=forking- thoát, systemd coi dịch vụ đã hủy kích hoạt và chấm dứt mọi quy trình vẫn đang chạy khác (trong nhóm kiểm soát) để dọn dẹp .

Đôi khi việc chuyển đổi từ rctập lệnh Hệ thống 5 sang systemd không đơn giản, bởi vì cách thức đúng đắn để thực hiện mọi thứ trong systemd khá khác nhau. Cách đúng để làm (giả sử) OpenVPN, hoặc OpenStack hoặc OSSEC HIDS trong systemd không giống như người ta sẽ làm điều đó với một rctập lệnh. Thực tế là bạn có một kịch bản đang giả mạo, sau đó sinh ra toàn bộ quá trình của các cháu, sau đó thoát ra để mong các cháu đó tiếp tục chạy cho thấy rằng bạn đang duy trì cùng một loại kinh dị như ossec-control, mặc dù có hai mức độ giả mạo ít hơn. Nếu bạn thấy mình đang viết một tập lệnh "chính" kiểm tra các cờ "kích hoạt" và chạy các tiến trình con cho các phần "được kích hoạt" trong hệ thống của bạn, thì bạn đang mắc một lỗi tương tự như khủng khiếp ossec-control.

Không có cơ chế trồng tại nhà như vậy là cần thiết với systemd. Nó đã là một người quản lý dịch vụ. Theo /unix//a/200365/5132 , cách đúng đắn để thực hiện điều này trong systemd là không có một dịch vụ nào tạo ra một số dịch vụ phụ và nhầm lẫn để có "dịch vụ phụ". Đó là để mỗi đứa trẻ xử lý như một dịch vụ systemd đầy đủ theo đúng nghĩa của nó. Sau đó, một cho phép và vô hiệu hóa, và bắt đầu và dừng, các phần khác nhau của hệ thống bằng cách sử dụng các điều khiển systemd bình thường. Như bạn có thể thấy trong trường hợp OSSEC HIDS, một đơn vị dịch vụ mẫu đơn giản bao gồm hầu hết tất cả (một ngoại lệ là tại các dịch vụ https://askubfox.com/a/624871/43344 ), cho phép một người làm những việc như systemctl enable ossec@agentlessd.serviceđể bật tùy chọnagentlessddịch vụ, hoàn toàn không cần bất kỳ nhu cầu nào đối với cơ chế "tập lệnh chính" khủng khiếp cần có với Hệ thống 5 rc.

Có rất nhiều trường hợp, có lẽ không cực đoan như OSSEC HIDS, trong đó việc suy nghĩ lại như vậy là cần thiết. MTS như exim và sendmail là hai như vậy. Người ta có thể đã có một rctập lệnh duy nhất sinh ra một người chạy hàng đợi, một Trình gửi SMTP và một Chuyển tiếp SMTP, với một loạt các biến vỏ ad hoc trong một tệp cấu hình để kiểm soát chính xác đang chạy. Nhưng cách đúng đắn để làm điều này với systemd là có ba đơn vị dịch vụ phù hợp (hai trong số đó có các đơn vị ổ cắm liên kết ) và không có công cụ ad hoc nào cả, chỉ là các cơ chế thông thường của người quản lý dịch vụ.


Tôi đánh giá cao phản hồi về điều này. Mặc dù tôi đồng ý có các dịch vụ tập hợp con có ý nghĩa, nhưng nó được thực hiện bằng Python vì một lý do mà tôi không thể đi vào. Giải pháp duy nhất của tôi là tìm cách làm cho phương pháp này hoạt động. Cảm ơn, mặc dù. Tôi thích làm điều đó đúng cách.
Bottswana

Các dịch vụ phụ mà tập lệnh khởi chạy chỉ là các máy chủ đang chạy trong màn hình gnu với tư cách là một người dùng cụ thể. Các máy chủ này thay đổi rất nhiều, một số được thêm vào, một số bị xóa và điều này được kiểm soát ở nơi khác, vì vậy chúng thực sự không thể là dịch vụ thực tế trong systemd, vì điều đó làm tăng thêm sự phức tạp và không thể được quản lý tập trung. Ngoài ra, kịch bản tương tự cũng được sử dụng trên các máy chủ không có hệ thống.
Bottswana

systemd có các phương tiện rõ ràng để cho phép các dịch vụ được thêm và xóa mà không cần quyền truy cập root. "Cũng được sử dụng trên các dịch vụ phi hệ thống" là một trong những đối số ở trên không thể sửa được bằng cách thêm nhiều hệ thống ... tốt, có thể nói, thậm chí có thể cũng vậy. :)
Charles Duffy

0

Bạn chỉ có thể ngủ cha mẹ và chờ systemd giết nó tại thời điểm dừng.

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.