最近想學學Linux下的Shell,基礎知識都看完了,想做點東西,但是絞盡腦汁還是沒想起來做點什麼,最後我也查了一下Shell的作用,到現在還沒有一個很好的答案,都說Shell可以直接與計算機交互,但是我想其他語言不也能方便的與計算機進行交互嗎?Shell實現的功能,其他語言也能實現,可能會稍微複雜一些,難道Shell就這點優勢嗎?望解惑!感激不盡


Shell就是命令行工具的膠水,沒有任何語言能像Shell一樣方便地將一大堆命令行工具組合起來。原則上來說,Shell做什麼都可以,但顯然它最適合的是自動化,因為只需要將你原來手動敲的命令都複製到一個文件裡面就行了。

Shell跟標準的編程語言區別很大,它基本上是一個面向字元串的編程語言,組合用好awk/sed/grep,偶爾配合eval,有時候會發揮奇效,但也有可能原地爆炸。可以跟Python之類的其他語言配合起來,比如某個複雜的功能使用一個Python腳本來實現,然後在shell中調用這個腳本實現較複雜的功能;或者反過來,在Python腳本中調用外部的Shell腳本來提高自動化的效率,也是可以的。


我們不妨想像一下彙編程序員、C/C++程序員以及java程序員還有項目經理分別是怎麼寫程序的。

彙編程序員:這個語言沒有if沒有switch也沒有for/while,甚至就連做個加法,我都得明確指出是單位元組加法、雙位元組加法還是雙字/四字加法……哦,我還得明確說明進位位是不是也要加上去。麻煩?連基本數據結構都沒有,只能操作裸內存?但CPU的每一個動作都得聽我指揮!

C/C++程序員:我不用管if/switch/for/while是如何實現的,我可以直接調用函數,大多數時候不用管函數調用究竟是什麼……

(彙編程序員:誰壓棧誰維護sp,是長跳轉還是短跳轉?現場誰保存誰恢復?)

C/C++程序員:滾!精神污染!程序員不需要考慮這些,他們真正要考慮的是演算法!演算法!

Java程序員:一個天天糾結內存糾結指針的程序員也是醉了。咱不能多談談業務少談談演算法嗎?

C/C++程序員:你喫內存,你沒我快!

Java程序員:設計模式……

C/C++程序員:語言設計太水才需要一大堆設計模式。以及,你喫內存,你沒我快!

項目經理:都別吵吵了!去給我寫個hello world!

眾程序員:切!外行,連hello world都不會寫!

項目經理:這就是你們寫的hello world?說好了要支持多國語言呢?

眾程序員:你哪說了?

項目經理:啊?沒說?那現在說了!

眾程序員:去TM的需求變更!加班你掏錢?


你看,每一種語言,它都封裝了一些東西——除了彙編。

這些封裝,使得它的使用者可以更簡潔的完成日常功能的同時,也不可避免的要付出一些底層控制能力/靈活性方面的代價——畢竟你只能通過它提供的、「封裝」的代理,才能完成任務。

其中,彙編可以控制一切;但用它時,就連if你都得自己拆開,用cmp/jnz/jz等指令的組合實現類if控制結構——在程序流程式控制制可以無限精確、無限複雜的同時……你不覺得每次都得根據實際情況,把if這倆字母拆成三五條甚至十幾條語句,太過繁瑣了嗎?

而C/C++呢,你近似可以控制一切,彙編能做到的,你99.99%都能做到。這就大大提高了開發效率。

等到了java,你失去了對內存的大部分控制權;但當你要寫一個商業/工業程序時,卻前所未有的簡單。

腳本語言,如python、php等,也都類似——它們比java更簡單,但也更慢。

再往上,就是shell腳本了。

shell腳本是一種比python更「糙」、因此性能等方面更為受限的語言;但它有個極大的優點,那就是可以把其他人寫的程序本身,像其他語言的庫函數那樣使用。

為了做到這個,它要求每個程序都把命令行參數當作「函數輸入」、向stdout/stderr的輸出當作函數輸出,同時以程序返回值說明執行成功與否。

這個約定是強制性的,在操作系統設計時就確定了的——這也是C語言的main函數需要返回一個int的原因。

但是,這個「命令行參數」的約定也束縛了shell,使得它比起其他語言更在乎空格/回車等符號——因為它的每一行,都必須是「命令 參數1 參數2」的格式。

這個約定就使得它語法怪異,也很難像其他編程語言那樣,支持語法結構的任意嵌套——不管有多像,它畢竟是「用命令行模擬出來的語法結構」。

那麼,這就是shell腳本的定位:它是一種只能支持較為簡單邏輯的、可以直接把任意現有程序當作函數無縫集成的「超高級語言」;但因為「命令行模擬」這個本質,它的語法較為笨拙,很難像正規的腳本語言那樣得到很多很多的語法糖或者其它便利。

但,同樣的,其它腳本語言語法結構是靈活了;但它們也就不可能很方便的和系統安裝的現有程序交互了——注意是不方便,不是不能。你完全可以通過popen/shellexec等方法調用外部程序。

程序員都是一羣特別特別「懶」的人。他們會根據目標的不同,選擇能夠最輕易達到目標的方法——這種選擇同樣包括編程語言。這反過來也導致了諸多不同定位的語言的出現。


shell是沒有圖形界面時與系統交互的手段,操作系統不會限制用戶用哪一種語言編程並運行,所以規定了這樣一種通用io法則,嚴格上說不算語言,一般的shell功能只需要詞法分析即可。在伺服器編程,部署,調試的時候沒有圖形界面,shell幾乎是唯一的界面


彙編器和連接器將多個彙編指令組織在一起,構成可行性文件

Shell 將多個可執行文件組織在一起,構成批處理腳本

操作系統中將大量可執行文件有效組織在一起,shell發揮了重要的作用


shell是OS內核與用戶之間的橋樑。

實際上,用戶沒法直接使用OS內核,需要通過shell把命令解析、交給內核,然後內核準備環境、啟動程序。shell還有另外一種模式,就是非交互模式,可以做一些系統初始化,系統管理的工作,還可以充當其他程序的啟動腳本,把多個程序(不是函數)組合起來。

都說Shell可以直接與計算機交互,但是我想其他語言不也能方便的與計算機進行交互嗎?

不是shell可以和計算機交互,是用戶通過shell與OS交互。其他語言編譯完,就等待用戶運行,可是怎麼讓OS知道用戶要運行哪一個呢?參數是什麼呢?這就需要shell了。從角色上看,windows系統的explorer程序也是一種shell,只不過是圖形的,用戶通過點擊與OS完成交互。

所以,shell的最重要的作用就是把用戶的命令交給OS,和一般的計算機語言不在同一層。


推薦閱讀:
相關文章