如何配置Linux的服務設置為自動啟動或崩潰重新啟動后


介紹

在本教程中,自動啟動 Linux 服務,我們將退后一步,更詳細地解釋 init 進程。 你應該很好地了解它們如何控制守護進程的啟動行為。

在第一部分本系列教程我們分享使用 MySQL 的如何崩潰或重啟后啟用的 Linux 服務自動啟動一些實際的例子。

我們看到了如何從三個不同的初始化方式做到這一點:System V 的,Upstart,和 systemd。 閱讀第一個教程在其上分布在默認情況下使用的 init 系統的復習。

在本教程中,我們將退后一步,解釋為什么我們運行命令並編輯我們所做的配置文件。 我們將從 System V init 守護進程開始。 我們還將看到為什么它隨着時間的推移被更新的 init 模式所取代。

先決條件

要學習本教程,你需要你創建的三個 DigitalOceanDroplet 之前 。

我們有:

  •  運行 MySQL 的 Debian 6 服務器
  •  一個運行 MySQL 的 Ubuntu 14.04 服務器
  •  運行 MySQL 的 CentOS 7 服務器

我們建議您回到本系列的第 1 部分,先創建 Droplets。

此外,您將需要是 root 用戶或在服務器上具有 sudo 權限。 要了解 sudo 的權限是如何工作的看到有關這個 Sudo 教程 DigitalOcean 。

您不應在生產 Linux 服務器上運行本教程中的任何命令,查詢或配置。

運行級別

運行級別代表了 Linux 系統的當前狀態。

該概念來自 System V init,其中 Linux 系統引導,初始化內核,然后輸入一個(且只有一個)運行級別。

例如,運行級可以是 Linux 服務器的關閉狀態,單用戶模式,重新啟動模式等。每個模式將指示什么服務可以在該狀態下運行。

某些服務可以在一個或多個運行級別運行,但不能在其他運行級別運行。

運行級別由單個數字表示,它們可以具有介於 0 和 6 之間的值。以下列表顯示了這些級別各自的含義:

  •  運行級別 0:系統關閉
  •  運行級別 1:單用戶,救援模式
  •  運行級別 2,3,4:多用戶,與網絡文本模式下啟用
  •  運行級別 5:多用戶,啟用網絡,圖形模式
  •  運行級別 6:系統重啟

運行級別 2,3 和 4 因分布而異。 例如,一些 Linux 發行版不實現運行級別 4,而其他的。 一些分布在這三個級別之間有明顯的區別。 通常,運行級別 2,3 或 4 意味着 Linux 已在多用戶,啟用網絡的文本模式下引導的狀態。

當我們啟用一個服務自動啟動,我們實際上是將它添加到運行級別。 在系統 V 中,OS 將以特定的運行級別開始; 並且,當它啟動時,它將嘗試啟動與該運行級別相關聯的所有服務。

運行級別成為 systemd 的目標 ,我們將在 systemd 部分討論。

Init 和 PID 1

初始化是在計算機啟動和內核加載到內存中后,開始在 Linux 系統中的第一個進程。

除此之外,它決定了用戶進程或系統服務應該按什么順序加載,以及是否應該自動啟動。

在 Linux 中每個進程都有一個進程 ID(PID)和init有 1. PID 就這么隨后產卵系統自帶的在線所有其他進程的父。

Init 的歷史

隨着 Linux 的發展,init 守護進程的行為也發生了變化。 最初,Linux 開始使用 System V init,與 UNIX 中使用的相同。 自那時以來,Linux 已經實施了Upstart的 init 守護進程(被 Ubuntu 創建)現在systemd的 init 守護進程(最初由 Fedora 的實現)。

大多數 Linux 發行版已逐漸從 System V 遷移或逐步淘汰,只保留向后兼容性。 FreeBSD 是 UNIX 的一種變體,它使用 System V 的不同實現,稱為 BSD init。 舊版本的 Debian 也使用 SysVinit。

每個版本的 init 守護程序都有不同的管理服務的方式。 這些變化背后的原因是需要一個強大的服務管理工具,不僅處理服務,而且處理設備,端口和其他資源; 這將並行加載資源,這將從崩潰恢復。

系統 V 初始化序列

系統 V 使用了inittab文件,它像 Upstart 后的 init 方法已經保持向后兼容性。

讓我們通過 System V 的啟動順序:

  1.  在 init 守護進程從二進制文件創建/sbin/init
  2.  第一個文件在 init 守護進程是讀取/etc/inittab
  3.  此文件中的一個條目決定機器應引導到的運行級別。 例如,如果運行級別的值指定為 3,則 Linux 將在啟用了聯網的多用戶文本模式下啟動。 (此運行級別稱為默認運行級別)
  4.  接下來,init 守護進程會進一步眺望/etc/inittab的文件和在讀什么初始化它需要為運行級別的腳本

因此,當 init 守護進程找到它需要為給定的運行級別運行的 init 腳本時,它基本上找出了啟動它需要什么服務。 這些 init 腳本是您可以在其中配置單個服務的啟動行為,就像我們在第一個教程中對 MySQL 的啟動行為一樣。

接下來,讓我們詳細了解 init 腳本。

系統 V 配置文件:Init 腳本

init 腳本是控制系統 V 中的特定服務(如 MySQL 服務器)的腳本。

服務的 Init 腳本由應用程序的供應商提供,或者帶有 Linux 發行版(適用於本地服務)。 我們還可以為自定義創建的服務創建自己的 init 腳本。

當一個進程或服務(如 MySQL 服務器)啟動時,其二進制程序文件必須加載到內存中。

根據服務的配置,此程序可能必須持續在后台執行(並接受客戶端連接)。 啟動,停止或重新加載此二進制應用程序的任務由服務的 init 腳本處理。 這就是所謂的初始化腳本,因為它初始化服務。

在 System V 中,init 腳本是 shell 腳本。

初始化腳本也被稱為RC(運行命令)的腳本。

目錄結構

/etc目錄是啟動腳本的父目錄。

init 的 shell 腳本的實際位置是在/etc/init.d 。 這些腳本符號鏈接到rc目錄。

/etc目錄下,我們有一些rc目錄,每一個在其名稱中的數字。

數字表示不同的運行級別。 因此,我們有/etc/rc0.d , /etc/rc1.d , /etc/rc2.d等等。

然后,每個內rc n .d目錄,我們有一個既具有開始的文件KS在他們的文件名,后面兩個數字。 這些是指向實際 init shell 腳本的符號鏈接文件。 為什么KS ? K 表示停止(即停止),“S”表示開始。

兩個數字表示腳本的執行順序。 因此,如果我們有一個名為 K25 some_script文件,它將 K99 another_script之前執行。

啟動

讓我們回來跟我們的啟動順序。 那么如何調用 init 腳本呢? 誰叫他們?

在 K 和 S 腳本不會由 init 守護程序直接調用,而是由另外一個腳本:在/etc/init.d/rc腳本。

如果你還記得,在/etc/inittab的文件通知 init 守護進程的運行級別,系統默認情況下應進入。 對於每一個運行級別,在一條線/etc/inittab文件調用/etc/init.d/rc腳本,傳遞上的運行級別作為參數。 基於此參數,腳本然后調用相應的下的文件/etc/rc n .d目錄。 所以,如果服務器靴子的 runlevel 2,根據腳本/etc/rc2.d會被調用; 為級別 3,根據腳本/etc/rc3.d被執行,等等。

在一個rc目錄,首先,所有 K 個腳本都按數字順序以“一站式”的參數運行,然后所有的 S 腳本都以類似的方式用的參數運行“開始。” 在后台,將分別使用 stop 和 start 參數調用相應的 init shell 腳本。

現在,因為下的文件/etc/rc n .d目錄( K nnnn文件)符號鏈接而已,美其名曰意味着調用與站的實際初始化 shell 腳本和啟動參數。

總而言之,當 Linux 服務器進入運行級別時,將運行某些腳本以停止某些服務,而其他腳本將運行以啟動其他服務。

啟動腳本中調用這個也恰好當系統切換到一個新的運行級別:對應/etc/rc<n>.d目錄的腳本執行。 而且,由於這些鉀和硫的文件是什么,但環節,根據實際的 shell 腳本/etc/init.d目錄與相應的啟動執行或停止爭論。

整個過程確保任何不應該在該運行級別運行的服務被停止,並且所有服務應該在該運行級別運行。

系統 V 自動啟動

 

由於我們使服務在引導時自動啟動,我們實際上是修改 init 行為。

因此,例如,當我們在運行級別 3 使能自動啟動服務,幕后的過程中會在適當的環節/etc/rc3.d目錄。

如果這聽起來很混亂,不要擔心 – 我們會在一分鍾內看到這一切意味着什么。

系統 V 示例

我們將回到我們的 MySQL 服務示例,這次有更多的理論。

第 1 步 – 登錄 Debian Droplet

為了本教程的這一部分,我們將回到我們在第 1 部分中創建的 Debian 6 Droplet。使用 SSH 命令連接到服務器(Windows 用戶可以使用像 PuTTy 這樣的工具連接)。

ssh sammy@your_server_ip 

第 2 步 – 查看 inittab

運行以下命令來查看inittab文件的內容:

cat /etc/inittab | grep initdefault

輸出應該是這樣的:

id:2:initdefault: 

2 后的 id 字段顯示系統被配置為以 runlevel 2 開始。這是默認的運行級別。 在這種情況下,Debian 將 2 指定為多用戶文本模式。 如果執行以下命令:

cat /etc/inittab | grep Runlevel

輸出確認:

# Runlevel 0 is halt.
# Runlevel 1 is single-user.
# Runlevels 2-5 are multi-user. # Runlevel 6 is reboot. 

第 3 步 – 查看 rc 目錄

運行以下命令列出rc目錄。 你應該看到有以下六個:

ls -ld /etc/rc*.d
drwxr-xr-x 2 root root 4096 Jul 31 07:09 /etc/rc0.d
drwxr-xr-x 2 root root 4096 Jul 31 07:09 /etc/rc1.d
drwxr-xr-x 2 root root 4096 Jul 31 07:21 /etc/rc2.d
drwxr-xr-x 2 root root 4096 Jul 31 07:21 /etc/rc3.d
drwxr-xr-x 2 root root 4096 Jul 31 07:21 /etc/rc4.d
drwxr-xr-x 2 root root 4096 Jul 31 07:21 /etc/rc5.d
drwxr-xr-x 2 root root 4096 Jul 31 07:09 /etc/rc6.d
drwxr-xr-x 2 root root 4096 Jul 23  2012 /etc/rcS.d

由於在運行級別 2(從 inittab 文件默認的 init)在系統啟動時,根據腳本/etc/rc2.d的目錄會在系統啟動時執行。

列出此目錄的內容:

ls -l /etc/rc2.d

這顯示文件只是符號鏈接,每個指向/etc/init.d 下的腳本文件:

. . .
lrwxrwxrwx 1 root root  17 Jul 23  2012 S01rsyslog -> ../init.d/rsyslog
lrwxrwxrwx 1 root root  22 Jul 23  2012 S02acpi-support -> ../init.d/acpi-support
lrwxrwxrwx 1 root root  15 Jul 23  2012 S02acpid -> ../init.d/acpid
lrwxrwxrwx 1 root root  17 Jul 23  2012 S02anacron -> ../init.d/anacron
lrwxrwxrwx 1 root root  13 Jul 23  2012 S02atd -> ../init.d/atd
lrwxrwxrwx 1 root root  14 Jul 23  2012 S02cron -> ../init.d/cron
lrwxrwxrwx 1 root root 15 Jul 31 07:09 S02mysql -> ../init.d/mysql lrwxrwxrwx 1 root root 13 Jul 23 2012 S02ssh -> ../init.d/ssh . . . 

我們可以看到這里沒有 K 腳本,只有 S(start)腳本。 腳本啟動知名的服務,如rsyslog 現在 ,cron 的 ,或ssh。

記住,S 之后的兩個數字決定起始順序:例如,rsyslog 在 cron 守護程序之前啟動。 我們還可以看到 MySQL 在這里列出。

第 4 步 – 查看 Init 腳本

現在我們知道,安裝在系統 V 兼容的服務時,它會創建下 shell 腳本/etc/init.d目錄。 檢查 MySQL 的 shell 腳本:

ls -l /etc/init.d/my*
-rwxr-xr-x 1 root root 5437 Jan 14  2014 /etc/init.d/mysql 

要查看啟動腳本的外觀,請閱讀文件:

cat /etc/init.d/mysql | less

從輸出,你會看到它是一個大的 bash 腳本。

第 5 步 – 使用 chkconfig 或 sysv-rc-conf

在基於 RHEL 的發行像 CentOS 的,一個命令調用chkconfig可以用來啟用或系統五,禁用服務,它還可以列出已安裝的服務和他們的運行級別。

檢查 CentOS 系統上所有運行級別的服務狀態的語法如下:

chkonfig --list | grep service_name 

 

沒有這樣的工具附帶的 Debian 本身( update-rc.d安裝或只從運行級別刪除服務)。 我們可以,但是,安裝定制的工具,稱為sysv-rc-conf幫助我們管理服務。

運行以下命令來安裝sysv-rc-conf :

sudo apt-get install sysv-rc-conf -y

安裝工具后,只需執行此命令即可查看各種服務的運行級別行為:

sudo sysv-rc-conf

輸出將是一個漂亮的圖形窗口,如下所示。 從這里,我們可以清楚地看到什么服務啟用了什么運行級別(標記為 X)。

sysv-rc-conf 顯示每個運行級別的各種服務的 X 標記的窗口

利用箭頭鍵和SPACEBAR ,可以啟用或對一個或多個運行級別禁用服務。

現在,按離開屏幕Q 。

第 7 步 – 在引導時測試 MySQL 啟動行為

從上一節的截圖中可以看出,根據我們在本教程第 1 部分的測試,MySQL 目前在運行級別 2-5 上啟用。

運行下面的命令關閉 MySQL 服務:

sudo update-rc.d mysql disable
update-rc.d: using dependency based boot sequencing
insserv: warning: current start runlevel(s) (empty) of script `mysql' overwrites defaults (2 3 4 5).
insserv: warning: current stop runlevel(s) (0 1 2 3 4 5 6) of script `mysql' overwrites defaults (0 1 6).

現在運行命令:

ls -l /etc/rc2.d

輸出應顯示從符號鏈接/etc/rc2.d/etc/init.d/mysql已更改為K :

. . .
lrwxrwxrwx 1 root root  15 Jul 31 07:09 K02mysql -> ../init.d/mysql . . . 

換句話說,MySQL 將不再在默認 runlevel(2)啟動。

這是當我們啟用和禁用服務時,在 System V 的幕后發生的。 只要在服務的缺省 runlevel 目錄下有一個 S 腳本,init 將在啟動時啟動該服務。

再次啟用服務:

sudo update-rc.d mysql enable

第 8 步 – 測試崩潰時 MySQL 啟動行為

讓我們看看 System V 如何處理服務崩潰。

請記住,我們做了一個改變了/etc/inittab在本教程的第 1 部分文件,以使 MySQL 的系統崩潰后自動啟動。 我們添加了以下行:

/ etc / inittab
ms:2345:respawn:/bin/sh /usr/bin/mysqld_safe

這是為了確保 MySQL 服務在崩潰后啟動。 要檢查是否發生這種情況,請首先重新啟動服務器:

sudo reboot

一旦服務器回來,SSH 到它並檢查 MySQL 進程 ID 像之前一樣:

ps -ef | grep mysql

注意進程 ID mysqld_safemysqld 。 在我們的例子中,分別是 895 和 1019:

root       907 1 0 07:30 ? 00:00:00 /bin/sh /usr/bin/mysqld_safe mysql 1031 907 0 07:30 ? 00:00:00 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --user=mysql --pid-file=/var/run/mysqld/mysqld.pid --socket=/var/run/mysqld/mysqld.sock --port=3306 root 1032 907 0 07:30 ? 00:00:00 logger -t mysqld -p daemon.error root 2550 2532 0 07:31 pts/0 00:00:00 grep mysql 

有一次終止這些進程-9開關(替代與 Debian 系統的 PID):

sudo kill -9 907 sudo kill -9 1031 

<! – 標記變量為紅色 – >

等待五分鍾左右,然后執行命令:

sudo service mysql status

輸出將顯示 MySQL 服務正在運行,從這行開始:

/usr/bin/mysqladmin  Ver 8.42 Distrib 5.1.73, for debian-linux-gnu on x86_64

如果您運行ps -ef | grep mysql ps -ef | grep mysql命令再次,你會看到,無論是mysqld_safemysqld進程已經上來了。

嘗試殺死進程幾次,在每種情況下,它應該在五分鍾后重生。

這是我們增加的原因,額外行/etc/inittab :你這是怎么配置的 System V 服務崩潰重生。 還有就是語法此行的詳細解釋第 1 部分 。

但是,為服務添加自動重新啟動時請小心:如果服務嘗試重新生成並在兩分鍾內失敗超過十次,則 Linux 將禁用在接下來的五分鍾內重新啟動。 這就是系統保持穩定,不會耗盡計算資源。

如果您碰巧在控制台中收到有關此類事件的消息或在系統日志中找到該消息,您將知道應用程序存在需要修復的問題,因為它會持續崩潰。

Upstart 簡介

 

經典 SysVinit 在 Upstart 出現之前已經成為主流 Linux 發行版的一部分。

隨着 Linux 市場的增長,加載作業和服務的序列化方法變得更加耗時和復雜。 與此同時,隨着越來越多的現代設備(如可熱插拔的存儲介質)激增了市場,SysVinit 被發現無法快速處理它們。

需要更快的加載操作系統,正常清理崩潰的服務,以及可預測的系統服務之間的依賴驅動了對更好的服務管理器的需要。 Ubuntu 的開發人員提出了另一種初始化方法,即 Upstart 守護進程。

Upstart init 在幾個方面優於 System V init:

  •  Upstart 不處理奧術 shell 腳本加載和管理服務。 相反,它使用易於理解和修改的簡單配置文件
  •  Upstart 不像 System V 一樣連續加載服務。這減少了系統引導時間
  •  Upstart 的采用了靈活的事件系統定制服務是如何在各種狀態下處理
  •  Upstart 有更好的方式來處理崩潰的服務應該重生的方式
  •  沒有必要保留一些冗余的符號鏈接,都指向同一個腳本
  •  Upstart 與 System V 的向后兼容/etc/init.d/rc腳本仍然運行管理本地系統 V 服務

Upstart 活動

Upstart 允許將與服務相關聯多個事件 。 這種基於事件的架構允許 Upstart 靈活地處理服務管理。

每個事件都可以觸發一個處理該事件的 shell 腳本。

Upstart 活動包括:

  •  開始
  •  開始
  •  停止
  •  停止

在這些事件之間,服務可以是在許多 ,像:

  •  等候
  •  預啟動
  •  開始
  •  運行
  •  預停
  •  停止
  •  等等

Upstart 也可以對這些狀態中的每一個采取行動,創建一個非常靈活的架構。

Upstart Init 序列

 

如 System V,也 Upstart 運行/etc/init.d/rc在啟動腳本。 此腳本正常執行任何 System V init 腳本。

Upstart 也期待下/etc/init目錄,並在每個服務配置文件執行 shell 命令。

Upstart 配置文件

Upstart 使用配置文件來控制服務。

Upstart 不使用系統 V 的方式使用 Bash 腳本。 相反,Upstart 使用服務配置文件與命名標准service_name .conf 。

該文件的純文本內容不同的部分,稱為 。 每節描述了服務的不同方面以及它應該如何運行。

不同的控制節為服務不同的事件,如預啟動 , 啟動 ,前期停止停止后 。

節本身包含 shell 命令。 因此,可以為每個服務的每個事件調用多個操作。

每個配置文件還指定了兩件事:

  •  服務應該啟動和停止的運行級別
  •  無論它是否崩潰服務應該重生

目錄結構

Upstart 配置文件位於下/etc/init目錄(不要與混淆/etc/init.d )。

Upstart 示例

 

讓我們來看看 Upstart 如何再次處理 MySQL Server,這次有更多的背景知識。

第 1 步 – 登錄到 Ubuntu Droplet

回到我們在第 1 部分中創建的 Ubuntu 14.04 Droplet。

使用 SSH 命令連接到服務器(Windows 用戶可以使用像 PuTTy 這樣的工具進行連接)。

ssh sammy@your_server_ip 

第 2 步 – 查看 init 和 rc 目錄

大多數 Upstart 的 config 文件在/etc/init目錄中。 這是創建新服務時應使用的目錄。

登錄服務器后,執行以下命令:

sudo ls -l /etc/init/ | less

結果將顯示大量的服務配置文件,一次一屏。 這些是在 Upstart 下本機運行的服務:

total 356
. . .
-rw-r--r-- 1 root root  297 Feb  9  2013 cron.conf
-rw-r--r-- 1 root root  489 Nov 11  2013 dbus.conf
-rw-r--r-- 1 root root  273 Nov 19  2010 dmesg.conf
. . .
-rw-r--r-- 1 root root 1770 Feb 19 2014 mysql.conf -rw-r--r-- 1 root root 2493 Mar 20 2014 networking.conf 

Q退出less 。

將其與系統中的本機 System V init 服務進行比較:

sudo ls -l /etc/rc3.d/* | less

將只有少數:

-rw-r--r-- 1 root root 677 Jun 14 23:31 /etc/rc3.d/README
lrwxrwxrwx 1 root root  15 Apr 17  2014 /etc/rc3.d/S20rsync -> ../init.d/rsync
lrwxrwxrwx 1 root root  24 Apr 17  2014 /etc/rc3.d/S20screen-cleanup -> ../init.d/screen-cleanup
lrwxrwxrwx 1 root root  19 Apr 17  2014 /etc/rc3.d/S70dns-clean -> ../init.d/dns-clean
lrwxrwxrwx 1 root root  18 Apr 17  2014 /etc/rc3.d/S70pppd-dns -> ../init.d/pppd-dns
lrwxrwxrwx 1 root root  26 Apr 17  2014 /etc/rc3.d/S99digitalocean -> ../init.d//rc.digitalocean
lrwxrwxrwx 1 root root  21 Apr 17  2014 /etc/rc3.d/S99grub-common -> ../init.d/grub-common
lrwxrwxrwx 1 root root  18 Apr 17  2014 /etc/rc3.d/S99ondemand -> ../init.d/ondemand
lrwxrwxrwx 1 root root  18 Apr 17  2014 /etc/rc3.d/S99rc.local -> ../init.d/rc.local

第 3 步 – 查看 Upstart 文件

我們已經看到了mysql.conf在本教程的第 1 部分文件。 所以,讓我們打開另一個配置文件:一個為 cron 守護進程。

sudo nano /etc/init/cron.conf

如你所見,這是一個相當簡單的配置文件的 cron 守護進程:

/etc/init/cron.conf
# cron - regular background program processing daemon
#
# cron is a standard UNIX program that runs user-specified programs at
# periodic scheduled times

description     "regular background program processing daemon"

start on runlevel [2345]
stop on runlevel [!2345]

expect fork
respawn

exec cron

最重要的領域要留意這里start on , stop onrespawn 。

start on指令告訴 Ubuntu 的啟動crond當系統進入運行級別 2,3,4 或 5。2,圖 3,和圖 4 是多用戶文本模式啟用聯網守護程序,和圖 5 是多用戶的圖形模式。 該服務不運行在任何其他運行級別(如 0,1 或 6)。

fork指令告訴 Upstart 過程中應該從控制台分離並在后台運行。

接下來是respawn指令。 這告訴系統 cron 應該自動啟動,如果它崩潰的任何原因。

退出編輯器,不進行任何更改。

cron 配置文件是一個相當小的配置文件。 MySQL 配置文件在結構上類似於 cron 配置文件; 它也有開始,停止和重生的節。 此外,它還有兩個腳本塊用於啟動前和啟動后事件。 這些代碼塊告訴系統當 mysqld 進程正在啟動或已經啟動時要執行什么。

有關使自己的 Upstart 文件實際的幫助,請參閱本教程的 Upstart 。

第 4 步 – 在引導時測試 MySQL 啟動行為

我們知道我們的 Ubuntu 14.04 服務器上的 MySQL 實例默認設置為在啟動時自動啟動。 讓我們看看如何禁用它。

在 Upstart,禁用服務依賴於文件的下存在/etc/init/稱為service_name .override 。 該文件的內容應該是一個簡單的單詞: manual 。

要查看我們如何使用此文件來禁用 MySQL,請執行以下命令為 MySQL 創建此覆蓋文件:

sudo nano /etc/init/mysql.override

添加這一行:

/etc/init/mysql.override
manual

保存更改。

接下來,重新啟動服務器:

sudo reboot

服務器恢復在線后,請檢查服務的狀態

sudo initctl status mysql

輸出應為:

mysql stop/waiting

這意味着 MySQL 沒有啟動。

檢查start指令 MySQL 的服務配置文件中已經改變:

sudo cat /etc/init/mysql.conf | grep start\ on

它應該是相同的:

start on runlevel [2345]

這意味着,選中.conf在文件init目錄是不希望看到,如果服務將在適當水平開始的唯一因素。 您還需要確保.override文件不存在。

要重新啟用 MySQL,請刪除覆蓋文件並重新啟動服務器:

sudo rm -f /etc/init/mysql.override
sudo reboot

一旦服務器重新啟動,遠程連接到它。

運行sudo initctl status mysql命令將顯示該服務已自動啟動。

第 5 步 – 測試崩潰崩潰的 MySQL 啟動行為

默認情況下,MySQL 在崩潰后自動啟動。

要停止 MySQL 的,請打開/etc/init/mysql.conf服務配置文件:

sudo nano /etc/init/mysql.conf

注釋掉兩個respawn指令。

/etc/init/mysql.conf
# respawn
# respawn limit 2 5

運行以下命令重新啟動服務:

sudo initctl stop mysql
sudo initctl start mysql

我們明確地停止和啟動服務,因為我們的測試表明initctl restartinitctl reload就不會在這里工作。

第二個啟動服務的命令顯示 PID 啟動的 MySQL:

mysql start/running, process 1274 

注意你的 MySQL 實例的 PID。 如果你崩潰mysql ,現在的過程,它不會自動來了。 刪除進程 ID(將其替換為您自己的數字):

sudo kill -9 1274 

現在檢查其狀態:

sudo initctl status mysql
mysql stop/waiting

嘗試找到狀態幾次,在每個之間給一些時間。 在每種情況下,MySQL 仍然會停止。 這是發生因為該服務配置文件沒有respawn的指令了。

1 份的教程的具有的一個更詳細的解釋respawn指令。

當你想要一個 Upstart 的服務上來重新啟動后還是崩潰?

說你已經升級你的 Linux 內核或放最新的補丁。你不想要任何戲劇; 你只是服務器來了。 您可以通過禁用任何 Upstart 進程的自動啟動來大大消除風險。

如果你的服務出現但仍然崩潰,你可以先停止它,然后改變它的重生行為。

systemd 簡介

最新的 Linux init 守護進程是 systemd。 事實上,它不僅僅是一個 init 守護進程:systemd 是一個全新的框架,包含了現代 Linux 系統的許多組件。

它的作用之一是為 Linux 的系統和服務經理 。 在這種情況下,systemd 控制的一個東西是服務崩潰或機器重新啟動時的行為。 你可以讀到這里 systemd 的 systemctl 。

systemd 向后兼容 System V 命令和初始化腳本。 這意味着任何 System V 服務也將在 systemd 下運行。 這是可能的,因為大多數 Upstart 和 System V 管理命令已被修改為在 systemd 下工作。

事實上,如果我們運行ps -ef | grep systemd ps -ef | grep systemd在支持它的操作系統命令,我們將不會看到任何東西,因為systemd重命名自己init在啟動時。 有一個/sbin/init文件,這是一個符號鏈接到/bin/systemd 。

systemd 配置文件:單元文件

 

在 systemd 的心臟是單元文件 。 每個單元文件表示系統資源。 systemd 和其他兩個 init 方法之間的主要區別是,systemd 不僅負責服務守護程序,而且負責其他類型的資源(如套接字,設備操作系統路徑,安裝點,套接字等)的初始化。資源可以是這些。

在單元文件中跟蹤有關資源的信息。

每個單元文件代表一個特定的系統資源,擁有的命名風格service name . unit type 。

因此,我們將有像文件dbus.service , sshd.sockethome.mount 。

正如我們將在后面看到,服務單元文件是簡單的文本文件(如 Upstart.conf文件)具有聲明語法。 這些文件很容易理解和修改。

目錄結構

在基於 Red Hat 的系統(如 CentOS)中,單元文件位於兩個位置。 主要位置是/lib/systemd/system/ 。

由系統管理員修改自定義創建單元文件或現有的單元文件將生活下/etc/systemd/system 。

如果具有相同名稱的單元文件在兩個位置存在,systemd 將使用下一個/etc 。 如果服務已啟用在啟動時或任何其他的目標/運行級別啟動,一個符號鏈接將被該服務單元下的文件在適當的目錄中創建/etc/systemd/system 。 在單元文件/etc/systemd/system實際上是符號鏈接的文件下同名/lib/systemd/system 。

初始序列:目標單位

一種特殊類型的單元文件是一個目標單位 。

一個目標單位的文件名是由 Stapling.target 。 目標單位與其他單位文件不同,因為它們不代表一個特定的資源。 相反,它們代表系統在任何時間的狀態。

目標單元通過分組和啟動應該是該狀態的一部分的多個單元文件來做到這一點。 systemd 目標 ,因此可以松散相比系統 V 運行級別,盡管它們並不相同。

每個目標都有一個名稱,而不是一個數字。 例如,我們已經multi-user.target ,而不是運行級別 3 或reboot.target,而不是運行級別 6。

當 Linux 服務器靴子說, multi-user.target ,它本質上使服務器到運行級別 2,3 或 4,這是多用戶的文本模式與網絡啟用。

如何將服務器帶到這個階段是差異在哪里。 與 System V 不同,systemd 不會按順序啟動服務。 一路上,它可以檢查其他服務或資源的存在,並決定其加載的順序。 這使得服務可以並行加載。

目標單元和運行級別之間的另一個區別是,在 System V 中,Linux 系統只能存在一個運行級別。 您可以更改運行級別,但系統將僅存在於該新的運行級別。 與 systemd,目標單元可以包容的,這意味着當一個目標單元激活,它可以確保其他目標單元被加載為它的一部分。

例如,在 Linux 的系統,與圖形用戶界面靴將具有graphical.target激活,這反過來會自動確保multi-user.target被加載並激活為好。

(在系統 V 術語中,這將類似地具有同時激活運行級別 3 和 5)。

下表比較運行級別和目標:

運行級別(System V init) 目標單位(Systemd)
運行級 0 poweroff.target
運行級 1 resuce.target
運行級 2,3,4 multi-user.target
運行級 5 graphical.target
運行級 6 reboot.target

systemd default.target

 

default.target等同於默認的運行級別。

在 System V,我們在一個叫做文件中定義的默認運行級別inittab 。 在 systemd,該文件被替換default.target 。 默認的目標單元文件家住下/etc/systemd/system目錄下。 這是一個符號鏈接在目標單位的一個文件/lib/systemd/system

當我們更改默認目標時,我們基本上重新創建該符號鏈接並更改系統的運行級別。

在系統 V inittab 文件還指定哪個目錄的 Linux 將執行其啟動腳本:它可以是任何RCñ.D目錄。 在 systemd 中,默認目標單元確定在引導時加載哪些資源單元。

所有這些單元被激活,但不是全部並行或全部順序。 如何資源單位負載可能依賴於其他資源的單位希望需要 。

systemd 依賴關系:需要

關於單元文件和目標單元的討論的原因是突出顯示 systemd 如何解決其守護進程之間的依賴。

正如我們之前看到的,Upstart 確保使用配置文件並行加載服務。 在系統 V 中,服務可以在特定運行級別開始,但也可以使其等待直到另一個服務或資源可用。 以類似的方式,可以使系統服務在一個或多個目標中加載,或者等待直到另一個服務或資源變為活動。

在 systemd, 需要另一個單位的單位將無法啟動,直到所需的單元被加載並激活。 如果在第一個單元激活時所需單元由於某種原因而失效,則第一個單元也將停止。

如果你考慮它,這可以確保系統的穩定性。 因此,可以使需要存在特定目錄的服務等待,直到該目錄的安裝點是活動的。 在另一方面, 希望其他單位不會強加這樣的限制單位。 如果當主叫方活動時,所需單元停止,它不會停止。 一個例子是在圖形目標模式下出現的非必要服務。

systemd 示例

 

現在是我們深入研究 MySQL 在 systemd 下的啟動行為的時候了。

第 1 步 – 登錄 CentOS Droplet

要了解所有這些概念以及它們如何與啟用服務自動啟動相關,讓我們回到我們在第 1 部分中創建的 CentOS 7 Droplet。

使用 SSH 命令連接到服務器(Windows 用戶可以使用像 PuTTy 這樣的工具進行連接)。

ssh sammy@your_server_ip 

第 2 步 – 查看 default.target 文件和依賴關系

這是一個長的路段,因為我們要遵循.target兔蹤跡,據我們可以。 systemd 的啟動順序遵循一個長鏈的依賴關系。

defaul.target

default.target正常的服務器引導過程中哪些服務啟動文件控制。

執行以下命令以列出默認目標單元文件:

sudo ls -l /etc/systemd/system/default.target

這將顯示如下輸出:

lrwxrwxrwx. 1 root root 37 Jul  8  2014 /etc/systemd/system/default.target -> /lib/systemd/system/multi-user.target

正如我們所看到的,默認的目標實際上是一個符號鏈接下的多用戶目標文件/lib/systemd/system/ 。 所以,該系統應該下引導multi-user.target ,這類似於運行級別 3。

multi-user.target.wants

接下來,執行下面的命令檢查所有的服務multi-user.target文件 :

sudo ls -l /etc/systemd/system/multi-user.target.wants/*.service

這應該顯示這樣的輸出:

. . .
lrwxrwxrwx. 1 root root  37 Jul  8  2014 /etc/systemd/system/multi-user.target.wants/crond.service -> /usr/lib/systemd/system/crond.service
. . .
lrwxrwxrwx  1 root root  38 Jul 31 22:02 /etc/systemd/system/multi-user.target.wants/mysqld.service -> /usr/lib/systemd/system/mysqld.service lrwxrwxrwx. 1 root root 46 Jul 8 2014 /etc/systemd/system/multi-user.target.wants/NetworkManager.service -> /usr/lib/systemd/system/NetworkManager.service lrwxrwxrwx. 1 root root 39 Jul 8 2014 /etc/systemd/system/multi-user.target.wants/postfix.service -> /usr/lib/systemd/system/postfix.service lrwxrwxrwx. 1 root root 39 Jul 8 2014 /etc/systemd/system/multi-user.target.wants/rsyslog.service -> /usr/lib/systemd/system/rsyslog.service lrwxrwxrwx. 1 root root 36 Jul 8 2014 /etc/systemd/system/multi-user.target.wants/sshd.service -> /usr/lib/systemd/system/sshd.service . . . 

我們可以看到,這些都是符號鏈接文件,指回單位實際文件下的/lib/systemd/system/ 。 我們還可以看到, mysqld.service是一部分multi-user.target 。

如果您執行此命令過濾輸出,可以找到相同的信息:

sudo systemctl show --property "Wants" multi-user.target | fmt -10 | grep mysql
mysqld.service

除了multi-user.target ,有不同類型的像目標system-update.targetbasic.target 。

要查看我們的多用戶目標取決於什么目標,請執行以下命令:

sudo systemctl show --property "Requires" multi-user.target | fmt -10
Requires=basic.target

於是,開始在系統multi-user.target模式, basic.target將必須先加載。

basic.target

看看其他目標basic.target依賴,執行以下命令:

sudo systemctl show --property "Requires" basic.target | fmt -10

輸出將是:

Requires=sysinit.target

sysinit.target

展望遞歸,我們可以看到,如果有任何需要的單位sysinit.target 。 沒有。 However, we can see what services are wanted by sysinit.target :

sudo systemctl show --property "Wants" sysinit.target | fmt -10

This will show a number of services wanted by sysinit.

Wants=local-fs.target
swap.target
cryptsetup.target
systemd-udevd.service
systemd-update-utmp.service
systemd-journal-flush.service
plymouth-read-write.service
. . .

As you can see, the system does not stay in one target only. It loads services in a dependent fashion as it transitions between targets.

Step 3 — Looking at a Unit File

Going a step further now, let’s look inside a service unit file. We saw the MySQL service unit file in Part 1 of this tutorial, and we will use it again shortly, but for now let’s open another service unit file, the one for sshd:

sudo nano /etc/systemd/system/multi-user.target.wants/sshd.service

它看起來像這樣:

[Unit]
Description=OpenSSH server daemon
After=syslog.target network.target auditd.service

[Service]
EnvironmentFile=/etc/sysconfig/sshd
ExecStartPre=/usr/sbin/sshd-keygen
ExecStart=/usr/sbin/sshd -D $OPTIONS
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartSec=42s

[Install]
WantedBy=multi-user.target

Just like an Upstart daemon config file, this service unit file is clean and easy to understand.

The first important bit to understand is the After clause. This says the SSHD service needs to load after the system and network targets and the audit logging service are loaded.

The file also shows the service is wanted by the multi-user.target , which means the target will load this service, but it won’t shut down or crash if sshd fails.

Since multi-user.target is the default target, sshd daemon is supposed to start at boot time.

Exit the editor.

Step 4 — Testing MySQL Startup Behavior at Boot

In Part 1 of the tutorial, we left the MySQL service enabled and running. Let’s see how to change that.

In the last section, we ran a command to confirm that mysqld.service is wanted by multi-user.target . When we listed the contents of the /etc/systemd/system/multi-user.target.wants/ directory, we saw a symbolic link pointing back to the original service unit under /usr/lib/systemd/system/ .

Run the following command to disable the service so it does not auto-start at boot time:

sudo systemctl disable mysqld.service

Now, run this command to check if MySQL is still wanted by multi-user.target :

sudo systemctl show --property "Wants" multi-user.target | fmt -10 | grep mysql

Nothing will be returned. Run the command below to check if the symbolic link still exists:

sudo ls -l /etc/systemd/system/multi-user.target.wants/mysql*

The link doesn’t exist:

ls: cannot access /etc/systemd/system/multi-user.target.wants/mysql*: No such file or directory

If you’d like, try rebooting the server. MySQL should not come up.

Now reenable the service:

sudo systemctl enable mysqld.service

The link will come back:

sudo ls -l /etc/systemd/system/multi-user.target.wants/mysql*
lrwxrwxrwx 1 root root 38 Aug  1 04:43 /etc/systemd/system/multi-user.target.wants/mysqld.service -> /usr/lib/systemd/system/mysqld.service

(If you rebooted before, you should start MySQL again.)

As you can see, enabling or disabling a systemd service creates or removes the symbolic link from the default target’s wants directory.

Step 5 — Testing MySQL Startup Behavior on Crash

MySQL will currently come up automatically after a crash. Let’s see how to disable that.

Open the MySQL service unit file in an editor:

sudo nano /etc/systemd/system/multi-user.target.wants/mysqld.service

After the header information, the contents of the file looks like this:

/etc/systemd/system/multi-user.target.wants/mysqld.service
[Unit]
Description=MySQL Community Server
After=network.target
After=syslog.target

[Install]
WantedBy=multi-user.target
Alias=mysql.service

[Service]
User=mysql
Group=mysql

# Execute pre and post scripts as root
PermissionsStartOnly=true

# Needed to create system tables etc.
ExecStartPre=/usr/bin/mysql-systemd-start pre

# Start main service
ExecStart=/usr/bin/mysqld_safe

# Don't signal startup success before a ping works
ExecStartPost=/usr/bin/mysql-systemd-start post

# Give up if ping don't get an answer
TimeoutSec=600

Restart=always PrivateTmp=false 

As we saw in Part 1, the value of the Restart parameter is set to always (for sshd, this was set to on-failure only). This means the MySQL service will restart for clean or unclean exit codes or timeouts.

The man page for systemd service shows the following table for Restart parameters:

Restart settings/Exit causes 沒有 總是 on-success on-failure on-abnormal on-abort on-watchdog
Clean exit code or signal   X X        
Unclean exit code   X   X      
Unclean signal   X   X X X  
暫停   X   X X    
Watchdog   X   X X   X

In a systemd service unit file, the two parameters – Restart and RestartSec – control crash behaviour. The first parameter specifies when the service should restart, and the second parameter defines how long it should wait before restarting.

Comment out the Restart directive, save the file, and exit the editor. This will disable the restart behavior.

/etc/systemd/system/multi-user.target.wants/mysqld.service
# Restart=always

Next, reload the systemd daemon, followed by a restart of the mysqld service:

sudo systemctl daemon-reload
sudo systemctl restart mysqld.service

Next, find the Main PID of the service by running this command:

sudo systemctl status mysqld.service
. . .
Main PID: 11217 (mysqld_safe) 

Using the kill -9 command, kill the main PID, using your own number.

sudo kill -9 11217 

Running the sudo systemctl status mysqld.service again will show that the service has failed:

sudo systemctl status mysqld.service
mysqld.service - MySQL Community Server
   Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled)
   Active: failed (Result: signal) since Sun 2015-06-21 02:28:17 EDT; 1min 33s ago Process: 2566 ExecStartPost=/usr/bin/mysql-systemd-start post (code=exited, status=0/SUCCESS) Process: 2565 ExecStart=/usr/bin/mysqld_safe (code=killed, signal=KILL) Process: 2554 ExecStartPre=/usr/bin/mysql-systemd-start pre (code=exited, status=0/SUCCESS) Main PID: 2565 (code=killed, signal=KILL) Jun 21 02:20:09 test-centos7 systemd[1]: Starting MySQL Community Server... Jun 21 02:20:09 test-centos7 mysqld_safe[2565]: 150621 02:20:09 mysqld_safe Logging to '/var/log/mysqld.log'. Jun 21 02:20:09 test-centos7 mysqld_safe[2565]: 150621 02:20:09 mysqld_safe Starting mysqld daemon with databases from /var/lib/mysql Jun 21 02:20:10 test-centos7 systemd[1]: Started MySQL Community Server. Jun 21 02:28:16 test-centos7 systemd[1]: mysqld.service: main process exited, code=killed, status=9/KILL Jun 21 02:28:17 test-centos7 systemd[1]: Unit mysqld.service entered failed state. 

Try to find the service status a few times, and each time the service will be shown as failed.

So, we have emulated a crash where the service has stopped and hasn’t come back. This is because we have instructed systemd not to restart the service.

Now, if you edit the mysqld.service unit file again, uncomment the Restart parameter, save it, reload the systemctl daemon, and finally start the service, it should be back to what it was before.

This is how a native systemd service can be configured to auto-start after crash. All we have to do is to add an extra directive for Restart (and optionally RestartSec ) under the [Service] section of the service unit file.

結論

So this is how Linux handles service startup. We have seen how System V, Upstart, and systemd init processes work and how they relate to auto-starting a service after a reboot or crash.

The declarative syntax of Upstart config files or systemd unit files is an improvement over the arcane System V init scripts.

As you work with your own Linux environment, check your distribution’s version and see what init daemon it supports.

It will be worthwhile to think about where would you want to enable a service and where would you want to disable it. In most cases, you don’t have to change anything for third-party applications or native Linux daemons. It’s only when you create your own service-based applications that you have to think about their startup and respawn behavior.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM