1. 程式人生 > >如何配置Linux的服務設定為自動啟動或崩潰重新啟動後

如何配置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 [email protected]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 [email protected]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 [email protected]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.