關於 Linux shell 你必須知道的

2022-07-04 00:54:07 字數 3878 閱讀 5586

-----------

我個人很喜歡使用 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的標準輸入,後者試圖將結果作為命令列引數傳入。

ps:我認真寫了 100 多篇原創,手把手刷 200 道力扣題目,全部發布在 labuladong的演算法小抄,持續更新。建議收藏,按照我的文章順序刷題,掌握各種演算法套路後投再入題海就如魚得水了。

標準輸入就是程式語言中諸如scanf或者readline這種命令;而引數是指程式的main函式傳入的args字元陣列

前文「linux檔案描述符」說過,管道符和重定向符是將資料作為程式的標準輸入,而$(cmd)是讀取cmd命令輸出的資料作為引數。

用剛才的例子說,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命令就完全沒有影響了。

類似的,還有一種後台執行常用的做法是這樣:

$ nohub some_cmd &
nohub命令也是類似的原理,不過通過我的測試,還是(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時,系統會使用/etc/sudoers這個檔案中規定的該使用者的許可權和環境變數,而這個指令碼在/etc/sudoers環境變數目錄中當然是找不到的。

ps:我認真寫了 100 多篇原創,手把手刷 200 道力扣題目,全部發布在 labuladong的演算法小抄,持續更新。建議收藏,按照我的文章順序刷題,掌握各種演算法套路後投再入題海就如魚得水了。

$ sudo /home/fdl/bin/connect.sh
_____________

你必須知道的關於tcp keepalive 設定

1.引數設定 檢視相關的引數 sysctl a grep tcp keepalive net.ipv4.tcp keepalive intvl 30 net.ipv4.tcp keepalive probes 2 net.ipv4.tcp keepalive time 160 設定相關的引數 sys...

關於Tomcat,你必須知道的那些事兒

1.如何修改tomcat的埠號?答 在conf的server.xml中 找到 的地方,修改port引數即可。2.如何配置虛擬目錄?path 表示虛擬目錄名,訪問時使用虛擬目錄名作為web目錄訪問 docbase 表示實際專案的磁碟位置。reloadable 3.如何部署web應用?其中通過瀏覽器訪問...

關於 Http 協議,你必須要知道的

http協議是hyper text transfer protocol 超文字傳輸協議 的縮寫,是用於從全球資訊網伺服器傳輸超文字到本地瀏覽器的傳送協議。http 是基於 tcp ip 協議通訊協議來傳遞資料 html 檔案,檔案,查詢結果等 它不涉及資料報 packet 傳輸,主要規定了客戶端和伺...