Làm cách nào để biết tại sao dịch vụ systemctl của tôi không bắt đầu trên CentOS 7?


12

Tôi đang sử dụng CentOS 7. Làm cách nào để biết tại sao dịch vụ không khởi động? Tôi đã tạo ra dịch vụ này

[rails@server ~]$ sudo cat /usr/lib/systemd/system/nodejs.service
[Unit]
Description=nodejs server

[Service]
User=rails
Group=rails
ExecStart=/home/rails/NodeJSserver/start.sh
ExecStop=/home/rails/NodeJSserver/stop.sh

[Install]
WantedBy=multi-user.target

Các tập tin chỉ ra điều này

[rails@server ~]$ cat /home/rails/NodeJSserver/start.sh
#!/bin/bash

forever start /home/rails/NodeJSserver/server.js

Tôi có thể chạy tập tin này tốt. Nhưng khi tôi thử và chạy nó như một phần của dịch vụ, tôi nhận thấy máy chủ nodeJS của tôi chưa khởi động. Ngay cả khi tôi kiểm tra "sudo systemctl --state = fail", tôi không thấy bất kỳ lỗi nào ...

[rails@server ~]$ sudo systemctl enable NodeJSserver
[rails@server ~]$ sudo systemctl start NodeJSserver
[rails@server ~]$
[rails@server ~]$
[rails@server ~]$ forever list
info:    No forever processes running
[rails@server ~]$
[rails@server ~]$
[rails@server ~]$ sudo systemctl --state=failed
  UNIT                           LOAD   ACTIVE SUB    DESCRIPTION
● nginx.service                  loaded failed failed The nginx HTTP and reverse proxy server
● systemd-sysctl.service         loaded failed failed Apply Kernel Variables
● systemd-vconsole-setup.service loaded failed failed Setup Virtual Console

LOAD   = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB    = The low-level unit activation state, values depend on unit type.

3 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.

Làm thế nào để tôi tìm ra lý do tại sao dịch vụ của tôi không bắt đầu?


journalctl -u nodejssẽ cung cấp cho bạn một thông báo lỗi có ý nghĩa hơn.
Federico klez Culloca

Tôi nhận được thông báo "Không tìm thấy tập tin tạp chí."
Dave

sudo tạp chí nên làm việc. Cũng trong start.sh hãy xem nếu nó chuyển hướng các tệp nhật ký đầu ra sang một nơi khác.
rogerdpack

Câu trả lời:


13

Dịch vụ của bạn không có Type=chỉ định trong [Service]phần, vì vậy, systemdgiả sử bạn có nghĩa Type=simple.

Điều đó có nghĩa là systemdsẽ mong đợi quá trình đã được bắt đầu ExecStart=để tiếp tục chạy miễn là dịch vụ đang chạy. Nhưng có vẻ như bạn start.shchỉ chạy một lệnh và sau đó thoát. Đó là các foreverlệnh : forever startbắt đầu lệnh mục tiêu như một daemon, hay nói cách khác, trong nền. Ngay khi forever startlệnh hoàn thành, shell đang chạy start.shsẽ thoát.

Tại thời điểm đó, systemdcoi dịch vụ này là thất bại. Nhưng chờ đã, nhóm kiểm soát được gán cho dịch vụ đó vẫn có một quy trình đang chạy trong đó. "Vì vậy," nghĩ systemd, "không chỉ nó đã thất bại, mà nó còn để lại một mớ hỗn độn sau đó. Không thể có điều đó." Vì không có KillMode=cũng không KillSignal=được chỉ định, systemdtiếp tục với các mặc định của nó và gửi SIGTERM cho bất kỳ quy trình còn lại nào trong nhóm kiểm soát đó và nếu chúng không dừng lại kịp thời, hãy theo dõi SIGKILL. Sau đó, quy trình NodeJS thực tế của bạn sẽ được bảo đảm.

Cách khắc phục

Vì lệnh bạn chạy với ExecStart=sẽ thoát ngay khi máy chủ thực tế được khởi động, bạn không thể sử dụng mặc định Type=simple. Bạn phải chỉ định loại dịch vụ khác.

Bạn có thể sử dụng Type=forking. Với loại này, man systemd.servicekhuyên bạn nên sử dụng một PIDFile=tùy chọn, vì vậy nếu máy chủ NodeJS của bạn tự tạo một tệp PID (hoặc bạn thêm tùy chọn vào foreverlệnh để tạo tùy chọn cho nó), bạn nên systemdbiết nó sẽ ở đâu.

[Service]
Type=forking
PIDFile=/absolute/path/to/nodejs.pid
User=rails
... <the rest as before>

Nếu Type=forkingkhông làm việc cho bạn, thì bạn có thể chỉ định Type=oneshotvới RemainAfterExit=yes.

Điều đó làm cho systemdchỉ chạy ExecStart=lệnh khi bắt đầu dịch vụ của bạn và ExecStop=khi dừng nó, và không quan tâm đến bất cứ điều gì khác.

systemdMặc dù vậy, vẫn sẽ nhớ liệu dịch vụ được đặt lần cuối ở trạng thái dừng hoặc bắt đầu. Vì vậy, nếu bạn đặt dịch vụ khác phụ thuộc vào dịch vụ này và sau đó dừng dịch vụ NodeJS của bạn theo cách thủ công, dịch vụ kia sẽ không tự động dừng và sẽ không nghi ngờ trả lại lỗi khi không thể sử dụng dịch vụ NodeJS của bạn.


Tùy chọn thứ ba là bỏ qua toàn bộ foreverlệnh và systemdthực hiện công việc khởi động lại quá trình NodeJS. Trong trường hợp đó, toàn bộ nodejs.serviceđơn vị của bạn sẽ là:

[Unit]
Description=nodejs server

[Service]
User=rails
Group=rails
ExecStart=/home/rails/NodeJSserver/server.js
Restart=always

[Install]
WantedBy=multi-user.target

Bạn có thể thêm các tùy chọn khác.

Ví dụ: bạn có thể chỉ định chỉ RestartSec=5định một giấc ngủ 5 giây trước khi cố gắng khởi động lại dịch vụ nếu nó bất ngờ chết, để tránh ăn cắp tài nguyên hệ thống bằng cách cố gắng khởi động lại thường xuyên nếu dịch vụ của bạn bị chết ngay lập tức sau khi được khởi động lại vì một số lý do. ( RestartSec=Giá trị mặc định là 100 ms.)

Hoặc nếu bạn muốn dịch vụ được khởi động lại nếu nó trả về một số giá trị trạng thái thoát cụ thể, nhưng xem xét nó không thành công với những người khác, cũng có các tùy chọn cho điều đó.


Tôi đã có một dịch vụ không dừng và sẽ không khởi động đúng cách (nó bắt đầu, nhưng quá trình systemctl không bao giờ thoát). Chỉ muốn thêm rằng trong trường hợp của tôi, tất cả những gì tôi cần làm là thêm Restart=alwaysvào tệp cấu hình dịch vụ.
Andy Forceno
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.