Linux shell必知必會
我個人很喜歡使用 Linux 系統,雖然說 Windows 的圖形化介面做的確實比 Linux 好,但是對 指令碼的支援太差了。一開始有點不習慣 命令行操作,但是熟悉了之後反而發現移動滑鼠點點點才是浪費時間的罪魁禍首。那麼對於 Linux 命令行,本文不是介紹某些命令的用法,而是說明一些簡單卻特別容易讓人迷惑的細節問題。 |
- 1、標準輸入和命令引數的區別。
- 2、在後臺執行命令在退出終端後也全部退出了。
- 3、單引號和雙引號表示字串的區別。
- 4、有的命令和sudo一起用就 command not found。
這個問題一定是最容易讓人迷惑的,具體來說,就是搞不清什麼時候用管道符|和檔案重定向>,<,什麼時候用變數$。
比如說,我現在有個自動連線寬頻的 shell 指令碼connect.sh,存在我的家目錄:
$ where connect.sh /home/fdl/bin/connect.sh
如果我想刪除這個指令碼,而且想少敲幾次鍵盤,應該怎麼操作呢?我曾經這樣嘗試過:
$ where connect.sh | rm
實際上,這樣操作是錯誤的,正確的做法應該是這樣的:
$ rm $(where connect.sh)
前者試圖將where的結果連線到rm的標準輸入,後者試圖將結果作為命令列引數傳入。
標準輸入就是程式語言中諸如scanf或者readline這種命令;而引數是指程式的main函式傳入的args字元陣列。
管道符和重定向符是將資料作為程式的標準輸入,而$(cmd)是讀取cmd命令輸出的資料作為引數,前文畫圖解釋過:
輸入重定向就是說,程式想讀取資料的時候就會去 files[0] 讀取,所以我們只要把 files[0] 指向一個檔案,那麼程式就會從這個檔案中讀取資料,而不是從鍵盤。
同理,輸出重定向就是把files[1]指向一個檔案,那麼程式的輸出就不會寫入到顯示器,而是寫入到這個檔案中。
管道符其實也是異曲同工,把一個程式的輸出流和另一個程式的輸入流接起一條「管道」,資料就在其中傳遞:
Linux 程式、執行緒、檔案描述符的底層原理
用剛才的例子說,rm命令原始碼中肯定不接受標準輸入,而是接收命令列引數,刪除相應的檔案。作為對比,cat命令是既接受標準輸入,又接受命令列引數:
$ cat filename ...file text... $ cat < filename ...file text... $ echo 'hello world' | cat hello world
如果命令能夠讓終端阻塞,說明該命令接收標準輸入,反之就是不接受,比如你只執行cat命令不加任何引數,終端就會阻塞,等待你輸入字串並回顯相同的字串。
比如說你遠端登入到伺服器上,執行一個 Django web 程式:
$ python manager.py runserver 0.0.0.0 Listening on 0.0.0.0:8080...
現在你可以通過伺服器的 IP 地址測試 Django 服務,但是終端此時就阻塞了,你輸入什麼都不響應,除非輸入 Ctrl-C 或者 Ctrl-/ 終止 python 程式。
可以在命令之後加一個&符號,這樣命令列不會阻塞,可以響應你後續輸入的命令,但是如果你退出伺服器的登入,就不能訪問該網頁了。
如果你想在退出伺服器之後仍然能夠訪問 web 服務,應該這樣把命令包裹成這樣(cmd &):
$ (python manager.py runserver 0.0.0.0 &) Listening on 0.0.0.0:8080... $ logout
每一個命令列終端都是一個 shell 程式,你在這個終端裡執行的程式實際上都是這個 shell 程式分出來的子程式。正常情況下,shell 程式會阻塞,等待子程式退出才重新接收你輸入的新的命令。加上&號,只是讓 shell 程式不再阻塞,可以繼續響應你的新命令。但是無論如何,你如果關掉了這個 shell 命令列埠,依附於它的所有子程式都會退出。
而(cmd &)這樣執行命令,則是將cmd命令掛到一個systemd系統守護程式名下,認systemd做爸爸,這樣當你退出當前終端時,對於剛才的cmd命令就完全沒有影響了。
類似的,還有一種後臺執行常用的做法是這樣:
$ nohup some_cmd &
nohup命令也是類似的原理,不過通過我的測試,還是(cmd &)這種形式更加穩定。
不同的 shell 行為會有細微區別,但有一點是確定的,對於$,(,)這幾個符號,單引號包圍的字串不會做任何轉義,雙引號包圍的字串會轉義。
shell 的行為可以測試,使用set -x命令,會開啟 shell 的命令回顯,你可以通過回顯觀察 shell 到底在執行什麼命令:
可見 echo $(cmd) 和 echo "$(cmd)",結果差不多,但是仍然有區別。注意觀察,雙引號轉義完成的結果會自動增加單引號,而前者不會。
也就是說,如果 $ 讀取出的引數字串包含空格,應該用雙引號括起來,否則就會出錯。
有時候我們普通使用者可以用的命令,用sudo加許可權之後卻報錯 command not found:
$ connect.sh network-manager: Permission denied $ sudo connect.sh sudo: command not found
原因在於,connect.sh這個指令碼僅存在於該使用者的環境變數中:
$ where connect.sh /home/fdl/bin/connect.sh
當使用sudo時,系統認為是 root 使用者在執行命令,所以會去搜尋 root 使用者的環境變數,而這個指令碼在 root 的環境變數目錄中當然是找不到的。
解決方法是使用指令碼檔案的路徑,而不是僅僅通過指令碼名稱:
$ sudo /home/fdl/bin/connect.sh
以上就是全部內容,對於出現的一些難以理解的現象,要多思考和嘗試,熟練之後,shell 命令列真的可以帶來很大的便利。
原文地址: https://www.linuxprobe.com/linux-shell-must-know.html
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31559985/viewspace-2680295/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Linux必會必知Linux
- Linux 程式必知必會Linux
- 程式猿必知必會Linux命令之awkLinux
- MySQL 必知必會MySql
- git必會必知Git
- Redis 必知必會Redis
- ThreadLocal必知必會thread
- Activity 必知必會
- JSON 必知必會JSON
- HashMap必知必會HashMap
- 效能測試必知必會:Shell指令碼設計實踐指南指令碼
- notion database 必知必會Database
- 必知必會Java命令-jpsJava
- Redis 必知必會之 APIRedisAPI
- mysql必知必會筆記MySql筆記
- Mysql必知必會練習MySql
- HTTP 必知必會的那些HTTP
- 01-mysql必知必會MySql
- 常用技術必知必會
- Linux 必會Linux
- 【必知必會的MySQL知識】①初探MySQLMySql
- 【必知必會的MySQL知識】②使用MySQLMySql
- Linux網路命令必知必會之瑞士軍刀 nc(netcat)Linux
- Java必知必會之註解Java
- Redis 必知必會之持久化Redis持久化
- SQL必知必會筆記(上)SQL筆記
- SQL必知必會筆記(下)SQL筆記
- Flutter 外掛使用必知必會Flutter
- ElasticSearch必知必會-進階篇Elasticsearch
- 必知必會之Lambda表示式
- MYSQL中的鎖必知必會MySql
- 【必知必會的MySQL知識】④DCL語言MySql
- 【必知必會的MySQL知識】⑤DQL語言MySql
- 【必知必會的MySQL知識】③DML語言MySql
- tableau必知必會之VMware 搭建 Tableau Server for Linux 單機環境ServerLinux
- Docker 必知必會1----初識Docker
- Android 中高階面試必知必會Android面試
- 《MySQL必知必會》萬用字元 ( like , % , _ ,)MySql字元