Systemd giết dịch vụ ngay sau khi bắt đầu


14

Tôi đang viết tệp đơn vị systemd cho OSSEC HIDS. Vấn đề là khi systemd bắt đầu dịch vụ, nó ngay lập tức dừng chúng lại.

Khi tôi sử dụng lệnh ExecStart đó, tất cả đều hoạt động tốt.

ExecStart=/var/ossec/bin/ossec-control start

Nhưng khi tôi thực hiện một cải tiến nhỏ, tôi ổn trong nhật ký OSSEC, rằng nó nhận được SIG 15 sau khi bắt đầu.

ExecStart=/bin/sh -c '${DIRECTORY}/bin/ossec-control start'

Nếu tôi thực hiện một dịch vụ thay đổi nhỏ khác sẽ nhận được SIG 15 sau 20 giây.

ExecStart=/bin/sh -c '${DIRECTORY}/bin/ossec-control start && sleep 20'

Vì vậy, tôi đoán rằng, systemd sẽ giết / bin / sh sau khi dịch vụ bắt đầu và bin / sh sẽ giết OSSEC.

Làm thế nào tôi có thể giải quyết vấn đề này?


1
Loại dịch vụ là gì?
Wieland

@Wieland, tôi đã thử đơn giản và giả mạo, nhưng kết quả vẫn như vậy.
Daniil Svetlov

Câu trả lời:


36

giao thức sẵn sàng không phù hợp

Như Wieland ngụ ý, Typedịch vụ này rất quan trọng. Cài đặt đó biểu thị những gì hệ thống giao thức sẵn sàng mong đợi dịch vụ nói. Một simpledịch vụ được coi là đã sẵn sàng ngay lập tức. Một forkingdịch vụ được thực hiện để sẵn sàng sau khi quy trình ban đầu của nó rèn một đứa trẻ và sau đó thoát ra. Một dbusdịch vụ được thực hiện để sẵn sàng khi một máy chủ xuất hiện trên Desktop Bus. Và kể từ đó trở đi.

Nếu bạn không nhận được giao thức sẵn sàng được khai báo trong đơn vị dịch vụ để khớp với những gì dịch vụ thực hiện, thì mọi thứ sẽ trở nên tồi tệ. Sự không phù hợp của giao thức sẵn sàng khiến các dịch vụ không khởi động chính xác hoặc (thường là) bị chẩn đoán bởi hệ thống là không thành công. Khi một dịch vụ được coi là không khởi động systemd, đảm bảo rằng mọi quy trình bổ sung mồ côi của dịch vụ có thể bị ngừng hoạt động là một phần của sự cố (theo quan điểm của nó) sẽ bị hủy để đưa dịch vụ trở lại không hoạt động tiểu bang.

Bạn đang làm chính xác điều này.

Trước hết, những thứ đơn giản: sh -ckhông khớp Type=simplehoặc Type=forking.

Trong simplegiao thức, quy trình ban đầu được coi quy trình dịch vụ. Nhưng trên thực tế, một sh -ctrình bao bọc chạy chương trình dịch vụ thực tế như một tiến trình con . Vì vậy, MAINPIDđi sai và ExecReloadngừng làm việc, cho người mới bắt đầu. Khi sử dụng Type=simple, người ta phải sử dụng sh -c 'exec …'hoặc không sử dụng sh -c ở nơi đầu tiên. Điều thứ hai thường là khóa học chính xác hơn một số người nghĩ.

sh -ccũng không khớp Type=forking. Giao thức sẵn sàng cho một forkingdịch vụ khá cụ thể. Quá trình ban đầu phải rẽ nhánh một đứa trẻ, và sau đó thoát ra. systemd áp dụng thời gian chờ cho giao thức này. Nếu quy trình ban đầu không rẽ nhánh trong thời gian quy định, đó là thất bại để sẵn sàng. Nếu quy trình ban đầu không thoát trong thời gian quy định, thì đó cũng là một thất bại.

nỗi kinh hoàng không cần thiết đó là ossec-control

Điều này đưa chúng ta đến những thứ phức tạp: ossec-controlkịch bản đó .

Nó chỉ ra rằng đó là một rckịch bản Hệ thống 5 , từ bỏ 4 đến 10 quy trình, chính chúng trong ngã ba rẽ và thoát ra. Đây là một trong những rctập lệnh Hệ thống 5 cố gắng quản lý toàn bộ tập hợp các quy trình máy chủ trong một tập lệnh duy nhất, với forcác vòng lặp, điều kiện cuộc đua, tùy ý sleepđể cố gắng tránh chúng, các chế độ thất bại có thể làm nghẹt hệ thống ở trạng thái nửa khởi động, và tất cả những điều khủng khiếp khác khiến mọi người phát minh ra những thứ như Bộ điều khiển tài nguyên hệ thống AIX và daemontools hai thập kỷ trước. Và đừng quên tập lệnh shell ẩn trong một thư mục nhị phân mà nó viết lại một cách nhanh chóng, để thực hiện các động từ enabledisableđộng từ riêng.

Vì vậy, khi bạn /bin/sh -c '/var/ossec/bin/ossec-control start'những gì xảy ra là:

  1. systemd rèn những gì nó mong đợi là quá trình dịch vụ.
  2. Đó là cái vỏ, cái dĩa ossec-control.
  3. Điều đó lần lượt dĩa từ 4 đến 10 đứa cháu.
  4. Các cháu tất cả ngã ba và lần lượt thoát ra.
  5. Các cháu chắt tất cả ngã ba và thoát ra song song.
  6. ossec-control lối thoát hiểm
  7. Vỏ đầu tiên thoát ra.
  8. Các quy trình dịch vụ là những người vĩ đại-great- cháu, nhưng vì cách này các trận đấu làm việc không những forking hay các simplegiao thức sẵn sàng, systemd xem xét dịch vụ nói chung đã thất bại và đóng nó lại xuống.

Không có gì kinh dị này là thực sự cần thiết theo systemd cả. Không có nó.

một đơn vị dịch vụ mẫu systemd

Thay vào đó, người ta viết một đơn vị mẫu rất đơn giản :

[Đơn vị]
Mô tả = Máy chủ OSSEC HIDS% i
Sau = mạng.target 

[Dịch vụ]
Loại = đơn giản
ExecStartPre = / usr / bin / env / var / ossec / bin /% p-% i -t
ExecStart = / usr / bin / env / var / ossec / bin /% p-% i -f

[Tải về]
WantedBy = multi-user.target

Lưu cái này như /etc/systemd/system/ossec@.service.

Các dịch vụ thực tế khác nhau là khởi tạo của mẫu này, được đặt tên:

  • ossec@dbd.service
  • ossec@agentlessd.service
  • ossec@csyslogd.service
  • ossec@execd.service
  • ossec@agentd.service
  • ossec@logcollector.service
  • ossec@syscheckd.service
  • ossec@maild.service
  • ossec@analysisd.service
  • ossec@remoted.service
  • ossec@monitord.service

Sau đó, chức năng bật và tắt xuất phát trực tiếp từ hệ thống quản lý dịch vụ (đã sửa lỗi RedHat 752774 ), không cần các tập lệnh shell ẩn.

 systemctl kích hoạt ossec @ dbd ossec @ agentlessd ossec @ csyslogd ossec @ maild ossec @ execd ossec @ analyd ossec @ logcollector ossec @ remote ossec @ syscheckd ossec @ monitord

Hơn nữa, systemd được biết về và theo dõi từng dịch vụ thực tế trực tiếp. Nó có thể lọc nhật ký của họ với journalctl -u. Nó có thể biết khi một dịch vụ cá nhân đã thất bại. Nó biết những dịch vụ nào được cho là được kích hoạt và chạy.

Nhân tiện: Type=simple-ftùy chọn là ngay tại đây như trong nhiều trường hợp khác. Rất ít dịch vụ trong tự nhiên thực sự báo hiệu sự sẵn sàng của họ bằng cách exit, và đây không phải là những trường hợp như vậy. Nhưng đó là những gì forkingloại có nghĩa. Các dịch vụ trong tự nhiên chỉ là ngã ba và thoát vì một số quan niệm sai lầm nhận được rằng đó là những gì các công ty phải làm. Trên thực tế, không phải vậy. Nó đã không được kể từ những năm 1990. Đã đến lúc bắt kịp.

đọc thêm


2
Câu trả lời rất chi tiết! Tôi cũng đề nghị tạo một mục tiêu "nhóm", giả sử, ossec.target, Requires=tất cả các trường hợp cần thiết, sau đó đặt PartOf=ossec.targettrong ossec @ .service. Điều này sẽ cho phép bắt đầu và dừng ossec bằng cách bắt đầu và dừng ossec.target.
intelfx 04/05/2015

@JdeBP, wow! Cảm ơn rất nhiều cho loại câu trả lời chi tiết. Hy vọng tôi sẽ làm cho đơn vị này và viết ở đây về kết quả. Tôi đã mặc dù, rằng tôi sẽ dễ dàng hơn. Nhưng bạn đã đúng, ossec-controls là một địa ngục init.
Daniil Svetlov 04/05/2015

1
Lý do sử dụng / usr / bin / env làm trình bao bọc là gì?
Marius Gedminas

1

Giữ Type = forking và cung cấp vị trí tệp pid nếu dịch vụ / ứng dụng bắt đầu duy trì bất kỳ pid nào.

[Đơn vị]
Mô tả = "Chạy ứng dụng khi khởi động"
After = network.target syslog.target audd.service

[Service]
Type = forking
PIDFile = / var / run / apache2 / apache2.pid
ExecStart = / etc / init.d / apache2 bắt đầu
ExecStop = / etc / init.d / apache2 dừng
StandardOutput = syslog
StandardError = syslog
Restart = on-
fail SyslogIdentifier = webappslog

[Install]
WantedBy = multi-user.target
Alias ​​= webapps


0

Một phần nào đó liên quan, tôi đã có một dịch vụ systemd rằng có vẻ như systemd sẽ "giết" nó sau 30 giây.

systemctl status service-namesẽ hiển thị main process exited, code=exited, status=1/FAILUREsau 30 giây đã trôi qua.

Nó sẽ chạy tốt "trong sự cô lập" (như thủ công trong thiết bị đầu cuối có cùng môi trường ).

Hóa ra là

Type=forking
...
Environment=ABC="TRUE"
ExecStart=/path/to/my_script_to_spawn_process.sh

trong my_script_to_spawn_process.shđó đang làm

/bin/something > /dev/null 2>&1 &

hoạt động nhưng đã loại bỏ thông tin nhật ký đầu ra (thông thường nó sẽ chuyển đến một tệp, hoặc, nếu không, có thể journalctl).

Thay đổi nó để đăng nhập vào một nơi khác như /bin/something > /tmp/my_file

sau đó theo đuôi /tmp/my_filetiết lộ nguyên nhân thực tế. Đó là (một cách tiếp tuyến) mà bạn không thể sử dụng cú pháp Environment=ABC="true"như bạn có thể trong bash, nó không phải là dấu ngoặc kép hoặc giá trị khóa tất cả trong dấu ngoặc kép Environment="ABC=true"khiến quá trình của tôi thoát khỏi "trong giai đoạn thiết lập" sau khoảng 30 giây.


-4

Lưu ý rằng mô hình trình nền của systemd rất đơn giản và không tương thích với nhiều trình nền hiện có, thực hiện nhiều thao tác cắt, thực thi và thiết lập. Phổ biến nhất là các trình tiện ích bắt đầu với quyền root để thiết lập mọi thứ và sau đó chuyển sang UID ít đặc quyền hơn cho hoạt động thường ngày. ví dụ: khởi tạo tệp Pid là một điều không thành công trong systemd do các vấn đề đặc quyền. Có cách giải quyết (không phải sửa) nhưng nó được ghi chép lại.

Lời giải thích của JdeBP rất đáng hoan nghênh nhưng không đầy đủ và ông cho rằng tất cả lỗi của kiểm soát ossec đơn giản là không đúng. Ngay cả những thứ khá tầm thường cũng có vấn đề, ví dụ như nhận được các dòng nhật ký chưa được xử lý để gỡ lỗi hoặc thông báo lỗi có ý nghĩa từ chính systemd khi nó giết chết các tiến trình.


1
Những gì sử dụng là các tập tin PID, anyway? Nếu một tồn tại cho một dịch vụ nhất định, có thể có hoặc không có một quy trình thực tế với PID đó và khi một quy trình với đúng PID tồn tại, nó có thể thực sự không phải là dịch vụ mong đợi.
JoostM
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.