Linux命令拾遺-常用的輔助開發類命令
原創:打碼日記(微信公眾號ID:codelogs),歡迎分享,轉載請保留出處。
簡介
之前介紹了大量的命令,有基礎操作相關的,也有問題診斷相關的,但Linux中還有一類命令,被時常使用在工作當中,如curl、mysql、ssh、vim等,本篇對它們做一個整體介紹。
使用curl除錯介面
curl是一個多功能的網路客戶端命令,可以支援非常多的網路協議,如HTTP、FTP、IMAP、SMTP、SMB、LADP、MQTT等,但大部分情況下,我們將其作為HTTP協議的客戶端工具來使用,用來除錯HTTP介面,常見用法如下:
# 傳送HTTP請求,預設GET方法 curl 'http://localhost/user/get' # -d指定請求體,有-d引數後,curl會使用POST方法 # 如果不指定Content-Type,預設是application/x-www-form-urlencoded curl 'http://localhost/user/add' -d 'id=32&name=zhangsan' # --data-urlencode,將請求體做urlencode編碼後再發送 curl 'http://localhost/user/add' --data-urlencode 'id=32&name=zhangsan' # 用-H新增請求頭,如下指定Content-Type是application/json curl 'http://localhost/user/add' -H 'Content-Type: application/json; charset=UTF-8' -d '{"id":32,"name":"zhangsan"}' # 使用-X,可以指定請求方法 curl -X DELETE 'http://localhost/user/delete' curl -X PUT 'http://localhost/user/modify' -d 'id=32&name=zhangsan' # -G,可以將請求體拼接到url,所以下面兩種呼叫方法是等效的 curl -G 'http://localhost/user/add' -d 'id=32&name=zhangsan' curl 'http://localhost/user/add?id=32&name=zhangsan' # -i和-I可以顯示響應頭,區別是-i會同時顯示響應頭與內容,-I只顯示響應頭 curl -i 'http://localhost/user/add?id=32&name=zhangsan' # 檢視curl處理細節(非常常用) curl -v http://www.baidu.com # -s不顯示進度提示資訊與錯誤資訊,-S顯示錯誤資訊 curl -sS http://www.baidu.com # 使用time執行curl,只能看到請求整體響應時間 $ time curl "http://www.baidu.com" -o /dev/null -s ... real 0m0.066s user 0m0.010s sys 0m0.000s # 如下,通過-w可以列印請求詳細耗時情況,包括dns查詢耗時,連線建立耗時、收到服務端響應的首位元組耗時、響應結果全部獲取到的耗時,注意時間都是累加的,即相對於命令執行那一刻開始 $ curl -w " time_namelookup:%{time_namelookup}s\n time_connect:%{time_connect}s\n time_starttransfer:%{time_starttransfer}s\n time_total:%{time_total}s\n speed_download:%{speed_download}\n http_code:%{http_code}" "http://www.baidu.com" -o /dev/null -s time_namelookup:0.009906s time_connect:0.035826s time_starttransfer:0.062370s time_total:0.062406s speed_download:38403.000 http_code:200
另外,curl也可以用來做檔案上傳與下載,如下:
# 下載檔案,-L讓curl支援重定向,-#顯示進度條,-O響應體下載為檔案 curl -LO -# http://localhost/user/avatar/xxxxx.png # wget也經常用於下載檔案 wget http://localhost/user/avatar/xxxxx.png # 上傳檔案,-F類似於html裡的form,使用-F後,Content-Type預設是multipart/form-data,這正是web上常見的檔案上傳方式 curl http://localhost/user/avatar/upload -F 'id=32' -F 'avatar=@./xxxxx.png' # 上傳檔案,這也是一種上傳檔案的方式,請求體直接就是檔案內容,整個傳給伺服器 curl http://localhost/user/avatar?id=32 --data-binary '@./xxxxx.png' -# # curl也可以訪問ftp伺服器,如下: # 下載ftp檔案 curl -u 使用者名稱:密碼 ftp://localhost/user/avatar/xxxxx.png -O # 上傳檔案到ftp curl -u 使用者名稱:密碼 ftp://localhost/user/avatar/ -T ./xxxxx.png
另外,有時使用curl會出現一些莫名其妙的麻煩,這裡分享一下我遇到的幾種,大家留個眼熟:
# 一些網站https證書過期了,curl報curl: (60) SSL certificate problem: unable to get local issuer certificate # 可以用-k忽略https證書校驗 curl -k https://www.ywnds.com/ # 一些網站網速極慢,導致curl會阻塞很久,需要指定下網路超時時間 curl --connect-timeout 2 --max-time 2 http://www.baidu.com # 一些網站會使用gzip壓縮響應內容,這會導致curl報Warning: Binary output can mess up your terminal. Use "--output -" to tell # 使用--compressed即可,使用gzip -d也可以 curl -H 'Accept-Encoding:gzip' http://www.baidu.com/ --compressed curl -H 'Accept-Encoding:gzip' http://www.baidu.com/ | gzip -d # 一些網站任然在使用GBK編碼,這會導致curl結果亂碼,甚至直接報Failed writing body錯誤,這時需要使用iconv轉換一下編碼 curl -i http://www.xxxxx.com | iconv -f GBK # 有時,你想在輸出響應結果後再輸出一個換行,避免多次curl的結果混在一行上 curl -w '\n' http://localhost/health
可以發現,curl幾乎可以定義HTTP請求的方方面面,因此,我經常使用curl作為與同事間溝通介面細節的工具,我也看到過不少廠商的api文件,直接使用curl來定義,畢竟對於開發者來說,任何文件都沒有程式碼解釋得清楚。
使用mysql命令執行SQL
mysql命令使用起來比較簡單,如下:
mysql -h localhost -P 3306 -u root -psecret test_db
執行上面命令後,就會進入SQL互動介面,然後你就可以執行SQL語句了,注意指定密碼的方式,-p
與secret
之間不能有空格。
其它比較有用的選項如下:
選項 | 作用 |
---|---|
-A | 不載入表名、列名等元資料,網路不好時可加快命令啟動速度,代價是按Tab鍵無法自動補齊表名與列名了 |
--default-character-set utf8mb4 | 指定字符集,避免某些環境下的亂碼 |
-e | 指定要執行的SQL,執行完後直接退出,不進入命令互動介面 |
-N | 查詢結果中不展示列名 |
-t | 查詢結果以表格形式輸出 |
-B | 查詢結果不以表格形式輸出,欄位以tab分隔 |
-X | 查詢結果以XML形式輸出 |
-U | 安全地執行查詢與更新,比如你操作大表時忘記了加limit這種 |
--pager | 指定結果分頁展示器,預設是標準輸出,--pager=less 表示使用less作為分頁展示器 |
這裡面比較有意思的是pager
,pager
可以設定成任何linux命令,來處理查詢結果,如下:
$ mysql -h localhost -P 3306 -u root -psecret test_db
# 未設定pager的情況,查詢結果直接輸出
mysql> select * from app_log where create_time >= '2021-04-18' and create_time < '2021-04-18 17:35:00';
+-------+------------------------------------+---------------------+---------------------+-------+----------+
| id | log_info | create_time | update_time | seq | add_time |
+-------+------------------------------------+---------------------+---------------------+-------+----------+
| 7706 | DOwhV4Odbuf0wVwyZxrJFbBOEGF0fhf7Ab | 2021-04-18 17:22:48 | 2022-03-11 00:25:49 | 7706 | 0 |
| 8155 | abc | 2021-04-18 16:55:42 | 2022-07-18 21:28:29 | 8155 | 0 |
| 14535 | uAXFeCJ3jtxhiQJS26q43MarWL5M | 2021-04-18 17:06:54 | 2022-06-26 21:19:42 | 14535 | 0 |
| 15303 | abc | 2021-04-18 17:30:18 | 2022-05-04 00:38:15 | 15303 | 0 |
| 31933 | cLfKXMYkaIta16kzmyWKFC | 2021-04-18 17:06:19 | 2022-09-14 20:14:10 | 31933 | 0 |
| 32503 | Rb6yMJ6fvViF28YWN9GA | 2021-04-18 17:33:59 | 2022-03-14 17:38:04 | 32503 | 0 |
+-------+------------------------------------+---------------------+---------------------+-------+----------+
6 rows in set (0.29 sec)
# 設定pager為cat -n,為輸出內容新增行號
mysql> pager cat -n
PAGER set to 'cat -n'
mysql> select * from app_log where create_time >= '2021-04-18' and create_time < '2021-04-18 17:35:00';
1 +-------+------------------------------------+---------------------+---------------------+-------+----------+
2 | id | log_info | create_time | update_time | seq | add_time |
3 +-------+------------------------------------+---------------------+---------------------+-------+----------+
4 | 7706 | DOwhV4Odbuf0wVwyZxrJFbBOEGF0fhf7Ab | 2021-04-18 17:22:48 | 2022-03-11 00:25:49 | 7706 | 0 |
5 | 8155 | abc | 2021-04-18 16:55:42 | 2022-07-18 21:28:29 | 8155 | 0 |
6 | 14535 | uAXFeCJ3jtxhiQJS26q43MarWL5M | 2021-04-18 17:06:54 | 2022-06-26 21:19:42 | 14535 | 0 |
7 | 15303 | abc | 2021-04-18 17:30:18 | 2022-05-04 00:38:15 | 15303 | 0 |
8 | 31933 | cLfKXMYkaIta16kzmyWKFC | 2021-04-18 17:06:19 | 2022-09-14 20:14:10 | 31933 | 0 |
9 | 32503 | Rb6yMJ6fvViF28YWN9GA | 2021-04-18 17:33:59 | 2022-03-14 17:38:04 | 32503 | 0 |
10 +-------+------------------------------------+---------------------+---------------------+-------+----------+
6 rows in set (0.29 sec)
# 設定pager為grep abc,只檢視包含abc的行
mysql> pager grep abc
PAGER set to 'grep abc'
mysql> select * from app_log where create_time >= '2021-04-18' and create_time < '2021-04-18 17:35:00';
| 8155 | abc | 2021-04-18 16:55:42 | 2022-07-18 21:28:29 | 8155 | 0 |
| 15303 | abc | 2021-04-18 17:30:18 | 2022-05-04 00:38:15 | 15303 | 0 |
6 rows in set (0.29 sec)
# 設定pager為less分頁器,這樣可以在查詢結果中翻頁與搜尋了
mysql> pager less -iSX
PAGER set to 'less -iSX'
mysql> select * from app_log where create_time >= '2021-04-18' and create_time < '2021-04-18 17:35:00';
+-------+------------------------------------+---------------------+---------------------+-------+----------+
| id | log_info | create_time | update_time | seq | add_time |
+-------+------------------------------------+---------------------+---------------------+-------+----------+
| 7706 | DOwhV4Odbuf0wVwyZxrJFbBOEGF0fhf7Ab | 2021-04-18 17:22:48 | 2022-03-11 00:25:49 | 7706 | 0 |
| 8155 | abc | 2021-04-18 16:55:42 | 2022-07-18 21:28:29 | 8155 | 0 |
| 14535 | uAXFeCJ3jtxhiQJS26q43MarWL5M | 2021-04-18 17:06:54 | 2022-06-26 21:19:42 | 14535 | 0 |
| 15303 | abc | 2021-04-18 17:30:18 | 2022-05-04 00:38:15 | 15303 | 0 |
| 31933 | cLfKXMYkaIta16kzmyWKFC | 2021-04-18 17:06:19 | 2022-09-14 20:14:10 | 31933 | 0 |
| 32503 | Rb6yMJ6fvViF28YWN9GA | 2021-04-18 17:33:59 | 2022-03-14 17:38:04 | 32503 | 0 |
+-------+------------------------------------+---------------------+---------------------+-------+----------+
(END)
# 設定pager為md5sum -,這樣可以為查詢結果生成md5
# 對比md5就能知道當前時間段資料是否產生了變化
mysql> pager md5sum -
PAGER set to 'md5sum -'
mysql> select * from app_log where create_time >= '2021-04-18' and create_time < '2021-04-18 17:35:00';
40ed2c49a72ff68ba11b97d843bb4da2 -
6 rows in set (0.29 sec)
mysql> select * from app_log where create_time >= '2021-04-18' and create_time < '2021-04-18 17:35:00';
40ed2c49a72ff68ba11b97d843bb4da2 -
6 rows in set (0.31 sec)
# 先使用cat將第一次查詢結果儲存到檔案中,然後使用icdiff對比查詢結果是否變化
mysql> pager cat > result.txt
PAGER set to 'cat > result.txt'
mysql> select * from app_log where create_time >= '2021-04-18' and create_time < '2021-04-18 17:35:00';
6 rows in set (0.31 sec)
mysql> pager icdiff result.txt /dev/stdin
PAGER set to 'icdiff result.txt /dev/stdin'
mysql> select * from app_log where create_time >= '2021-04-18' and create_time < '2021-04-18 17:35:00';
如果要恢復pager的話,只需要輸入nopager
並回車即可。
另外,對於mysql的相關命令列選項,是可以永久配置在mysql.cnf
配置檔案中的,這樣可以避免每次都要在命令列帶上自己常用的選項,如下:
$ sudo vim /etc/mysql/conf.d/mysql.cnf
[mysql]
default-character-set=utf8mb4
pager=less -iSFX
safe-updates=TRUE
使用ssh管理主機
登入遠端主機
一般我們使用ssh來登入並管理遠端主機,比如安裝軟體、排查問題等,常見用法如下:
# 登入到主機192.168.0.1上,使用work使用者,然後輸入work使用者密碼即可
$ ssh [email protected]
# -p指定埠,有時主機為了安全會不使用預設的22埠
$ ssh [email protected] -p 8022
# 直接在遠端主機上執行命令
$ ssh [email protected] -e 'ping www.baidu.com'
PING www.a.shifen.com (112.80.248.76) 56(84) bytes of data.
64 bytes from 112.80.248.76 (112.80.248.76): icmp_seq=1 ttl=54 time=19.1 ms
64 bytes from 112.80.248.76 (112.80.248.76): icmp_seq=2 ttl=54 time=19.9 ms
上傳下載檔案
除了遠端登入到主機上,我們經常需要上傳下載檔案,如下:
# scp和ssh是一個軟體包的,為上傳下載場景定製的命令,用法如下:
# 下載192.168.0.1主機上/home/work/logs/app.log到本機的logs目錄下
$ scp [email protected]:/home/work/logs/app.log ./logs/
# 上傳本機./logs/app.log檔案到192.168.0.1主機上/home/work/logs/目錄裡
$ scp ./logs/app.log [email protected]:/home/work/logs/
# 實際上scp的原始檔與目標檔案都可以是遠端主機上的,如下:
$ scp [email protected]:/home/work/logs/app.log [email protected]:/home/work/logs/app.log
# 實際上使用ssh也能上傳下載
# 使用ssh下載,其中pv命令是為了檢視進度,換成cat其實也可以
$ ssh [email protected] 'cat /home/work/logs/app.log' | pv > ./logs/app.log
# 使用ssh上傳,其中pv命令是為了檢視進度,換成cat其實也可以
$ pv ./logs/app.log | ssh [email protected] 'cat > /home/work/logs/app.log'
# 對比遠端檔案與本地檔案內容
$ ssh [email protected] 'cat /path/to/remotefile' | icdiff /path/to/localfile –
sshfs掛載遠端目錄
如果你覺得這樣上傳下載好麻煩,可以使用sshfs將遠端主機上的目錄,直接掛載到本機上,這樣你就可以像訪問本機檔案一樣訪問遠端檔案了。
sshfs是基於fuse機制與ssh協議實現的使用者態檔案系統,只要是你能用ssh的地方都能用sshfs,並且由於是使用者態的檔案系統,因此它並不像NFS那樣需要特殊許可權,只要網路連通即可,使用方法如下:
# sshfs掛載目錄
$ sshfs [email protected]:/home/work/logs /home/work/logs
# 列出檔案
$ ls /home/work/logs
app_2022-01-23T12:05:51.log app_2022-01-23T12:05:53.log app_2022-01-23T12:05:57.log app_2022-01-23T12:06:00.log
# 使用ssh列出遠端目錄,與上面結果是一樣的
$ ssh [email protected] 'ls /home/work/logs'
app_2022-01-23T12:05:51.log
app_2022-01-23T12:05:53.log
app_2022-01-23T12:05:57.log
app_2022-01-23T12:06:00.log
也許你會奇怪,為啥上面結果一個沒換行而另一個換行了,這是因為ls會檢測輸出物件是否是終端,如果是終端就會橫排展示,否則豎排展示,不信你可以ls | cat
看看。
其實好多命令都會有這種行為,比如curl
預設不顯示進度,但如果輸出物件不是終端,如curl|cat
,就會顯示出進度資訊。
免密碼登入
一旦你這樣用著ssh,就會發現每次都需要輸入密碼好麻煩,好在ssh提供了私鑰認證機制,因此我們可以生成一對公私鑰來避免每次都要輸入密碼,如下:
# 使用ssh-keygen生成ssh金鑰對,使用rsa演算法,長度4096,生成的金鑰預設~/.ssh目錄下,私鑰叫id_ras,公鑰叫id_ras.pub
ssh-keygen -o -t rsa -b 4096 -C "[email protected]"
# 使用ssh-copy-id將公鑰上傳到目標主機上
ssh-copy-id -i ~/.ssh/id_rsa.pub [email protected]
# 沒有ssh-copy-id時,這樣上傳公鑰也是可以的
cat ~/.ssh/id_rsa.pub | ssh [email protected] 'cat >> ~/.ssh/authorized_keys'
# 測試公鑰是否生效,如果看到Authentication succeeded (publickey).字樣,說明成功
ssh -vT [email protected] </dev/null
是的,相信不少用過github/gitee/gitlab
的同學會感覺到熟悉,其實github
等也是一樣使用ssh金鑰來避免git操作需要輸入密碼的,配置過程是類似的:
- 使用ssh-kengen生成金鑰對。
- 將公鑰手動拷貝到github的ssh金鑰管理頁面上並儲存。
- 測試配置成功。
埠轉發
有時,兩個主機A、C之間網路並不互通,但A和B互通,B和C互通,這種情況下,我們可以利用B主機做一個埠轉發,使得主機A可以訪問主機C上的網路服務。
能夠實現埠轉發的軟體有很多,如iptables、socat、portmap、rinetd等,而ssh也是常見的一個,用法如下:
# ssh本地埠轉發,在A機器上執行,會在A機開啟2001埠,並將此埠資料發到B機,B機又轉發到C機的80埠
ssh -fgN -L2001:host_c:80 work@host_b
# ssh遠端埠轉發,在B機器上執行,在A機開啟22333埠(由A機sshd服務開啟),將A機22333埠流量通過B機(中轉機)轉到C機的80埠上
ssh -fgN -R 22333:host_c:80 work@host_a
# ssh遠端動態埠轉發,在B機器上執行,會在A機開啟2222埠開放socks代理服務,被代理的資料會發到B機,B機又轉發到任何B機能訪問的網路服務上
ssh -fgN -R 2222 work@host_a
# ssh本地動態埠轉發,在A機器上執行,會在A機開啟2222埠開放socks代理服務,被代理的資料會發到B機,B機又轉發到任何B機能訪問的網路服務上
ssh -Nfg -D 2222 work@host_b
# A機通過本機socks代理,登入到C機
ssh -o ProxyCommand='ncat --proxy 127.0.0.1:2222 --proxy-type socks5 %h %p' work@host_c
# A機通過B機ssh登入C機,其實就是兩次ssh登入過程
ssh -t work@host_b 'ssh work@host_c'
為啥會有本地埠轉發與遠端埠轉發兩種轉發方式呢?
這和允許網路連線的方向有關,比如有些情況下,B能連線到A,但A不能連線到B,這時就需要使用遠端埠轉發了!
總結
除了這些常用的命令外,Linux中還有很多其它型別的工具命令,比如:
- vim、emacs:用來編輯文字檔案,實際上你也可以把他們配置成類似idea的IDE,感興趣可參考spacevim、spacemacs。
- openssl:用來生成金鑰檔案、證書檔案以及做加密、解密等操作。
- ffmpeg:可以處理音視訊檔案,如mp4轉flv、mp4轉gif、錄屏、剪裁、觀看直播等。
- convert:可以進行圖片格式轉換,如png轉jpeg。
- jp2a:可以將圖片變成字元畫。
- wkhtmltopdf、xhtml2pdf可以將html轉換為pdf,pandoc可以進行各種文件的格式轉換。
這裡就不一一介紹了,後面有機會可以單獨拿出來介紹介紹。
本系列文章索引
Linux命令拾遺-入門篇
Linux命令拾遺-文字處理篇
Linux命令拾遺-軟體資源觀測
Linux命令拾遺-硬體資源觀測
Linux命令拾遺-剖析工具
Linux命令拾遺-動態追蹤工具
Linux命令拾遺-理解系統負載
Linux命令拾遺-top中的%nice是啥
Linux命令拾遺-網路抓包工具
Linux命令拾遺-檢視系統資訊