apt install 到底做了什么

痛點說明

當我們在使用 debian/ubuntu 的時候,如果需要安裝一些應用,通常會執(zhí)行 sudo apt install ...,如果源中有的話,這是最傻瓜式,也最方便的方式了。

但是筆者其實一直不是很喜歡這種方式,原因如下:

  1. 這種方式由于給到了 root 權限,無形中,背后做了很多事,對于筆者來說,總感覺缺乏一些掌控
  2. 這種方式安裝的軟件,相關的文件會分散到各種目錄,很亂。
  3. 沒法精確的去控制到底使用哪個版本,因為源中可能沒有。

為什么亂呢? 這和 Linux 的設計有關。這塊筆者不是很清晰,之前看過一片 文章,這篇文章很長,它后面簡要介紹了 Linux 上安裝軟件的特點,強烈建議玩 Linux 的同學看下。這里,我簡單描述下,希望我理解的沒有問題。
我們先說下 Windows。 在 Windows 下,安裝一個軟件,通常會是一個安裝包,點擊安裝,會指定一個安裝目錄,安裝完成后,這個軟件連同這個軟件的相關依賴,都會同時放進我們指定的安裝目錄。
當然,如果是那種解壓直接用的,直接找個目錄放解壓就好。這個時候,是不是很清晰,某個軟件就是安裝在某個目錄。當然,除此外,然后也有可能在 比如 User 目錄下,放一些配置文件,緩存什么的。但是筆者以為,相比較 Linux,可以說相當清爽。
反觀 Linux 呢? 當我們執(zhí)行 sudo apt install ... 時,最終文件會散落到 /usr、/var、/run 、/etc等等這些目錄,如果你是個小白,可能對此完全蒙圈,即便對于一些開發(fā)人員,其實對這些也知之不多。只有對于有經(jīng)驗的運維人員,才能快速熟練的找到相關文件的位置。

我們從 Linux 上面軟件的安裝方式出發(fā),其實就能窺見這其中的混亂了。 比如說 Ubuntu,當我們要安裝一個軟件時,通常會有幾種安裝方式:

  1. sudo apt install ...
  2. sudo dpkg -i ***.deb
  3. snap install ...
  4. 如果是桌面版的話,可以直接從應用商店下載
  5. 下載二進制文件壓縮包,解壓直接使用
  6. 下載源碼,自行編譯,再 make install

所以,在使用 Linux 的時候,我們總會去搜索諸如 “Ubuntu18.04 如何安裝 mongodb ” 這樣的問題,而且經(jīng)常是一個軟件有幾種不同的安裝方式,對于初學者,當從其中一個點出發(fā)的時候,基本是蒙圈的。與此同時,我們在使用 Windows 完全不會有這樣的困擾,管你是 QQ,PS 還是 mysql,基本上通過一個安裝包解決問題。

下面我們來梳理下混亂之下到底是些什么?
以下描述基于 Ubuntu18.04 安裝 redis 為例, 當我們執(zhí)行 sudo apt install redis 的時候,系統(tǒng)做了如下事件:

  1. 創(chuàng)建了 redis user 和 redis group, 同時指定其 home 為 /var/lib/redis,我們 執(zhí)行 cat /etc/passwd | grep redis, 看到以下結果,注意該用戶無法登錄系統(tǒng)
    redis:x:124:129::/var/lib/redis:/usr/sbin/nologin
  1. 添加了 /etc/init.d/redis-server 的可執(zhí)行腳本
  2. 添加了 /etc/rcx.d/S01redis-server 的軟鏈
  3. 添加了 /lib/systemd/system//redis-server.service 文件,供 systemd 調(diào)度
  4. 添加了 /etc/systemd/system/multi-user.target.wants/redis-server.service -> /lib/systemd/system/redis-server.service 的軟鏈,用于開機啟動
  5. redis-server、redis-cli 等命令 放到 /usr/bin 目錄下
  6. 啟動 redis-server 服務,這個時候會關聯(lián)一下目錄
    • /etc/redis/redis.conf redis 默認配置文件
    • /var/lib/redis redis 用戶家目錄,默認情況下,redis 的數(shù)據(jù)會放在這里
    • /var/log/redis 默認 redis 的日志會放在這里
    • /run/redis.pid 默認 redis daemon 的 pid 放在這里

如果這個軟件按照規(guī)范來的話,通常是做了這些事情。當然不同的軟件會有所差別,這個差別可能是未知的,你如果想要搞明白,需要去花好多時間研究。

作為一個工程師,筆者以為信心源于全面的測試和對細節(jié)的掌控,所以以上的安裝方式,我其實是懼怕的。
出于以上種種原因吧,筆者更傾向于下載二進制文件解壓,盡量像在 Windows 下,采用單一目錄安裝。其實這種安裝方式,在 Linux 下也越發(fā)的常見了,比如 hadoop 生態(tài)組件,比如 elasticsearch 生態(tài)的組件,都是采用這種方式安裝的。
我們來看下兩種安裝方式目錄結構的區(qū)別

apt install 的方式,這種方式將應用程序相關文件拆開,放到 Linux 下的各種目錄下,其實這種方式我覺得類似于將一個項目完全從純技術角度分包,當項目小的時候還好,但是項目很大時,一切都會變得惡心。目錄結構如下:

# tree /var/log
/var/log
├── redis
│   └── redis-server.log
├── mongod
│   └── mongod.log

# tree /var/lib
/var/lib
├── redis
│   └── .bashrc
├── mongod
│   └── .bashrc

# tree /run
/run
├── redis
│   └── redis.pid
├── mongod
│   └── mongod.pid


# tree /etc
/etc
├── redis
│   └── redis.conf
├── mongod
│   └── mongod.conf

第二種方式是先將某軟件相關的文件聚合到自己的目錄下,然后在自己的目錄下,從技術角度再分包。我們采用這種方式組織文件。其實也體現(xiàn)了內(nèi)聚的思想。類似于,將整個項目根據(jù)不同的 feature,先分包,然后在 feature 包內(nèi),再從技術角度出發(fā)細分。如果項目足夠復雜,當然這種是更好的。其目錄結構如下:

# tree /opt
/opt
├── redis
│   ├── data
│   │   └── redis.data
│   ├── logs
│   │   └── redis.log
│   ├── redis.conf
│   ├── redis.pid
├── mongodb
    ├── data
    │   └── mongod.data
    ├── logs
    │   └── mongod.log
    ├── mongod.conf
    ├── mongod.pid

部署 mongodb

下面,我們以 mongodb 為例,在 Ubuntu18.04 上詳細的走一遍流程。mongodb 官方提供了二進制文件下載,在這里。
下面我先說下我自己的部署標準

  1. 該軟件整體安裝在 /opt 目錄下
  2. 相關的可執(zhí)行文件如 mongo、mongod 全局可用
  3. 配置到系統(tǒng)服務,可開機啟動

了解了以上思路,我們正式開始部署流程,注意以下所有操作都是在 root 賬戶下,后面不再贅述。

1. 先解壓從官網(wǎng)下載的二進制文件包,在 /opt 目錄下解壓后,解壓后文件目錄如下

# tree /opt
/opt
└── mongodb-linux-x86_64-3.6.4
    ├── bin
    │   ├── bsondump
    │   ├── install_compass
    │   ├── mongo
    │   ├── mongod
    │   ├── mongodump
    │   ├── mongoexport
    │   ├── mongofiles
    │   ├── mongoimport
    │   ├── mongoperf
    │   ├── mongoreplay
    │   ├── mongorestore
    │   ├── mongos
    │   ├── mongostat
    │   └── mongotop
    ├── GNU-AGPL-3.0
    ├── MPL-2
    ├── README
    └── THIRD-PARTY-NOTICES

2. 創(chuàng)建相關文件及文件夾

# 進入到 mongodb 安裝目錄
cd /opt/mongodb-linux-x86_64-3.6.4

# 創(chuàng)建將來存放 mongo 數(shù)據(jù)的文件夾
mkdir data 

# 創(chuàng)建日志文件夾
mkdir logs

# 創(chuàng)建并編寫配置文件
vim mongod.conf

# 創(chuàng)建并編寫 mongod.service, 用于將來注冊進 systemd
vim mongod.service

配置文件 mongod.conf 內(nèi)容如下

# mongod.conf
# Where to store the data.
dbpath = /opt/mongodb/data
storageEngine = wiredTiger
directoryperdb = true

# where to log
logpath = /opt/mongodb/logs/mongodb.log
logappend=true
logRotate = reopen

port = 27017

# daemon
fork = true

# Enable journaling, http://www.mongodb.org/display/DOCS/Journaling
journal=true

# Turn on/off security.  Off is currently the default
noauth = true
# auth = true
# keyFile = /srv/mongodb/conf/rs.key

# crawler repl
# replSet=rs_crawler

pidfilepath = /opt/mongodb/mongod.pid

Service 配置文件 mongod.service 內(nèi)容如下

# mongod.service
[Unit]
Description=mongodb server
After=network.target

[Service]
Type=simple
User=mongodb
Group=mongodb
SyslogIdentifier=mongodb
LimitNOFILE=65536
ExecStart=/opt/mongodb/bin/mongod -f /opt/mongodb/mongod.conf
ExecStop=/bin/kill -s TERM $MAINPID
PIDFile=/opt/mongodb/mongod.pid
Restart=always

[Install]
WantedBy=multi-user.target

3. 接下來為了解耦或是方便,我們可以創(chuàng)建一些軟鏈接

ln -s /opt/mongodb-linux-x86_64-3.6.4 /opt/mongodb
ln -s /opt/mongodb-linux-x86_64-3.6.4/bin/mongod /usr/local/bin/mongod
ln -s /opt/mongodb-linux-x86_64-3.6.4/bin/mongo /usr/local/bin/mongo

# /opt/mongodb-linux-x86_64-3.6.4/bin 下的其它命令是否創(chuàng)建軟鏈,根據(jù)自己需求

我們注意到,mongodb 的所有相關文件都在自己的目錄內(nèi),如果外部引用的話,都是通過軟鏈接的方式,這類似于設計模式中的橋接或是代理。

完成以上步驟后, 執(zhí)行 mongod -f /opt/mongodb/mongod.conf, 啟動 mongodb,如果一切正常的話,mongodb 正常啟動,此時目錄結構如下,所有相關的內(nèi)容全部聚合到一個目錄下。

怎么樣,很清晰吧 O(∩_∩)O

# tree /opt
/opt
├── mongodb -> mongodb-linux-x86_64-3.6.4
└── mongodb-linux-x86_64-3.6.4
    ├── bin
    │   ├── bsondump
    │   ├── install_compass
    │   ├── mongo
    │   ├── mongod
    │   ├── mongodump
    │   ├── mongoexport
    │   ├── mongofiles
    │   ├── mongoimport
    │   ├── mongoperf
    │   ├── mongoreplay
    │   ├── mongorestore
    │   ├── mongos
    │   ├── mongostat
    │   └── mongotop
    ├── data
    │   ├── admin
    │   │   ├── collection-0--3307101973996970816.wt
    │   │   └── index-1--3307101973996970816.wt
    │   ├── diagnostic.data
    │   │   ├── metrics.2019-10-15T11-05-02Z-00000
    │   │   └── metrics.2019-10-15T11-05-20Z-00000
    │   ├── journal
    │   │   ├── WiredTigerLog.0000000002
    │   │   ├── WiredTigerPreplog.0000000001
    │   │   └── WiredTigerPreplog.0000000002
    │   ├── local
    │   │   ├── collection-2--3307101973996970816.wt
    │   │   └── index-3--3307101973996970816.wt
    │   ├── _mdb_catalog.wt
    │   ├── mongod.lock
    │   ├── sizeStorer.wt
    │   ├── storage.bson
    │   ├── WiredTiger
    │   ├── WiredTigerLAS.wt
    │   ├── WiredTiger.lock
    │   ├── WiredTiger.turtle
    │   └── WiredTiger.wt
    ├── GNU-AGPL-3.0
    ├── logs
    │   └── mongodb.log
    ├── mongod.conf
    ├── mongod.pid
    ├── mongod.service
    ├── MPL-2
    ├── README
    └── THIRD-PARTY-NOTICES

通過 mongod -f /opt/mongodb/mongod.conf 啟動的服務在后臺運行,通過 ps 找到 pid 先將其殺掉,然后進行下一步,否則會導致后續(xù)配置失敗。

4. 注冊到系統(tǒng)服務

# 創(chuàng)建 mongodb 的用戶,通常這種系統(tǒng)服務,出于安全考慮,我們不會直接以 root 用戶運行
# 我們首先創(chuàng)建一個 mongodb 用戶,將來用這個用戶運行 mongodb
# 下面的命令創(chuàng)建了 mongodb user,同時創(chuàng)建了 mongodb group,指定該用戶無法登錄系統(tǒng),同時創(chuàng)建了家目錄,此處家目錄其實可以不創(chuàng)建,因為我們的部署流程中沒用到 mongodb 的家目錄
useradd mongodb --home-dir /var/lib/mongodb --shell /usr/sbin/nologin --create-home --user-group

# 將 mongodb 的安裝目錄 全部交給 mongodb 用戶
chown -R mongodb:mongodb /opt/mongodb /opt/mongodb-linux-x86_64-3.6.4

# 將 service 文件軟鏈到 /lib/systemd/system, 注冊成系統(tǒng)服務
ln -s /opt/mongodb/mongod.service /lib/systemd/system/mongod.service
# 重載 systemd 列表
systemctl daemon-reload

# 清除掉剛剛啟動 mongodb 在安裝目錄下創(chuàng)建的文件,因為剛才是以 root 用戶啟動的,里面創(chuàng)建的文件都屬于 root,不刪除的話,服務起不來
rm -rf /opt/mongodb/mongod.pid /opt/mongodb/logs/* /opt/mongodb/data/* 

# 開啟服務, 如果一切正常,顯示如下
systemctl start mongod.service

    ● mongod.service - mongodb server
       Loaded: loaded (/opt/mongodb/mongod.service; disabled; vendor preset: enabled)
       Active: active (running) since Tue 2019-10-15 19:29:10 CST; 2s ago
     Main PID: 21850 (mongod)
        Tasks: 23 (limit: 478)
       CGroup: /system.slice/mongod.service
               └─21850 /opt/mongodb/bin/mongod -f /opt/mongodb/mongod.conf

    Oct 15 19:29:10 iZ8vb9wvg14ypn9rjj3sdpZ systemd[1]: Started mongodb server.

# 設置開機啟動
systemctl enable mongod.service

結語

至此,我們盡量模擬了 apt install ... 的方式部署好了 mongodb,并逐步拆解成單一步驟,感覺一切盡在掌握。
但是其實,其中還是有些不同的。
上面我們在注冊系統(tǒng)服務的時候提到了 systemd, init.d, 還用到了 systemctl 命令, 這到底是什么呢?
其中的不同恰好涉及到這些知識點,我們 下篇文章 詳細說明。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容