有段時間沒有跟學弟學妹們互動了,因為最近這段時間實在是太忙了,因為快臨近雙十一嘛!
言歸正傳啊,上次有學妹跟我聊,剛去公司不熟悉環境,Linux系統不熟悉,很多命令不知道怎么用,外加上公司里面查詢日志還是使用跳板機的方式,所以特別被動。今天就跟大家聊聊一些簡單實用的Linux命令來面對一些工作中遇到問題。
什么是Linux?
Linux全稱GNU/Linux,是一種免費使用和自由傳播(開源)的UNIX操作系統,安裝在我們我們的計算機硬件上,用來管理計算機的硬件和軟件資源管理等。
當然也并不只是因為免費和開源導致Linux為啥這么火的,相比于widows系統它還是有很多優點的:
Linux相比較于widows系統他更注重安全性,比如說在Linux目錄的下的文件都有一個權限的控制,不同的用戶訪問的權限能有不同的控制權限,所以它的安全性更好一點
相比較于widows系統,Linux的穩定性更好,很少會出現系統崩潰的情況出現,因為權限控制到位了,很多核心應用文件沒有權限是不能進行操作的,還有很多配置更改都不需要去重啟機器,不會影響到相關的服務程序。
Linux還有很多其他的一些特點比如說靈活性,因為開源嘛,還有對硬件沒啥要求等等,所以現在很多的公司都是使用Linux系統來作為服務器。
而我們在服務器終端輸入的命令通過命令解析器(常見的有 shell,)處理完之后才真正的被運行。
今天主要是從三個方面跟學妹聊Linux,其實就是一些我們工作中比較實用的命令
- Linux的基礎命令
- Java中的服務器排查問題命令
- 擴展Arthas中的常見用法(號稱 Java診斷神器)
Linux的基礎命令
一些簡單的常見的我就不跟大家一一列舉出來了,這個直接百度一下就全部都有了
文件相關命令
ls :顯示當前目錄下所有的文件
ls -a :列出所有文件,包括以 "." 開頭的隱含文件。
ll :顯示當前文件或目錄的詳細信息,含有時間、讀寫權限、大小、時間等信息,等于是 ls -l 命令
du :用于顯示目錄或文件的大小。一般用來查看文件的大小,比如說看一些dump的日志的文件的大小
du -sh * :查詢當前目錄下所有的文件的大小以K,M,G為單位,提高信息的可讀性。
- 場景:查看服務器中一個文件(比如日志)大小,在刪除磁盤文件的時候能有一個對比,那個文件占用磁盤最大
cat :輸出當前文件內容。
- 場景:一般就是用來查看當前文件的內容,比如說要看下服務器的啟動service.sh腳本文件中的內容(cat service.sh)
- 擴展:cat -n fileName 輸出文件內容并且在前面加上行號。
- 擴展:cat -b fileName 輸出文件內容并且在前面加上行號,與上面的不同是會過濾空白行。
- 擴展:cat -n textfile1 > textfile2 把 textfile1 的文檔內容加上行號后輸入 textfile2 這個文檔里。
more :跟cat差不多,但是有一個優點就是展示出來的是按照頁的形式出來,可以接著按space空格鍵向下翻頁
- 擴展:more -num 一次顯示行數。
- 擴展:more +num 從第num行開始顯示。
chmod :修改當前用戶對文件的權限
- r=4,w=2,x=1,所以想要rxw 讀寫和可執行權限,那就是4+2+1=7,而一個位數表示一個角色,chmod a=rwx txt1.txt就可以理解為就是 chmod 777 txt1.txt
- u 表示該文件的擁有者,g 表示與該文件的擁有者屬于同一個群體(group)者,o 表示其他以外的人,a 表示這三者皆是
- + 表示增加權限、- 表示取消權限、= 表示唯一設定權限
- r 表示可讀取,w 表示可寫入,x 表示可執行
- 場景:chmod這個命令實用比較廣泛,但是說白了就是一點更改文件權限,但是權限這個東西怎么加,是加所有用戶還是其他?是加讀寫還是去除讀寫?這個就需要理解 u、g、o、a、+、-、=、r、w、x等含義
- 擴展:chmod ugo+r txt1.txt 或者 chmod a+r txt1.txt 設置txt1.txt 對所有的用戶角色可讀
- 擴展:chmod 777 file ,chmod也可以用數字來代表權限問題,
diff :用于比較文件的差異。
- 擴展:diff log1.log log2.log -y -W 50并排輸出兩個文件的不同。
grep :用于查找文件里符合條件的字符串,這個是最常見的也是日常查詢文件最常用的。
- $grep2021-10-27T20:17:20.519+0800gc.log|wc-l
- 1
- $grep2021-10-27T21gc.log|grep25:33
- 2021-10-27T21:25:33.413+0800:797616.955:[GC(AllocationFailure)2021-10-27T21:25:33.414+0800:797616.955:[ParNew:848318K->18793K(943744K),0.0263809secs]1283786K->454263K(1992320K),0.0270603secs][Times:user=0.09sys=0.00,real=0.03secs]
- 擴展:grep "aaa" log.log -A 10 ,除了顯示符合搜索條件的那一列之外,并顯示該行之后的10行內容。wc
- 擴展:grep "aaa" log.log -B 10 ,除了顯示符合搜索條件的那一列之外,并顯示該行之前的10行內容。
- 擴展:grep "aaa" log.log | grep "bb" -A 10,同時搜索滿足條件以上兩個條件的結果,并向下在打印剩下的10行。
- 擴展:grep "aaa" log.log | wc -l,統計滿足條件的的次數
scp : 命令用于 Linux 之間復制文件和目錄。可以用來作為下載文件到本地的一種方式。scp 是 secure copy 的縮寫, scp 是 linux 系統下基于 ssh 登陸進行安全的遠程文件拷貝命令。
- 打開本地系統服務 文件 遠程登入 允許訪問 所有用戶
- 輸入:scp heap.hprof aobing@172.19.36.87:/Users/aobing/Downloads
- 輸入本機電腦登入密碼即可,就能顯示當前在下載的進度了
- 擴展:舉一個用法的例子,假設用我自己當前電腦作為演示,怎么去把我們跳板機中的dump文件下載到我們本地,以便于我們自己來分析堆棧呢?
- 這個是比較常用的方法,可以有其他的用法,就因個人而已吧
mkdir :用于創建目錄。這個是最簡單的了。
- 擴展:mkdir aaaa 創建一個aaaa文件
kill :刪除執行中的程序或工作,這個需要慎重使用,我們可以一般在我們的電腦卡死,或者我們本地啟動tomcat端口被占用了,但是我們又沒有找到,可以ps查一下進程ID,然后kill一下
- 擴展:kill 14269,殺死14269這個進程
- 擴展:kill -KILL 14269,強制殺死14269這個進程
- 擴展:kill -9 14269,徹底殺死14269這個進程
rm :用于刪除一個文件或者目錄。在使用這個命令之前需要注意,不要隨便執行這個命令,文件一旦通過rm命令刪除,則無法恢復所以可能有時候不小心刪除某些文件,第二天新聞就出來“杭州某公司丙某因為執行時rm -rf命令,導致服務器或者數據庫 數據丟失 造成嚴重損失”
- $rmgc.log.20210506151038
- rm:removeregularfile‘gc.log.20210506151038’?y
- 擴展:rm gc.log.20210506151038 ,刪除 gc.log.20210506151038 文件?會跳出一個確定提示,輸入 y,則是刪除
- 擴展:rm -f gc.log.20210506151038,不會產生確認刪除提示,直接刪除文件
- 擴展:rm -rf gc.log.20210506151038,不會產生確認刪除提示,直接刪除文件,并且會把當前目錄下的所有文件一并刪除,非常的暴力。
gzip :用于壓縮文件。文件經它壓縮過后,其名稱后面會多出".gz"的擴展名。當服務器某個文件過大時,你下載非常的慢,所以考慮一下壓縮之后再下載。
- 擴展:gzip gc.log.20210506151038 ,壓縮一下文件gc.log.20210506151038,壓縮之后會生成一個文件gc.log.20210506151038.gz,這個比較簡單,壓縮完可以使用上面的 ll 或者 du 等相關命令再查看下文件的大小。
- 擴展:gzip -<壓縮效率> gc.log.20210506151038 , 壓縮效率是一個介于1-9的數值,預設值為"6",指定愈大的數值,壓縮效率就會愈高,控制壓縮比例。
ps :(全拼:process status)用于顯示當前進程的狀態,主要是用來查詢當前進程的狀態,比如說需要查詢一下當前tomcat的相關信息,或者說服務器配置的tomcat的一些啟動參數,都是可以看到。
- $ps-ef|greptomcat
- www383304000:02pts/000:00:00grep--color=autotomcat
- www557918Oct22?10:36:09/opt/vdian/java/bin/java-Djava.util.logging.config.file=/home/www/item-sell/.server/conf/logging.properties-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager-Djdk.tls.ephemeralDHKeySize=2048-server-Xms5g-Xmx5g-XX:MetaspaceSize=256m-XX:MaxMetaspaceSize=256m-Xmn2g-XX:MaxDirectMemorySize=512m-XX:SurvivorRatio=8
- 擴展:ps -ef | grep 進程關鍵字,查詢某個關鍵字的進程,如下所示,能顯示很多信息。我這里沒有復制全,自己可以進公司的服務試一下,不會有問題的。
- 擴展:ps -A,列出所有的進程
- 擴展:ps -aux,顯示所有包含其他使用者的行程
- 等等還有很多很多,我就舉出常用的,一一列舉大家不常用也就沒有什么意思。
pwd :用于顯示工作目錄,這個命令就很簡單了, 沒有什么特殊的參數啥的,就是顯示當前目錄地址。
- $pwd
- /home/www
- 擴展:pwd,跟簡單,后面不需再加什么參數,顯示一下目錄,方便下我們復制文件的目錄地址。
source :這個命令一般就是和**點(.)**是一樣的效果,就是修改了某個文件不用重啟,而可以立馬生效
- 擴展:source fileName等于. fileName是一個效果。使改動的文件立即生效
tail :用于查看文件的內容。通常比如說我們需要查看正在變動的日志文件,那就可以用這個命令了。
- 擴展:tail -f filename,會把 filename 文件里的最尾部的內容顯示出來,并且不斷刷新,只要 filename 更新就可以看到最新的文件內容。
- 擴展:tail -20f filename,會把 filename 文件里的最后的20行內容顯示出來,并且不斷刷新。
- 擴展:tail -c 20 filename,顯示文件 filename 的最后 20 個字符。
- 擴展:tail -n +20 filename,顯示文件 filename 的內容,從第 20 行至文件末尾。
以上就是在Linux中我們工作中比較常用的一些命令,以及它們的一些擴展,當然,這個并不是全部的,我也只是列出了冰山一角。如果還是沒有滿足你們的日常工作可能就需要你們自己的再去查查資料,看看書了。
Java中的常見排查問題命令
在工作中都會多少都會接觸到一些服務器調優,或者說一些線上問題排查,這是在面試過程中,面試官比較喜歡問的一個問題,也是為了考察面試者的思考能力以及動手能力和基礎是否扎實。都說是面試造飛機,進去擰螺絲。很多時候問題都輪不到你來處理,但是你還是得會。
之前也有很多學弟學妹來給我留言怎么去排查一些線上服務器問題,比如說某個時間 dubbo線程池滿,內存告警,以及OOM等。
所以這里主要也就跟學弟學妹從三個方面負載、cpu、內存 這三個方面去聊聊,怎么通過一些命令去看這些東西。
負載
負載是對當前CPU的工作量的一個度量,通常負載越低,說明機器工作輕松,反之則越累,高負載的情況下就可能會出現機器無法處理其他的業務請求了。
查看負載的命令有很多,top、uptime 等都可以查看
- $uptime
- 01:13:53up319days,14:05,1user,loadaverage:0.39,0.34,0.39
從這個信息看,我們要關注的 是后面的 load average 顯示的信息
- load average:0.39, 0.34, 0.39 這三個數字的意思分別是1分鐘、5分鐘、15分鐘內系統的平均負荷
- user:1 user,當前一個用戶登入
前面顯示的信息就是服務器啟動到現在已經有多長時間了。
top 命令是比較常見的,也是最常用的,因為他顯示的信息也是最全的。
- $top
- top-01:19:56up319days,14:11,1user,loadaverage:0.13,0.25,0.35
- Tasks:145total,1running,144sleeping,0stopped,0zombie
- %Cpu(s):2.8us,0.9sy,0.3ni,95.6id,0.1wa,0.0hi,0.2si,0.2st
- KiBMem:8173324total,142188free,5861548used,2169588buff/cache
- KiBSwap:0total,0free,0used.1634952availMem
- PIDUSERPRNIVIRTRESSHRS%CPU%MEMTIME+COMMAND
- 7704www20097140244.824g5932S27.661.93717:34java
- 2150root30107850085867235804S1.70.73254:22polaris-agent
- 16043www20038007324026043788S0.34.9603:29.85java
- 1root2004353633961948S0.00.056:12.32systemd
這里可以看到除了顯示平均負載的情況下還能顯示 CPU相關信息。還有每個進程占用的資源情況。
針對負載的問題,我們怎么能確定負載當前是高還是低?
一般來說只要負載超過0.7可能就表示當前負載有點高了,需要排查一下,這個是針對單核CPU來說的,如果是多核CPU來說,我們就是CPU核數乘以0.7來計算的。
在top顯示的進程信息的時候,我們可能看到當前進程中 7704這個進程 占用CPU最高,而且是我們的Java進程
假設現在是CPU被這個進程占用百分之90,那我們就可以重點排查一下這個進程到底在做什么導致CPU占用這么高
- $top-Hp7704
- top-01:33:05up319days,14:24,1user,loadaverage:0.12,0.23,0.31
- Threads:651total,5running,646sleeping,0stopped,0zombie
- %Cpu(s):2.1us,0.8sy,0.3ni,96.4id,0.1wa,0.0hi,0.3si,0.1st
- KiBMem:8173324total,143612free,5862648used,2167064buff/cache
- KiBSwap:0total,0free,0used.1633376availMem
- PIDUSERPRNIVIRTRESSHRS%CPU%MEMTIME+COMMAND
- 9046www20097140244.824g5932S4.661.913:12.99java
- 8415www20097140244.824g5932R2.661.9442:19.10java
- 8418www20097140244.824g5932R2.661.9424:18.67java
top -Hp 是查看當前進程中的所有的線程情況,同樣的可以看到 9046 這個線程占用比較高,那么我們再接著分析這個線程在處理什么邏輯就可以了。
- $printf%s9046
- 2356
使用printf命令查看這個線程的16進制
最后使用jstack命令查看當前線程正在執行的什么方法
- $jstack7704|grep-A102356
- "DubboServerHandler-10.33.130.247:2201-thread-154"#867daemonprio=5os_prio=0tid=0x00007f4ef005a800nid=0x2356waitingoncondition[0x00007f4ec1acf000]
- java.lang.Thread.State:WAITING(parking)
- atsun.misc.Unsafe.park(NativeMethod)
- -parkingtowaitfor<0x0000000708513d48>(ajava.util.concurrent.SynchronousQueue$TransferStack)
- atjava.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
- atjava.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:458)
- atjava.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:362)
- atjava.util.concurrent.SynchronousQueue.take(SynchronousQueue.java:924)
- atjava.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
- atjava.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
- atjava.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
從這里就能大致做一個分析了,但是這個不一定都能確定出來問題,但是能給我展示出一些有用的信息。具體的還需要我們再去看下這里執行了什么方法。
再或者我們直接使用 jmap 來dump內存。
CPU
在看CPU信息的時候主要關注的點就是CPU的使用率。
在上面使用top能查看CPU的使用情況之后,還有一個vmstat命令,這個命令有一個好處可以看到內存使用,虛擬內存還有IO等信息。
- $vmstat
- procs-----------memory-------------swap-------io-----system--------cpu-----
- rbswpdfreebuffcachesisobiboincsussyidwast
- 000172572021337800015100419500
- us:用戶進程執行時間百分比(如果當前值比較高,說明用戶進程消耗高)
- sy:內核系統進程執行時間百分比(如果系統比較高,那么你可以找運維了)
- id:空閑時間百分比
- wa:IO等待時間百分比(如果IO時間長,那說明機器在大量的處理磁盤的讀寫操作,這個也是關注的重點,可能寫日志啊等都有可能)
- st:虛擬 CPU 等待實際 CPU 的時間的百分比
所以觸發CPU高的場景也有很多,這個CPU高可能只是一個 “果的關系”,具體的“因”是啥還需要在進步排查,比如說再用top,按上面的思路再看下。
內存
內存是保證我們程序能正常運行的關鍵,這個也是需要我們查看的一個關鍵指標數據。
查看內存的命令除了上面的top之外還有一個free來查看內存數據。細心的人應該發現了top命令真的展示信息最全了。當然我們還是主要分析一下這個命令展示的數據,以及怎么分析這些數據。
- $free
- totalusedfreesharedbuff/cacheavailable
- Mem:8173324587086812644840181221760081625028
- Swap:000
Mem行,顧名思義也就是展示內存的使用情況
- total:表示物理內存總大小
- used:已經被使用的物理內存和交換空間
- free:表示未被分配的內存
- shared:共享使用的物理內存大小
- buff/cache buffer 和 cache 使用的物理內存大小
- available:當前剩余實際可用內存(還可以被應用程序使用的物理內存大小)
Swap:這個被稱之為交換區,當系統內存不夠使用時,釋放磁盤內存,來保證當前運行的程序能正常使用(Linux會將一些不常訪問的數據保存在交換區,但是目前一般不會配置)。
- Total:Swap內存總大小
- Used:已分配的Swap大小
- Free:未被分配的內存
所以在查看內存的時候我們還是不能不能確定這個因果關系,在出現問題的時候,如果我們沒有一個很好的思路,就先看看這三個指標,可以通過一些排除法來給我們一些思考。
但是現在我們最常用的基本都是看top 一下看看各個指標,如果確定是Java進程的問題,很多時候都會去dump一下內存,來分析一下對象信息。如果有很多大對象,一直被引用那就具體看代碼了。一般的問題大部分都是因為我們的代碼引起的。
Arthas
說到dump內存,常見的可能就是使用jmap 命令來處理,但是這里跟大家分享一個新的阿里開源的工具Arthas。
Arthas 是Alibaba開源的Java診斷工具,深受開發者喜愛。在線排查問題,無需重啟;動態跟蹤Java代碼;實時監控JVM狀態。
我個人覺得也確實是蠻好用的。官方文檔:https://arthas.aliyun.com/doc/arthas-tutorials.html?language=cn
首先就是先安裝一下
- $curl-Ohttps://arthas.aliyun.com/arthas-boot.jar
- %Total%Received%XferdAverageSpeedTimeTimeTimeCurrent
- DloadUploadTotalSpentLeftSpeed
- 100138k100138k00420k0--:--:----:--:----:--:--421k
啟動
- $java-jararthas-boot.jar
- [INFO]arthas-bootversion:3.5.4
- [INFO]Foundexistingjavaprocess,pleasechooseoneandinputtheserialnumberoftheprocess,eg:1.ThenhitENTER.
- *[1]:20851/home/www/xxxxx/xxxx.14_75b3f783befda28c22c6ce8b48d7f41b_prod.jar
- [2]:6152com.xxxx.xxxx.xxxx.main.Main
這里看到會有兩個應用但是我們需要進入Java應用,所以直接按2,進入。
因此如果需要dump堆棧內存只要一個命令就可以了
dump到指定文件
- heapdump/tmp/dump.hprof
只dump live對象
- heapdump--live/tmp/dump.hprof
在dump堆棧的時候是會觸發fullGC的這個需要注意一下,一般針對這有問題的機器,可以先把這個機器offline掉,這樣流量進不來,保證平臺先“止血“。
在獲取到堆棧信息之后那就是分析堆棧了,可以MAT、Jprofiler等,但是還有一個簡單的輕小的gceasy也可以去分析一個堆棧信息。
還有一個我們比較常用的功能就是分析我們方法的耗時問題。
假設現在我們有個方法,里面有很多子方法,包含很多rpc掉用,以及很多很多的業務邏輯在里面,那我們怎么去獲取每個子方法的耗時呢?
針對相信上面的問題,很多人都會想到先用System.currentTimeMillis()來獲取當前時間,然后每執行一個方法在減去開始的時間以此來得到一個時間差,再用日志打印出來。這樣雖然是可行的,但是非常的麻煩。Arthas里面有一個trace命令就能幫我處理這個問題。
- [arthas@6152]$tracecom.xxxx.xxx.xxx.service.ItemSnapshotServicesaveFullSnapshot
- PressQorCtrl+Ctoabort.
- Affect(classcount:1,methodcount:1)costin231ms,listenerId:3
- `---ts=2021-10-2802:50:23;thread_name=ConsumeMessageThread_4;id=3c2;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@18b4aac2
- `---[3.939696ms]com.xxx.xx.xx.service.ItemSnapshotService:saveFullSnapshot()
- +---[0.047704ms]com.xxx.xx.xx.service.ItemSnapshotService:$jacocoInit()
- +---[0.014779ms]com.xx.xx.xx.xx.snapshot.ItemSnapShot:getItemId()#304
- +---[0.008545ms]com.xxx.xxx.xx.x.snapshot.ItemSnapShot:getOperateTime()#305
- +---[0.306668ms]com.xx.xxx.xx.service.ItemSnapshotService:buildRowKey()#306
- +---[0.006373ms]com.xxx.xx.xxx.domain.snapshot.ItemSnapShot:getAfter()#307
- +---[0.004874ms]com.xx.xx.xx.domain.snapshot.ItemSnapShot:getBefore()#307
- +---[0.058562ms]
展示結果如上所示,還有能做過濾啊,統計次數啊等等一些功能。
Arthas它的功能還有很多很多啊,我也一下子說不完,感興趣的同學可以去看看我貼的那個官方文檔。之所以跟大家聊這個是我覺得確實挺好用的,在我們的工作中能起到一個很好的幫助。
總結
這次跟大家分享的都是我個人感覺在工作中比較實用的一些常見命令以及工具,以及在工作中會經常遇到的一些問題。這也是在面試的過程中您能和面試官聊的東西。只有當別人不知道而你知道那你就走在別人的前面,不是故意要卷,而是當前互聯網就是一個卷的時代了。
本次要跟學弟學妹聊的一些命令就到到這里了,雖然擴展了很多其他的東西,但是我感覺還是比較有用的吧!!!
原文鏈接:https://mp.weixin.qq.com/s/T6try9YIKh8gTLG2lyKKOQ