第三天:從安裝nginx到權(quán)限與日志排查的完整實(shí)戰(zhàn))
1. 為什么偏偏是第三天嚴(yán)格來說我不是什么有天賦的學(xué)習(xí)者。前兩天我還在跟終端里的黑框框大眼瞪小眼甚至一度懷疑自己是不是買了個(gè)假的Linux系統(tǒng)。第一天裝好系統(tǒng)之后我干得最多的事情就是打開瀏覽器然后把它關(guān)掉再打開文件管理器再關(guān)掉。到了第二天我終于鼓起勇氣敲了ls、cd、pwd這幾個(gè)命令當(dāng)時(shí)心里想的其實(shí)是“這不就跟Windows里的文件夾差不多嘛有什么好吹的?!钡谌扉_始事情變得不一樣了。不是因?yàn)槲彝蝗婚_竅而是因?yàn)槲业牡谝粋€(gè)實(shí)際需求出現(xiàn)了我要在Linux上做一個(gè)簡單的網(wǎng)頁測試環(huán)境需要裝一個(gè)服務(wù)端程序還要讓它開機(jī)自己跑起來。這個(gè)需求讓我意識(shí)到前兩天的“玩一玩”階段結(jié)束了接下來面對(duì)的是一個(gè)真正要?jiǎng)邮帧⒁獎(jiǎng)幽X的系統(tǒng)。所以這篇文章的記錄是從“第三天早上打開終端”開始的。這篇文章適合誰看如果你正在自學(xué)Linux可能和我一樣還在前期摸索階段那么這篇文章里記錄的思路、命令、踩坑過程應(yīng)該會(huì)對(duì)你有幫助。如果你已經(jīng)學(xué)了一段時(shí)間大概率也能從我的錯(cuò)誤里找到點(diǎn)共鳴。我不講那種動(dòng)不動(dòng)就要背幾千條命令的“高手方法論”我只講我在第三天實(shí)際做了什么、遇到了什么、以及我是怎么從一團(tuán)亂麻里把問題撿起來的。2. 第三天早晨我的第一個(gè)真實(shí)任務(wù)2.1 任務(wù)拆解而不是直接開干我的目標(biāo)是搭建一個(gè)簡單的本地網(wǎng)頁服務(wù)。聽起來不復(fù)雜但當(dāng)我坐下來準(zhǔn)備操作時(shí)發(fā)現(xiàn)自己其實(shí)連“服務(wù)”這個(gè)詞在Linux里意味著什么都不太清楚。Windows下我可能就雙擊一個(gè)安裝包下一步下一步完事。但在Linux里我面對(duì)的是一個(gè)終端一個(gè)沒有圖形界面的“裸環(huán)境”所有操作都要自己一步步拼出來。我給自己定了三條路第一搞清楚我現(xiàn)在用的這個(gè)發(fā)行版怎么安裝軟件包第二搞清楚服務(wù)程序裝完之后放在哪里、怎么啟動(dòng)第三搞清楚怎么讓它開機(jī)自動(dòng)運(yùn)行還要能隨時(shí)看日志。這三件事每件單獨(dú)拎出來都不至于讓人崩潰但合在一起就足以讓一個(gè)初學(xué)者在第三天早上對(duì)著屏幕發(fā)呆半小時(shí)。2.2 確認(rèn)環(huán)境和版本是學(xué)習(xí)的第一步很多新手容易忽略的一件事是不同Linux發(fā)行版之間的操作習(xí)慣差異很大。我前兩天用的命令到了第三天才發(fā)現(xiàn)有些是當(dāng)前系統(tǒng)自帶的有些則壓根不存在。為了避免“命令不存在”這種尷尬我先花了幾分鐘確認(rèn)環(huán)境信息。我敲的第一組命令是這樣的uname -a cat /etc/os-releaseuname -a顯示內(nèi)核版本、主機(jī)名、架構(gòu)這些信息cat /etc/os-release則能讓我清楚看到當(dāng)前發(fā)行版的名稱和版本號(hào)。我看到的結(jié)果是“Ubuntu”以及某個(gè)具體版本號(hào)心里就有底了接下來查資料時(shí)只要搜索Ubuntu相關(guān)的教程基本都能對(duì)上。這里有個(gè)小建議不要跳過環(huán)境確認(rèn)這一步。它雖然不產(chǎn)生任何“成果”但能幫你省下后面大量排查問題的時(shí)間。畢竟你在網(wǎng)上搜到一條命令結(jié)果發(fā)現(xiàn)在自己的環(huán)境里不能用那不是命令的問題而是環(huán)境差異的問題。2.3 刷新軟件源安裝一切軟件的前提確認(rèn)完環(huán)境之后我嘗試安裝第一個(gè)軟件包。當(dāng)時(shí)我憑記憶敲了install開頭的一條命令結(jié)果立刻被提示沒有找到相關(guān)命令。后來我才知道Ubuntu下安裝軟件包的工具叫apt而它的完整用法需要配合子命令使用。我當(dāng)時(shí)執(zhí)行的是sudo apt updatesudo是提權(quán)用的意思是“以管理員身份執(zhí)行”。apt是包管理工具update會(huì)從軟件源服務(wù)器獲取最新的軟件包列表。這步操作讓我第一次直觀感受到Linux和Windows的一個(gè)本質(zhì)區(qū)別Linux的軟件安裝是依賴“源”的它不是從某個(gè)網(wǎng)站下載一個(gè)exe文件而是從一個(gè)配置好的軟件源倉庫里拉取并解決依賴關(guān)系。跑完update之后屏幕上刷出一堆進(jìn)度條我當(dāng)時(shí)其實(shí)也沒完全看懂那些數(shù)字只知道最后出現(xiàn)了一行類似“所有軟件包均為最新”的提示。不管怎么說這一步跑通了接下來就可以正式安裝程序了。3. 第一道坎軟件包安裝與依賴地獄的初體驗(yàn)3.1 安裝一個(gè)程序居然要裝一堆“順便”的東西我準(zhǔn)備安裝的是一個(gè)輕量級(jí)網(wǎng)頁服務(wù)器軟件因?yàn)橹皇窍霚y試所以選擇了體積小、配置簡單的方案。命令是sudo apt install nginx輸入這行命令后系統(tǒng)問我是否繼續(xù)我按了y然后就看著終端刷出一整屏的新軟件包信息。這里面除了nginx本身還有一堆我完全不認(rèn)識(shí)的名字。當(dāng)時(shí)我的第一反應(yīng)是“我到底裝了多少個(gè)東西”這個(gè)感受特別典型。Linux的軟件管理系統(tǒng)中一個(gè)軟件包往往會(huì)依賴另外一些軟件包而這些被依賴的包又可能依賴更多的東西。這不是壞事兒它在幫你把所有需要的零件一次性備齊但對(duì)于新手來說確實(shí)容易產(chǎn)生“失控感”。我后來才知道這個(gè)機(jī)制叫“依賴管理”是Linux軟件生態(tài)相對(duì)穩(wěn)定的根基。apt默認(rèn)會(huì)把依賴包一起裝好不需要我手動(dòng)操心。這一點(diǎn)比Windows下那種“你缺個(gè)運(yùn)行庫自己去官網(wǎng)找”的體驗(yàn)要省心很多。3.2 裝完之后我怎么知道它去哪了安裝過程結(jié)束以后我面臨一個(gè)新問題“這東西到底裝哪了”Windows里我會(huì)去“開始菜單”里找圖標(biāo)但Linux服務(wù)器環(huán)境里沒有開始菜單程序也不是簡單躺在某個(gè)固定文件夾里。我試了which nginx返回了一個(gè)路徑類似/usr/sbin/nginx。于是我開始了解Linux目錄的大致分工/usr/bin和/usr/sbin是普通用戶和管理員命令所在的地方/etc是配置文件的家nginx的配置很可能就在/etc/nginx/下/var/log是日志的大本營/var/www或/usr/share/nginx/html之類的地方通常是默認(rèn)網(wǎng)頁文件的所在目錄。我是怎么驗(yàn)證的直接用了ls /etc/nginx/果然看到了nginx.conf和一堆亂七八糟的子目錄。這個(gè)發(fā)現(xiàn)對(duì)當(dāng)時(shí)的我來說幾乎等于找到了新世界的入口——原來Linux不是沒有“安裝目錄”而是它把不同功能的文件分散到不同目錄里各司其職。3.3 如何啟動(dòng)一個(gè)服務(wù)安裝完之后我照著直覺去執(zhí)行了可執(zhí)行文件結(jié)果發(fā)現(xiàn)前臺(tái)一直被卡住了終端完全被日志刷屏連命令都敲不進(jìn)去。我意識(shí)到這不是正確的啟動(dòng)方式。后來我查到管理服務(wù)的方法通常是用systemctl命令sudo systemctl start nginx sudo systemctl status nginxstart是啟動(dòng)服務(wù)status是查看運(yùn)行狀態(tài)。執(zhí)行完status后終端上會(huì)顯示一段狀態(tài)信息包括當(dāng)前進(jìn)程是否在運(yùn)行、有沒有報(bào)錯(cuò)、占用資源情況等等。我看到狀態(tài)欄里寫著active (running)的那一刻整個(gè)人是有點(diǎn)激動(dòng)的。說實(shí)話這個(gè)“active (running)”在別人眼里就是幾個(gè)英文單詞但在我第三天的認(rèn)知里它意味著我成功把一個(gè)后臺(tái)程序拉起來了而且是通過真正的Linux管理方式搞定的。4. 權(quán)限新手和系統(tǒng)打架的重災(zāi)區(qū)4.1 為什么總提示 “Permission denied”裝好并啟動(dòng)nginx之后我想修改一下默認(rèn)網(wǎng)頁內(nèi)容把我自己的HTML文件放進(jìn)網(wǎng)站的根目錄。當(dāng)我興沖沖地用cp命令復(fù)制文件時(shí)卻收到了一條冷冰冰的提示Permission denied我第一次看到這行字時(shí)心里的獨(dú)白是“這是我自己的電腦憑什么不讓我動(dòng)”后來才知道在Linux里文件和目錄有一整套權(quán)限體系權(quán)限不夠就是不夠哪怕你覺得自己是電腦的主人也不行。權(quán)限這個(gè)東西我用一個(gè)類比才徹底理解Linux把每個(gè)文件和目錄看成帶了三把鎖的箱子一把管“讀”一把管“寫”一把管“執(zhí)行”。這三把鎖分別對(duì)應(yīng)三類人文件所有者、文件所屬組、其他用戶。用ls -l查看文件時(shí)那一串類似-rw-r--r--的字符就是在展示這些鎖的開關(guān)狀態(tài)。我當(dāng)時(shí)執(zhí)行的命令是ls -l /var/www/html/輸出結(jié)果顯示默認(rèn)的網(wǎng)頁文件是root用戶所有的且普通用戶沒有寫權(quán)限。這其實(shí)是一個(gè)安全設(shè)計(jì)防止普通用戶隨意篡改系統(tǒng)級(jí)的網(wǎng)頁內(nèi)容。但如果我真的要改文件該怎么辦兩個(gè)思路第一用sudo強(qiáng)制提權(quán)操作第二修改文件的所有者或權(quán)限。4.2 修改權(quán)限的“三板斧”我的第一個(gè)思路自然是sudo但后來發(fā)現(xiàn)如果每個(gè)文件都要用sudo去編輯時(shí)間長了會(huì)很別扭。于是我開始接觸chmod和chown。chown用來改變文件所有者比如sudo chown -R 我的用戶名 /var/www/html-R表示遞歸對(duì)目錄及其內(nèi)部所有文件生效。執(zhí)行完之后我再用ls -l查看發(fā)現(xiàn)文件的所有者變成了我自己這個(gè)時(shí)候就擁有了直接修改的權(quán)限。chmod則用來改變權(quán)限位常見用法有兩種符號(hào)模式和數(shù)字模式。我一開始覺得數(shù)字模式很難記直到有人告訴我r4、w2、x1把它們相加就好。比如755表示所有者可讀寫執(zhí)行7組內(nèi)用戶可讀執(zhí)行5其他用戶可讀執(zhí)行5。這樣記起來就順多了。我把自己的網(wǎng)頁目錄權(quán)限設(shè)置成了755然后在里面新建了一個(gè)index.html再次用瀏覽器訪問終于看到了我自己寫的頁面。那一刻的成就感比第一次看到active (running)還要強(qiáng)烈。5. 第三天最值錢的收獲學(xué)會(huì)看日志5.1 程序沒問題為什么訪問不了我把自己的網(wǎng)頁內(nèi)容替換進(jìn)去之后瀏覽器打開卻還是顯示默認(rèn)頁面。我當(dāng)時(shí)把配置文件翻來覆去地看也沒看出哪里有問題。后來在一篇教程里看到一句話“Linux下排查問題第一步永遠(yuǎn)是看日志?!睂?duì)就是日志。我順著這個(gè)提示查看了nginx的日志目錄ls /var/log/nginx/目錄里通常有access.log和error.log。access.log記錄每一次訪問請(qǐng)求error.log記錄程序運(yùn)行時(shí)的錯(cuò)誤信息。我當(dāng)時(shí)用了一個(gè)命令去查看日志的最后幾行tail -f /var/log/nginx/error.log-f參數(shù)的意思是“實(shí)時(shí)追蹤”文件有新內(nèi)容時(shí)自動(dòng)追加顯示。在我用瀏覽器重新訪問網(wǎng)站之后error.log立刻吐出了一行錯(cuò)誤信息內(nèi)容是找不到某個(gè)具體路徑下的文件。我順著錯(cuò)誤提示去檢查發(fā)現(xiàn)是我把文件放錯(cuò)位置了一直放在自己創(chuàng)建的臨時(shí)目錄里而不是nginx實(shí)際讀取的根目錄。這件事給了我很深的印象Windows世界里出了問題很多時(shí)候是靠彈窗提示和重啟解決但在Linux里程序未必會(huì)給友好提示它只會(huì)默默把錯(cuò)誤記錄在日志里。懂不懂看日志直接決定了你是“瞎猜者”還是“排查者”。5.2 日志里的常見關(guān)鍵詞速查我把自己第二天到第三天積累的常見日志關(guān)鍵詞整理了一下雖然不全面但作為新手備忘足夠用了關(guān)鍵詞可能的含義Permission denied沒有權(quán)限檢查文件所有者或權(quán)限位Connection refused服務(wù)沒起來或者端口不對(duì)Address already in use端口被占用可能另一個(gè)進(jìn)程占用著File not found路徑不對(duì)或文件真的不存在command not found命令拼寫錯(cuò)誤或軟件包未安裝遇到問題時(shí)先打開對(duì)應(yīng)日志搜索這些關(guān)鍵詞通常能很快定位問題范圍。這個(gè)方法在我第三天下午的排查過程中幫了大忙后續(xù)我相信也會(huì)一直用下去。6. 進(jìn)程管理原來電腦里藏著這么多“分身”6.1 查看進(jìn)程像查戶口一樣nginx跑起來之后我產(chǎn)生了一個(gè)疑問“它到底是怎么運(yùn)作的為什么我關(guān)掉終端它還在運(yùn)行”后來才知道這類服務(wù)程序會(huì)以“守護(hù)進(jìn)程”的方式在后臺(tái)運(yùn)行不會(huì)隨著終端的關(guān)閉而退出。為了驗(yàn)證我執(zhí)行了ps auxps是“進(jìn)程快照”命令aux是一組參數(shù)用來顯示所有用戶的進(jìn)程列表。屏幕上刷出幾頁密密麻麻的信息我看到有好多條nginx相關(guān)的進(jìn)程瞬間有點(diǎn)懵“我只啟動(dòng)了一個(gè)服務(wù)為什么有這么多”稍微多了解一點(diǎn)之后我才明白nginx采用的是多進(jìn)程模型一個(gè)主進(jìn)程用來管理全局再派生出多個(gè)工作進(jìn)程來處理并發(fā)請(qǐng)求。這就像一家餐廳里主廚負(fù)責(zé)全局調(diào)度幾個(gè)灶臺(tái)師傅分別負(fù)責(zé)不同的菜客人再多也能同時(shí)出餐。用這種比喻去看進(jìn)程列表就好理解多了。6.2 干掉一個(gè)卡死進(jìn)程的正確姿勢(shì)學(xué)進(jìn)程管理的過程中我還碰到過一個(gè)“僵尸”進(jìn)程。具體情況對(duì)方不重要重要的是我發(fā)現(xiàn)某個(gè)進(jìn)程占用了CPU和內(nèi)存始終不退出。我想把它關(guān)掉于是用上了kill命令。最簡單的用法是kill 進(jìn)程號(hào)但有時(shí)候進(jìn)程比較頑固單次kill無效。后來我了解到kill其實(shí)是在向進(jìn)程發(fā)送信號(hào)不同信號(hào)的含義不同kill -15是禮貌地請(qǐng)求進(jìn)程退出給它時(shí)間收尾kill -9是強(qiáng)制終結(jié)不讓進(jìn)程做任何善后處理。我嘗試的是先用kill -15發(fā)現(xiàn)那個(gè)進(jìn)程還在最后只能上kill -9效果立竿見影。后來我學(xué)到一句經(jīng)驗(yàn)口訣“平時(shí)能用15就不用9只有實(shí)在退不出去才強(qiáng)制?!币?yàn)橹苯訌?qiáng)殺可能導(dǎo)致文件損壞或配置未保存這種風(fēng)險(xiǎn)還是盡量避免。6.3 觀察資源占用top 初體驗(yàn)除了ps我還試了另一個(gè)命令top。top會(huì)動(dòng)態(tài)刷新顯示當(dāng)前系統(tǒng)資源占用情況類似Windows的任務(wù)管理器。第一次進(jìn)去時(shí)我被頁面上花花綠綠的數(shù)據(jù)弄花了眼但這些數(shù)據(jù)里最關(guān)鍵的兩欄是CPU占用和內(nèi)存占用。如果某一欄一直居高不下就說明有進(jìn)程在消耗大量資源需要重點(diǎn)關(guān)注。退出top的方式是按q鍵這一點(diǎn)是我折騰了好一會(huì)兒才發(fā)現(xiàn)的……當(dāng)時(shí)差點(diǎn)把終端直接關(guān)掉重啟實(shí)在有點(diǎn)丟人。7. 目錄結(jié)構(gòu)讀懂了它就讀懂了大半個(gè)系統(tǒng)7.1 從“文件都在哪”到“為什么這么放”第三天下午我決定不再東一榔頭西一棒槌地亂敲命令了而是認(rèn)真把Linux的目錄結(jié)構(gòu)底朝天看一遍。因?yàn)橐徽於荚诟鞣N路徑之間跳來跳去如果不知道每個(gè)目錄的基本用途永遠(yuǎn)只能靠死記硬背。Linux的根目錄是/所有路徑都從它開始。我把頂層目錄列舉了一遍ls /在我這個(gè)系統(tǒng)里顯示出來的目錄有bin、boot、dev、etc、home、lib、media、mnt、opt、proc、root、run、sbin、srv、sys、tmp、usr、var。每個(gè)目錄名都不長但背后承載著不同的職責(zé)。我花了一個(gè)下午的時(shí)間逐一進(jìn)入這些目錄查看內(nèi)容。比如/bin里放的是系統(tǒng)運(yùn)行所需的基本命令/usr里是用戶安裝的軟件/var是經(jīng)常變化的數(shù)據(jù)比如日志和緩存/tmp是臨時(shí)文件/home是普通用戶的家目錄。7.2 一個(gè)值得養(yǎng)的“家目錄”習(xí)慣在家目錄里我給自己建了一個(gè)專用的練習(xí)文件夾以后所有臨時(shí)測試都放在這里不去污染系統(tǒng)目錄mkdir -p ~/lab/logsmkdir -p的意思是連同上級(jí)目錄一起創(chuàng)建如果~/lab不存在也會(huì)一并建出來。我在這個(gè)目錄下創(chuàng)建了一些測試文件、腳本草稿以及一些從網(wǎng)上復(fù)制下來的練習(xí)代碼。養(yǎng)成“所有實(shí)驗(yàn)都在自己家目錄里做”的習(xí)慣可以避免很多安全問題。比如如果某個(gè)文件誤刪了至少不會(huì)影響到系統(tǒng)級(jí)文件。對(duì)于自學(xué)者來說這一點(diǎn)尤其重要因?yàn)槲覀儎?dòng)手試錯(cuò)的機(jī)會(huì)非常多而試錯(cuò)的代價(jià)不應(yīng)該由整個(gè)系統(tǒng)來承擔(dān)。7.3 用 find 找文件比眼睛靠譜下午我一度忘記某個(gè)測試腳本放在哪個(gè)子目錄里了。在Windows下我可能會(huì)打開資源管理器一個(gè)個(gè)文件夾翻但在Linux終端里我學(xué)會(huì)了更高效的方案find ~/lab -name *.sh這條命令會(huì)在~/lab目錄下查找所有以.sh結(jié)尾的文件。find的粒度可以很細(xì)可以按名字、按類型、按大小、按修改時(shí)間來找文件。對(duì)新手來說只要會(huì)用-name這一個(gè)參數(shù)就已經(jīng)能解決大多數(shù)“我文件呢”的問題了。8. 文本處理三兄弟grep、awk、sed 的前世今生8.1 grep在垃圾堆里找針眼第三天遇到的問題里有相當(dāng)一部分可以歸結(jié)為“信息太多難以定位”。比如某個(gè)配置文件里有幾十行內(nèi)容但我只想知道其中和端口有關(guān)的那幾行。這時(shí)候grep就派上了用場grep listen /etc/nginx/nginx.confgrep會(huì)逐行讀取文件內(nèi)容把包含指定關(guān)鍵詞的行打印出來。我當(dāng)時(shí)看到輸出里確實(shí)有l(wèi)isten開頭的幾行才確認(rèn)端口配置的位置。這個(gè)命令在排查日志、檢查配置、過濾命令輸出時(shí)幾乎是無處不在的。我還學(xué)了一個(gè)特別常用的組合用法在查看某個(gè)軟件運(yùn)行狀態(tài)時(shí)如果輸出內(nèi)容太多可以接一個(gè)管道符再交給grep過濾。管道符用|表示意思是“把前面命令的輸出結(jié)果交給后面的命令繼續(xù)處理”。比如ps aux | grep nginx這一條命令能直接把進(jìn)程列表里跟nginx相關(guān)的行挑出來不用在一堆數(shù)據(jù)里慢慢找了。8.2 awk按列拆數(shù)據(jù)的好手如果說grep是“按行篩選”那么awk對(duì)我來說更像“按列拆數(shù)據(jù)”。比如我想知道日志文件里每一行的第一列是什么我可以這樣操作awk {print $1} /var/log/nginx/access.log這個(gè)命令會(huì)讀取文件每一行然后打印出第一個(gè)字段。awk支持的邏輯遠(yuǎn)不止這些但它對(duì)第三天的我來說已經(jīng)是一個(gè)“能看懂輸出里每一列代表什么”的得力工具了。整個(gè)過程就是從原始數(shù)據(jù)中抽出一列來看有點(diǎn)像Excel里只保留某一列一樣。8.3 sed批量替換配置的利器一開始我修改配置都是用文本編輯器手動(dòng)改后來發(fā)現(xiàn)遇到多個(gè)相似配置需要改動(dòng)時(shí)手動(dòng)編輯實(shí)在太慢。于是我開始接觸sed的替換功能。sed最常用的一個(gè)小片段是sed -i s/舊內(nèi)容/新內(nèi)容/g 文件名-i表示直接修改文件s是替換動(dòng)作g表示全局替換。意思就是把文件里所有“舊內(nèi)容”全部替換成“新內(nèi)容”。我在調(diào)整nginx默認(rèn)端口時(shí)就是用這條命令把80換成了其他端口非常方便。但我后來也發(fā)現(xiàn)sed的替換是純文本層面的如果你把某個(gè)路徑寫成變量形式用它就不太方便。對(duì)于新手來說先把這三個(gè)命令各自最核心的用法掌握住就足以應(yīng)付日常操作了不必一開始就追求所有高級(jí)功能。9. 服務(wù)器配置的第一次完整閉環(huán)9.1 改配置之前先備份下午我覺得對(duì)系統(tǒng)有點(diǎn)感覺了開始嘗試修改nginx的默認(rèn)配置比如更換監(jiān)聽端口。第一次改之前我犯了一個(gè)幾乎每個(gè)新手都會(huì)犯的錯(cuò)誤忘記備份。后來我重新把配置文件復(fù)制了一份sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak這樣做的意義在于一旦修改出錯(cuò)導(dǎo)致服務(wù)起不來我可以立刻用備份文件還原并重新加載。經(jīng)歷過一次“改了配置導(dǎo)致服務(wù)崩潰”之后我就把“先備份再修改”刻進(jìn)了肌肉記憶。9.2 驗(yàn)證配置是否正確在修改完配置之后我沒有直接重啟服務(wù)而是先執(zhí)行了sudo nginx -t這條命令會(huì)檢查配置文件的語法是否正確。輸出如果顯示類似“syntax is ok”的提示說明配置至少?zèng)]有格式問題。這個(gè)步驟極其重要因?yàn)槿绻渲糜姓Z法錯(cuò)誤直接重啟服務(wù)會(huì)把服務(wù)搞掛導(dǎo)致網(wǎng)站暫時(shí)無法訪問。先驗(yàn)證再重啟是降低風(fēng)險(xiǎn)的標(biāo)準(zhǔn)操作。9.3 重新加載配置而不是粗暴重啟我一開始不知道“重啟”和“重新加載”的區(qū)別直接用了systemctl restart nginx。后來才知道對(duì)于配置變更類操作更穩(wěn)妥的方式是用reloadsudo systemctl reload nginxreload會(huì)讓服務(wù)在不停機(jī)的情況下讀取新的配置文件平滑生效。而restart則是先停止再啟動(dòng)過程中會(huì)有一段短暫的中斷。對(duì)本地測試來說差別不大但如果以后部署真正的線上服務(wù)這個(gè)區(qū)別就會(huì)變得非常重要。整套流程走下來我算是把“修改配置、驗(yàn)證配置、重新加載配置、查看日志確認(rèn)效果”這條鏈路完整跑通了一遍。這個(gè)閉環(huán)看起來簡單但確實(shí)是我學(xué)Linux以來第一次獨(dú)立完成的一件“正事”。10. 第三天踩坑實(shí)錄三個(gè)最容易卡住新手的細(xì)節(jié)10.1 寫錯(cuò)了路徑還以為是命令不對(duì)我至少浪費(fèi)了二十分鐘在一個(gè)問題上輸入nginx提示找不到命令但軟件明明已經(jīng)安裝好了。后來發(fā)現(xiàn)原來當(dāng)前的用戶環(huán)境變量里沒有包含/usr/sbin這個(gè)路徑所以直接輸入命令名時(shí)找不到它必須用完整路徑/usr/sbin/nginx來執(zhí)行。解決方式有兩種一種是用完整路徑執(zhí)行另一種是把該路徑加入環(huán)境變量。對(duì)新手來說優(yōu)先使用完整路徑更簡單、更安全也能避免影響系統(tǒng)全局配置。這個(gè)坑的通用教訓(xùn)是命令提示找不到時(shí)不要馬上懷疑軟件沒裝好先用which 命令名或者ls /usr/bin/命令名查一下實(shí)際位置。10.2 端口被占用改配置還不夠有一次我改了nginx監(jiān)聽端口以為重啟之后必然生效結(jié)果訪問還是失敗。日志顯示“端口已被占用”。我后來才意識(shí)到可能有其他程序占用了我要使用的端口。解決辦法是先確認(rèn)占用端口的進(jìn)程sudo lsof -i :8080或者用sudo ss -tuln | grep 8080lsof能列出占用該端口的進(jìn)程詳情ss -tuln則是查看端口監(jiān)聽狀態(tài)的常用命令。找到占用進(jìn)程后要么關(guān)掉它要么換一個(gè)別的端口問題就迎刃而解了。10.3 改了配置沒生效這個(gè)問題困擾了我很久配置文件明明改對(duì)了服務(wù)也重新加載了但訪問結(jié)果還是老樣子。最后發(fā)現(xiàn)是因?yàn)闉g覽器有緩存我看到的其實(shí)是舊頁面。清掉瀏覽器緩存之后再訪問新頁面立刻就出來了。這件事的啟示是問題不一定出在系統(tǒng)端有時(shí)候是你自己的“查看方式”有緩存。排查問題時(shí)不要只盯著終端也要考慮外部因素。11. 自我復(fù)盤與新手心法11.1 第三天結(jié)束時(shí)我到底掌握了什么我給自己列了一份清單把當(dāng)天學(xué)到的東西做了一個(gè)匯總。這個(gè)習(xí)慣是從前兩天開始養(yǎng)成的每天結(jié)束前都把零散的知識(shí)點(diǎn)收攏一遍第二天回顧時(shí)會(huì)特別有用。文件系統(tǒng)結(jié)構(gòu)明白每個(gè)主要目錄的職責(zé)軟件包管理apt update、apt install、apt remove服務(wù)管理systemctl start/stop/status/reload權(quán)限體系chmod和chown的基本用法日志排查tail -f、grep查看日志關(guān)鍵詞進(jìn)程管理ps aux、kill、top文本處理grep過濾、awk取列、sed替換。說實(shí)話這些內(nèi)容放在老手眼里全是基本功中的基本功。但對(duì)于三天前的我來說Linux還是一個(gè)“黑乎乎的、不知道點(diǎn)哪里才能運(yùn)行程序”的系統(tǒng)。能走到這一步我自己是比較滿意的。11.2 允許自己慢下來反而學(xué)得更快學(xué)Linux的第三天我最深的心得是不要急著一天就掌握所有命令。命令是無窮無盡的而且每條命令都有幾十個(gè)參數(shù)想把它們?nèi)坑涀「静滑F(xiàn)實(shí)。更有效的辦法是遇到一個(gè)問題去查解決方案然后動(dòng)手做一遍做的時(shí)候自然而然就記住了最常用的部分。我舉個(gè)例子如果我只背“mkdir是創(chuàng)建目錄的”不實(shí)際去建幾次目錄那我永遠(yuǎn)不會(huì)有“用-p創(chuàng)建多級(jí)目錄”的需求和認(rèn)知。只有當(dāng)我遇到“一次性創(chuàng)建a/b/c三層目錄”的場景才發(fā)現(xiàn)單用mkdir會(huì)提示父目錄不存在然后一查原來有mkdir -p這個(gè)參數(shù)。這種“先踩坑再補(bǔ)齊”的學(xué)習(xí)路徑雖然慢但記憶非常牢固。所以如果你也在自學(xué)Linux不要被那些一天速成、三十天精通之類的說法嚇住。每個(gè)人的知識(shí)背景不同有的人用Linux時(shí)間很長自然上手快有的人和我一樣是零基礎(chǔ)轉(zhuǎn)過來那就允許自己一天只弄懂一個(gè)概念只要堅(jiān)持一定會(huì)越走越順。11.3 把錯(cuò)誤記錄成日志形成自己的排錯(cuò)手冊(cè)從第三天開始我養(yǎng)成了一個(gè)習(xí)慣每次遇到報(bào)錯(cuò)不僅把解決方案記錄下來還把當(dāng)時(shí)的錯(cuò)誤提示原文也記錄下來。比如“Permission denied” 對(duì)應(yīng)的是什么場景下發(fā)生的“command not found” 是在鍵入哪個(gè)命令時(shí)出現(xiàn)的“Address already in use” 最終是怎么解決的我用最簡單的文本文件把這些信息保存起來按日期和關(guān)鍵詞分類。這個(gè)文件雖然很簡陋但它是我真正親身踩坑換來的資料。以后如果再遇到類似問題直接查閱自己的記錄比在網(wǎng)上重新搜索要高效得多。12. 第三天結(jié)束時(shí)我給自己的下一個(gè)任務(wù)12.1 從“會(huì)敲命令”到“能解決問題”第三天結(jié)束前我給自己設(shè)計(jì)了一個(gè)小挑戰(zhàn)寫一個(gè)簡單的shell腳本把每天要做的環(huán)境檢查動(dòng)作自動(dòng)化。這個(gè)挑戰(zhàn)對(duì)我來說有點(diǎn)超前因?yàn)槟_本語法我還不太熟但我覺得有挑戰(zhàn)才有進(jìn)步。腳本內(nèi)容也不復(fù)雜就是每天打開終端后執(zhí)行幾條檢查命令包括查看IP地址、查看服務(wù)狀態(tài)、查看磁盤占用、查看內(nèi)存占用。我發(fā)現(xiàn)這些操作我每天都要重復(fù)做干脆用腳本把它們串起來。這個(gè)想法雖然簡單但讓我第一次體會(huì)到“用Linux去自動(dòng)化Linux操作”的感覺。腳本大概是這樣的#!/bin/bash echo 當(dāng)前登錄用戶$(whoami) echo 當(dāng)前IP地址 ip addr show | grep inet echo nginx服務(wù)狀態(tài) systemctl status nginx echo 磁盤使用情況 df -h寫完之后我用bash 腳本名執(zhí)行了一下看到一串信息依次輸出雖然還不懂每一行背后的原理但至少我知道自己已經(jīng)在用程序員的思路來使用系統(tǒng)了。12.2 給自己定下第四天的主題第三天的核心是“把服務(wù)跑起來、把日志看懂、把權(quán)限理順”。第四天我打算圍繞“腳本化和自動(dòng)化”繼續(xù)深入學(xué)一學(xué)變量、條件判斷和循環(huán)這些基礎(chǔ)語法把今天這個(gè)簡單腳本擴(kuò)展成真正能幫我干活的工具。我給自己定的方向不是去啃大部頭教材而是繼續(xù)沿用“解決實(shí)際問題驅(qū)動(dòng)學(xué)習(xí)”的方式。哪個(gè)環(huán)節(jié)不順手就去查資料搞懂哪個(gè)環(huán)節(jié)。這個(gè)過程不需要多么高深的理論支撐只要前期每一步都走得扎實(shí)后面自然會(huì)順暢起來。從第三天早晨對(duì)著終端不知所措到第三天晚上能自己寫一個(gè)簡單的檢查腳本這種變化其實(shí)是真實(shí)且踏實(shí)的。Linux并沒有傳聞中那么可怕只是它需要你換一種方式去理解“用電腦”這件事你不再只是點(diǎn)按鈕的人而是逐步變成告訴系統(tǒng)“該干什么”的人。這條路才剛開始但方向已經(jīng)清楚了。