理解Unix可執(zhí)行文件

Unix可執(zhí)行文件

在Linux/Mac系統(tǒng)中身弊,可執(zhí)行文件長(zhǎng)成上面的樣子丸边,其實(shí)我們可以把任何一個(gè)文本文件(包括普通文本儿普、shell腳本文件等)轉(zhuǎn)換成一個(gè)Unix可執(zhí)行文件贮竟。

新建一個(gè)文本丽焊,輸入shell格式的終端命令较剃,然后另存為無(wú)格式文件,比如另存為名script技健。然后打開(kāi)終端進(jìn)入其所在目錄写穴,輸入 sudo chmod u+x script 回車。執(zhí)行后雌贱,那個(gè)script文件就會(huì)變成類似批處理的文件啊送,雙擊就能運(yùn)行里面的終端命令。

在Linux中欣孤,我們執(zhí)行內(nèi)置命令時(shí)馋没,直接輸入命令名稱即可,如:

#將a重命名為b
$ mv a b 

而在執(zhí)行自己寫(xiě)好的程序時(shí)降传,卻要帶上./篷朵,如:

$ hello
hello: command not found
$ ./hello
hello world

這是為什么呢?它們有什么區(qū)別呢婆排?

首先声旺,我們必須要清楚的是,執(zhí)行一條Linux命令段只,本質(zhì)是在運(yùn)行一個(gè)程序腮猖,如執(zhí)行l(wèi)s命令,它執(zhí)行的是ls程序赞枕。那么在Linux系統(tǒng)上的shell中(Mac的上終端中)輸入一條命令澈缺,它會(huì)經(jīng)歷哪幾個(gè)查找過(guò)程?到底發(fā)生了什么鹦赎?

1. 查找命令

要執(zhí)行一個(gè)命令谍椅,就要找到該命令對(duì)應(yīng)程序所在的位置误堡,啟動(dòng)它執(zhí)行它古话。

alias中查找

alias命令可用來(lái)設(shè)置命令別名,而單獨(dú)輸入alias可以查看到已設(shè)置的別名:

$ alias
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l='ls -CF'
alias la='ls -A'
alias ll='ls -alF'
alias ls='ls --color=auto'

如果這里沒(méi)有找到你執(zhí)行的命令锁施,那么就會(huì)接下去查找陪踩。如果找到了,那么就會(huì)執(zhí)行下去悉抵。

內(nèi)置命令中查找

不同的shell包含一些不同的內(nèi)置命令肩狂,通常不需要shell到磁盤(pán)中去搜索。通過(guò)help命令可以看到有哪些內(nèi)置命令:

$ help

通過(guò)type 命令可以查看命令類型:

$ type echo
echo is a shell builtin

如果是內(nèi)置命令姥饰,則會(huì)直接執(zhí)行傻谁,否則繼續(xù)查找。

PATH中查找

以ls為例列粪,在shell輸入ls時(shí)审磁,首先它會(huì)從PATH環(huán)境變量中查找谈飒,PATH內(nèi)容是什么呢,我們看看:

$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games

所以它會(huì)在這些路徑下去尋找ls程序态蒂,按照路徑找到的第一個(gè)ls程序就會(huì)被執(zhí)行杭措。使用whereis也能確定ls的位置:

$ whereis ls
ls: /bin/ls /usr/share/man/man1/ls.1.g

既然它是在bin目錄下,那么我把ls從bin目錄下移走是不是就找不到了呢钾恢?是的手素。

$ mv /bin/ls /temp/ls_bak  #測(cè)試完后記得改回來(lái)奧

現(xiàn)在再來(lái)執(zhí)行l(wèi)s命令看看:

$ ls 
The program 'ls' is currently not installed. You can install it by typing:
apt install coreutils

沒(méi)錯(cuò),它會(huì)提示你沒(méi)有安裝這個(gè)程序或者命令沒(méi)有找到瘩蚪。

所以你現(xiàn)在明白為什么你第一次安裝jdk或者python的時(shí)候要設(shè)置環(huán)境變量了吧泉懦?不設(shè)置的話行不行?

行募舟。這個(gè)時(shí)候你就需要指定路徑了祠斧,怎么指定路徑?無(wú)非就是那么幾種拱礁,相對(duì)路徑琢锋,絕對(duì)路徑等等。比如:

$ cd /temp
$ ./ls_bak

// 或
$ /temp/ls_bak

是不是發(fā)現(xiàn)和運(yùn)行自己的普通程序方式?jīng)]什么差別呢呢灶?
到這里吴超,如果還沒(méi)有找到你要執(zhí)行的命令,那么就會(huì)報(bào)錯(cuò)鸯乃。

2. 確定解釋程序

在找到程序之后呢鲸阻,需要確定解釋程序。什么意思呢缨睡?
shell通衬胥玻可以執(zhí)行兩種程序,一種是二進(jìn)制程序奖年,一種是腳本程序细诸。

而一旦發(fā)現(xiàn)要執(zhí)行的程序文件是文本文件,且文本未指定解釋程序陋守,那么就會(huì)默認(rèn)當(dāng)成shell腳本來(lái)執(zhí)行震贵。例如,假設(shè)有test.txt內(nèi)容如下:

echo -e "hello world"

賦予執(zhí)行權(quán)限并執(zhí)行:

$ chmod +x test.txt
$ ./test.txt
hello world

當(dāng)然了水评,我們通常會(huì)在shell腳本程序的來(lái)頭帶上下面這句:

#!/bin/bash

這是告訴shell猩系,你要用bash程序來(lái)解釋執(zhí)行test.txt。作為一位調(diào)皮的開(kāi)發(fā)者中燥,如果開(kāi)頭改成下面這樣呢寇甸?

#!/usr/bin/python

再次執(zhí)行之后結(jié)果如下:

$ ./test.txt
  File "./test.txt", line 2
    echo -e "hello world"
                        ^
SyntaxError: invalid syntax

是的,它被當(dāng)成python腳本來(lái)執(zhí)行了,自然就會(huì)報(bào)錯(cuò)了拿霉。

那么如果是二進(jìn)制程序呢式塌?就會(huì)使用execl族函數(shù)去創(chuàng)建一個(gè)新的進(jìn)程來(lái)運(yùn)行新的程序了。

小結(jié)一下前面的內(nèi)容友浸,就是說(shuō)峰尝,如果是文本程序,且開(kāi)頭沒(méi)有指定解釋程序收恢,則按照shell腳本處理武学,如果指定了解釋程序,則使用解釋程序來(lái)解釋運(yùn)行伦意;對(duì)于二進(jìn)制程序火窒,則直接創(chuàng)建新的進(jìn)程即可。

3. 運(yùn)行

前面我們也已經(jīng)看到了運(yùn)行方式驮肉,設(shè)置環(huán)境變量或者使用相對(duì)路徑熏矿,絕對(duì)路徑即可。不過(guò)對(duì)于shell腳本离钝,你還可以像下面這樣執(zhí)行:

$ sh test.txt
$ . test.txt  

即便test.txt沒(méi)有執(zhí)行權(quán)限票编,也能夠正常執(zhí)行。

什么卵渴?你說(shuō)為什么txt也能執(zhí)行慧域?注意,Linux下的文件后綴不過(guò)是為了方便識(shí)別文件類型罷了浪读,以.txt結(jié)尾昔榴,并不代表一定是文本。當(dāng)然在這里它確實(shí)是碘橘,而且還是ASCII text executable:

$ file test.txt
test.txt: Bourne-Again shell script, ASCII text executable
$ file hello
hello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 2.6.32, BuildID[sha1]=8ae48f0f84912dec98511581c876aa042824efdb, not stripped

4. 擴(kuò)展一下

那么如果讓我們自己的程序也能夠像Linux內(nèi)置命令一樣輸入即可被識(shí)別呢互订?

將程序放到PATH路徑下

第一種方法就是將我們自己的程序放到PATH中的路徑中去,這樣在shell輸入hello時(shí)痘拆,也能找到仰禽,例如我們將其放在/bin目錄下:

$ hello
hello world
$ whereis hello
hello: /bin/hello

也就是說(shuō),如果你的程序安裝在了PATH指定的路徑错负,就需要配置PATH環(huán)境變量坟瓢,在命令行輸入就可以直接找到了勇边。

設(shè)置PATH環(huán)境變量

那么如果想在指定的目錄能夠直接運(yùn)行呢犹撒?很簡(jiǎn)單,那就是添加環(huán)境變量粒褒,例如將當(dāng)前路徑加入到PATH中:

$ PATH=$PATH:./   #這種方式只在當(dāng)前shell有效识颊,所有shell生效可修改/etc/profile文件
$ hello
hello world

設(shè)置別名

$ alias hello="/temp/hello"
$ hello
hello world

以上三種方法都可以達(dá)到目的。

執(zhí)行順序

那么假設(shè)我寫(xiě)了一個(gè)自己的printf程序,當(dāng)執(zhí)行printf的時(shí)候祥款,到底執(zhí)行的是哪一個(gè)呢清笨?
實(shí)際上它的查找順序可以可以通過(guò)type -a來(lái)查看:

$ type -a printf
printf is aliased to `printf "hello\n"'
printf is a shell builtin
printf is /usr/bin/printf
printf is ./printf

這里就可以很清楚地看到查找順序了。也就是說(shuō)刃跛,如果你輸入printf抠艾,它執(zhí)行的是:

$ printf
hello

而如果刪除別名:

unalias printf

它執(zhí)行的將會(huì)是內(nèi)置命令printf。
以此類推桨昙。

5. 總結(jié)

說(shuō)到這里检号,想必標(biāo)題的問(wèn)題以及下面的問(wèn)題你都清楚了:

安裝Python或者Jdk程序?yàn)槭裁匆O(shè)置PATH環(huán)境變量?如果不設(shè)置蛙酪,該如何運(yùn)行齐苛?

除了./方式運(yùn)行自己的程序還有什么方式?

如果讓自己的程序能夠像內(nèi)置命令一樣被識(shí)別桂塞?

如何查看文件類型凹蜂?

執(zhí)行一條命令,如何確定是哪里的命令被執(zhí)行

本文涉及命令:

  • mv 移動(dòng)/重命名
  • file 查看文件信息
  • whereis 查看命令或者手冊(cè)位置
  • type 查看命令類別

原文地址:
Linux中的shell到底是什么阁危?
為什么在Linux下玛痊,如果使用ping只需輸入ping?

注意,
可執(zhí)行文件狂打,內(nèi)存中存在的本質(zhì)卿啡?執(zhí)行過(guò)程?處理輸入?yún)?shù)菱父?讀/寫(xiě)文件過(guò)程颈娜?等!U阋恕9倭伞!粟瞬!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末同仆,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子裙品,更是在濱河造成了極大的恐慌俗批,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,546評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件市怎,死亡現(xiàn)場(chǎng)離奇詭異岁忘,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)区匠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)干像,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事麻汰∷倏停” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,911評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵五鲫,是天一觀的道長(zhǎng)溺职。 經(jīng)常有香客問(wèn)我,道長(zhǎng)位喂,這世上最難降的妖魔是什么辅愿? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,737評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮忆某,結(jié)果婚禮上点待,老公的妹妹穿的比我還像新娘。我一直安慰自己弃舒,他們只是感情好癞埠,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著聋呢,像睡著了一般苗踪。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上削锰,一...
    開(kāi)封第一講書(shū)人閱讀 51,598評(píng)論 1 305
  • 那天通铲,我揣著相機(jī)與錄音,去河邊找鬼器贩。 笑死颅夺,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蛹稍。 我是一名探鬼主播吧黄,決...
    沈念sama閱讀 40,338評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼唆姐!你這毒婦竟也來(lái)了拗慨?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,249評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤奉芦,失蹤者是張志新(化名)和其女友劉穎赵抢,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體声功,經(jīng)...
    沈念sama閱讀 45,696評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡烦却,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了减噪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片短绸。...
    茶點(diǎn)故事閱讀 40,013評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖筹裕,靈堂內(nèi)的尸體忽然破棺而出醋闭,到底是詐尸還是另有隱情,我是刑警寧澤朝卒,帶...
    沈念sama閱讀 35,731評(píng)論 5 346
  • 正文 年R本政府宣布证逻,位于F島的核電站,受9級(jí)特大地震影響抗斤,放射性物質(zhì)發(fā)生泄漏囚企。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評(píng)論 3 330
  • 文/蒙蒙 一瑞眼、第九天 我趴在偏房一處隱蔽的房頂上張望龙宏。 院中可真熱鬧,春花似錦伤疙、人聲如沸银酗。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,929評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)黍特。三九已至,卻和暖如春锯蛀,著一層夾襖步出監(jiān)牢的瞬間灭衷,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,048評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工旁涤, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留翔曲,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,203評(píng)論 3 370
  • 正文 我出身青樓劈愚,卻偏偏與公主長(zhǎng)得像部默,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子造虎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容