Bagaimana saya mengetahui mengapa layanan systemctl saya tidak dimulai pada CentOS 7?

12

Saya menggunakan CentOS 7. Bagaimana cara mengetahui mengapa layanan gagal untuk memulai? Saya telah membuat layanan ini

[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

File menunjuk ke ini

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

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

Saya dapat menjalankan file ini dengan baik dengan sendirinya. Tetapi ketika saya mencoba dan menjalankannya sebagai bagian dari layanan, saya perhatikan bahwa server nodeJS saya belum dimulai. Bahkan ketika saya memeriksa "sudo systemctl --state = gagal," Saya tidak melihat kesalahan apa pun ...

[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'.

Bagaimana saya mencari tahu mengapa layanan saya gagal untuk memulai?

Dave
sumber
journalctl -u nodejsseharusnya memberi Anda pesan kesalahan yang lebih bermakna.
Federico klez Culloca
Saya mendapat pesan "Tidak ada file jurnal yang ditemukan."
Dave
sudo journalctl harus bekerja. Juga dalam start.sh melihat apakah itu mengarahkan file log keluaran ke tempat lain.
rogerdpack

Jawaban:

13

Layanan Anda tidak Type=ditentukan di [Service]bagian ini, jadi systemdanggaplah maksud Anda Type=simple.

Itu berarti systemdakan mengharapkan proses yang dimulai dengan ExecStart=tetap berjalan selama layanan berjalan. Tapi sepertinya Anda start.shhanya menjalankan satu perintah dan kemudian keluar. Itulah yang foreverperintah : forever startmulai perintah target sebagai daemon, atau dengan kata lain, di latar belakang. Segera setelah forever startperintah selesai, shell running start.shakan keluar.

Pada saat itu, systemdanggap layanan ini gagal. Tapi tunggu, grup kontrol yang ditugaskan untuk layanan itu masih memiliki proses yang berjalan di dalamnya. "Jadi," pikir systemd, "tidak hanya gagal, tetapi juga meninggalkan kekacauan setelahnya sendiri. Tidak dapat memilikinya." Karena tidak ada KillMode=atau tidak KillSignal=ditentukan, systemdlanjutkan dengan default-nya dan kirimkan SIGTERM untuk setiap proses yang tersisa dalam grup kontrol itu, dan jika mereka tidak berhenti tepat waktu, lanjutkan dengan SIGKILL. Setelah itu, proses NodeJS Anda yang sebenarnya akan mati, dijamin.

Bagaimana memperbaikinya

Karena perintah yang Anda jalankan ExecStart=akan keluar segera setelah server yang sebenarnya dimulai, Anda tidak dapat menggunakan default Type=simple. Anda harus menentukan jenis layanan lain.

Anda bisa menggunakan Type=forking. Dengan tipe ini, man systemd.servicemerekomendasikan menggunakan PIDFile=opsi, jadi jika server NodeJS Anda membuat file PID untuk dirinya sendiri (atau Anda menambahkan opsi pada foreverperintah untuk membuatnya membuatnya untuk itu), Anda harus memberi systemdtahu di mana itu akan berada.

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

Jika Type=forkingtidak bekerja untuk Anda, maka Anda dapat menentukan Type=oneshotdengan RemainAfterExit=yes.

Itu systemdhanya menjalankan ExecStart=perintah ketika memulai layanan Anda dan ExecStop=ketika menghentikannya, dan tidak peduli tentang hal lain.

systemdmasih akan ingat apakah layanan terakhir kali diatur dalam keadaan berhenti atau mulai. Jadi jika Anda mengatur layanan lain untuk bergantung pada layanan ini, dan kemudian menghentikan layanan NodeJS Anda secara manual, layanan lainnya tidak akan berhenti secara otomatis dan tidak diragukan lagi akan mengembalikan kesalahan ketika tidak dapat menggunakan layanan NodeJS Anda.


Opsi ketiga adalah untuk melewatkan foreverperintah sepenuhnya dan biarkan systemdmelakukan pekerjaan memulai kembali proses NodeJS. Jika demikian, seluruh nodejs.serviceunit Anda adalah:

[Unit]
Description=nodejs server

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

[Install]
WantedBy=multi-user.target

Anda bisa menambahkan opsi lain.

Misalnya, Anda dapat menentukan RestartSec=5untuk menentukan waktu tidur 5 detik sebelum mencoba memulai kembali layanan jika tiba-tiba mati, untuk menghindari sumber daya sistem yang memonopoli dengan upaya memulai kembali secara rutin jika layanan Anda terus sekarat segera setelah dimulai kembali karena suatu alasan. (Nilai default RestartSec=adalah 100 ms.)

Atau jika Anda ingin layanan di-restart jika mengembalikan beberapa nilai status keluar tertentu, tetapi menganggapnya gagal pada yang lain, ada opsi untuk itu juga.

telcoM
sumber
Saya memiliki layanan yang tidak berhenti, dan tidak akan mulai dengan benar (itu dimulai, tetapi proses systemctl tidak pernah keluar). Hanya ingin menambahkan bahwa dalam kasus saya, yang perlu saya lakukan adalah menambahkan Restart=alwaysfile konfigurasi .service saya.
Andy Forceno