Java的生產系統,最常用的是Linux,所以當解決生產系統問題時,理解Linux系統,熟練掌握常用命令,對于解決問題,甚至對從更高層次理解Java,都是很有幫助的。
那么,應該怎么學Linux呢?上周五聽了一次高手講座,對于學習的串聯、銜接、進階,都是很有幫助的,所以分享到這里來。
本次講座,先走馬觀花串一遍Linux命令,讓其可以輔助我們的工作。但是不僅僅是講幾個命令而已,而是希望能看清楚一些操作系統層面上的事,達到理解和境界思想上的提升。
理解是靈魂,串講是骨架,然后可以自行豐滿血肉,這是目的。
本次講座,特別適合“有一定理解,但是不深刻,或者恰恰處于進階邊緣”這種情況的人,一講,一串,醍醐灌頂,理解會立刻深了一層。
# 1、strace
strace常用來跟蹤進程執行時的系統調用和所接收的信號。
strace -T -t -f ? java Test >out 2>&1
strace -T -t -f p pid
通過這個工具,我們可以看到當Java程序,或者任何一種程序在Linux系統上運行時,實際上都是被分解成Linux API的。
講這個命令的目的,是提示我們,可以用一種方式,用一種工具,比如strace,去理解我們的程序的運行。
語言,不論在哪種平臺運行,最后都是要分解成操作系統API,分解成CPU指令。這是思維的進階,或者我們忙于日常應用系統的開發,忘記了曾經的本質。
**參考文章:**
[使用strace, ltrace尋找故障原因的線索](http://blog.csdn.net/delphiwcdj/article/details/7387325)
[五種利用strace查故障的簡單方法](http://blog.csdn.net/dlmu2001/article/details/8842891)
# 2、進程
pstree 是Linux的進程體系。
ps 是系統某個時刻的進程切面,代表某個時刻有多少個進程在運行。
因為在Linux下,包括進程、Socket等,都是以文件的形式存在的,內存中的。我們可以通過ps找出進程id,然后通過“運行時文件系統”,查看進程的任何信息。
從操作系統層面鑒定進程的信息(路徑、jar、連接等),是完全準確的,比從配置文件里面查詢準確,也不需要問別人。
ps -ef | grep catalina
cd /proc/60282/fd

可以進一步查看更多內容,比如:
a、寫多少日志:ll | grep log
b、啟動要那些jar:ll | grep jar
c、看到那些一閃一閃的了嗎?那些是socket,代表誰連我了:ll | grep socket
d、對于這些socket句柄,我們可以進一步查看是什么進程:lsof | grep 387084
# 3、內存+CPU
top,這是應該極熟的Linux命令,是Linux下常用的性能分析工具,能夠實時顯示系統中各個進程的資源占用狀況,其顯示的內容,和Windows的任務管理器是一樣的。
free ,查看內存使用情況。
我們也可以在Windows下使用jvisualvm,以圖形化的方式,查看Java應用的內存,線程,也可以把線程dump下來,比如,Test應用運行方式如下:
java -Dcom.sun.management.jmxremote.port=9998 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=192.168.80.128 Test
則可以在本地通過jvisualvm監控進程情況,在命令行輸入jvisualvm,遠程,連接ip地址,之后右鍵這個遠程連接,新建JMX連接,輸入端口,則可以監控這個遠程java進程了,截圖如下:

# 4、網絡
netstat -anop | grep LIST ? 可以查看,都啟動了那些端口,比如:

第六列“2489/mongod”,進程號2489,是mongod進程,在27017端口監聽mongo接入。
有的時候,netstat不顯示PID和應用,這一般是兩個原因:權限不夠,或者netstat版本太低,小于1.6,如果是版本太低,可以用:lsof -i:端口號,來找出PID。
參考文章:[netstat不顯示進程名pid的bug](http://blog.chinaunix.net/uid-28337979-id-4230505.html)。
netstat -anop | grep EST ? ?可以查看,端口都被誰連著呢,比如:

第4列,代表自己的IP和端口;第5列,對標對方的IP和端口;第6列,代表進程號和啟動進程的應用。
**其他常用的:**
strace -T -t -e network,poll curl www.baidu.com ? 我們可以看到從我們的機器,到百度的服務器,經過的路由路徑
cat /etc/resolv.conf ?可以看到域名解析服務器的順序
cat /etc/hosts ?The static table lookup for host name(主機名查詢靜態表)
# 5、線程
top -p 59851 ?shift+H,查看59851進程,有多少個線程。

第一列PID,線程ID,換算成16進制,就是線程棧中的NID。
我們可以使用 jstack -l 59851查看,整個進程的信息,也可以使用jstack -l 59851 | grep NID,只看一個線程棧的信息。
很多時候,查看問題的時候,都需要找出占用資源最多的線程,然后查看這個線程的線程棧信息。
這幾個步驟,操作起來很容易,其實最最關鍵的是,線程棧dump下來了,要看得懂。
關于JVM線程的講解,有一些非常好的文章,如下:
[JVM 內部運行線程介紹](http://ifeve.com/jvm-thread/)
[JVM合集](http://ifeve.com/category/jvm/)
# 6、GC
Linux下一個進程里面的線程,都是共享內存的,所以當分析內存時 ,要看進程。
jstat -gccause ?59851 1000 ? ? jstat,即JVM Statistics Monitoring Tool,用于收集HotSpot虛擬機各方面的運行數據

我們不怕YGC,YGC很頻繁,很快,系統耗時極短,微妙級,對于用戶來說是沒有感覺的;
但是FGC要注意,FGC進行的時候,JVM是假死的,只進行FullGC,不處理其他請求,可能會持續幾秒,FGC太多,說明YGC回收不了,太多的對象進入老年代,很快占滿,系統肯定有問題的。
java -XX:+PrintFlagsInitial ,可以查看JVM的參數配置情況,比如,默認情況下,我們可以看到,Survior:Eden ?= 1:8,New:Old ?= 2:1。
jmap -histo 59851 | more ?Memory Map for Java,生成虛擬機的內存轉儲快照(heapdump文件)

通過jmap,可以找出系統中可能有安全隱患(比如太多而不能回收)的對象。
通過這些手段,不用分析代碼,不用停機,就可以找出問題,解決問題。
jps、jstat、jstack、jmap,這些不是Linux命令,而是JDK寫好的放在rt.jar里面的用于輔助診斷的Java APP。
GC是Java程序員的基本功,應該理解的很清晰。
# 7、dstat和iftop
場景1:演示通過sftp上傳文件
可以在top中看到sshd和sftp耗費CPU資源很大,因為sftp是基于sshd的;可以在dstat中看到,receive流量很大。
場景2:演示http請求百度首頁,通過ss5代理壓測,在ss5機器中,dstat顯示的send和recv幾乎一樣。
和我們通常理解的,應該會有很少的發出數據,和很多的接收數據不一致。原因是:
這種理解不對的,作為ss5代理的機器,既從遠端接收到大量數據,同時把接收到的大量數據,轉發給它所代理的機器,所以有這個網絡現象。
這個時候,我們通過iftop,則可以清楚的看到IP到IP的發出發入數據包。
所以,知道,借助于工具,基于Linux的知識,基于Java的知識,定位問題,找出問題,是很關鍵的。
iftop 是第三方的,是一個實時流量監控工具:
主要用來顯示本機網絡流量情況及各機器相互通信的流量集合,如單獨同那臺機器間的流量大小,非常適合于代理服務器和iptables服務器使用。
官方網站:http://www.ex-parrot.com/~pdw/iftop/。
**安裝步驟:**
yum -y install flex byacc ?libpcap ncurses ncurses-devel libpcap-devel
wget http://soft.kwx.gd/tools/iftop-0.17.tar.gz #獲得軟件包
tar zxvf iftop-0.17.tar.gz ? ? ? ? ? ? ? ? ? ? ?#解壓
cd iftop-0.17 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#進入目錄
./configure ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#使用默認配置
make && make install ? ? ? ? ? ? ? ? ? ? ? ? ? ?#編譯并安裝
如果libpcap包裝不上的話,需要到http://pkgs.org/自行下載rpm進行安裝。
dstat是Linux自帶的,可以yum安裝。
**dstat截圖:**

**iftop截圖:**

# 8、“|” ?管道。連接、過濾,這是管道的作用,就像連接千家萬戶的自來水管
管道操作符,按行給數據,一行一給,把上個命令的輸出,變成下個命令的輸入。
經常使用的參數-c ,類似于 SQL中的group by。
在linux中,要把日志文件,當成數據庫表,日志文件也是有行有列的。日志要標準,要有規律,就會很方便的分割查找。
我們可以借助less、more、cat、sort、uniq、grep、awk等命令,很方便的分析日志。
另外,awk是一個強大的文本分析工具,awk在對數據分析并生成報告時,很強大。簡單來說awk就是把文件逐行的讀入,以空格為默認分隔符將每行切片,切開的部分再進行各種分析處理。
# 9、其他常用命令
df -h ?顯示磁盤分區使用情況
du -sh /root/temp ?顯示某個文件夾的大小 ? ?
find /root/temp -type f -name "*.txt" | xargs grep "main" ?在/root/temp目錄下,在普通文件中,在擴展名為txt的文件中,查找含有main字符串的行
lsof -l 顯示所有的socket句柄
lsof | grep deleted ?剛剛rm或者echo沖文件內容后,看看空間有沒有釋放
sed 文件內容查找和替換
vim 文本編輯器,常用就會熟悉。開始的時候記錄最常用的,比如,翻屏:CTRL+U(D),2gg,3dd,3dw,yy,/查找,?查找。
# 10、學會分析錯誤的思路
學會錯誤的模擬重現,會模擬重現就能解決。模擬重現的手段:可以開發一些質量差的代碼,把錯誤做出來。
工具只是幫助我們定位問題的,幫我們記錄發生問題時的操作系統切面,要理解這個切面所代表的意義、所隱含的異常,還需要對相關基礎知識的深刻了解。比如:
- 用jstat看GC,需要對Java的內存管理、垃圾收集技術深入了解;
- 用netstat看網絡,需要對網絡知識,特別是TCP,有深入了解;
- 用jstack轉儲線程棧,需要對Java線程的知識,有深入了解。
- 前言
- Java之旅--如何從草根成為技術專家
- 《深入理解Java虛擬機》學習筆記
- 《Spring3.X企業應用開發實戰》學習筆記--IoC和AOP
- 《Tomcat權威指南》第二版學習筆記
- Java之旅--多線程進階
- Java之旅--Web.xml解析
- 《Spring3.X企業應用開發實戰》學習筆記--DAO和事務
- 《Spring3.X企業應用開發實戰》學習筆記--SpringMVC
- Java之旅--定時任務(Timer、Quartz、Spring、LinuxCron)
- Spring實用功能--Profile、WebService、緩存、消息、ORM
- JDK框架簡析--java.lang包中的基礎類庫、基礎數據類型
- JDK框架簡析--java.util包中的工具類庫
- JDK框架簡析--java.io包中的輸入輸出類庫
- Java之旅--通訊
- Java之旅--XML/JSON
- Java之旅--Linux&java進階(看清操作系統層面的事)
- Java之旅--硬件和Java并發(神之本源)
- Java之旅--設計模式
- jetty