sourceshell腳本
① 用sh、./、source執行Shell腳本到底有何不同
要解答這個看似簡單的問題,需要先復習一下linux系統里「命令」這個詞的含義。
Linux系統中的命令有兩種:一是內置冊沒命令,是Shell與生俱來的一部分,比如最基礎的 cd 、 echo 、 kill 等;二是外部命令,包含已編譯的實用程序以及Shell腳本兩種,它們兩者又可以統稱為可執行文件(executables)。我們平時常用的大多數看起來像「內置(自帶)命令」的命令,其實都是/usr/bin及其他目錄下的已編譯程序,如 ls 、 ps 、 grep 等。
可見,外部命令的實體並不存在於Shell中,而是在調用時才從對應的位置載入。如果用戶調用命令時沒有提供路徑的話,Shell通過PATH環境變數來定位外部命令的路徑。
如果在PATH給定的路徑仍然找不到命令,Shell就會返回"command not found"。這也就解釋了為什麼在Linux下安裝完JDK之後,總是要將$JAVA_HOME/bin寫入PATH——用戶肯定不想每次調用JDK提供的命令時都要先cd到JDK的安裝路徑,或者把路徑寫得清清楚楚。
按照上文所述,我們平時自己寫的Shell腳本也是外部命令。下面在/tmp/test目錄下直接創建一個文件: touch my_script.sh ,並在其中寫幾句簡單的話。
然後以不同的方式執行這個腳本。
這段示例的信息量蠻大的,下面以Q&A的形式逐個解決問題。
並沒有,只是表示相對路徑(即當前目錄)而已, ./my_script.sh 即在當前目錄/tmp/test執行my_script.sh腳本。用絕對路徑和用相對路徑執行腳本是等價的,因此可以乾脆將它們打包統稱為「./方式」,以與「sh方式」區分開來。
在./方式下,當前Shell進程會使用fork系統調用產生一個子Shell進程,並使用execve系統調用讓OS在子Shell進程中執行腳本。execve系統調用必然會檢查腳本文件的許可權,而新touch出來的文件許可權是 -rw-r--r-- ,並沒有可執行(x)許可權,所以會報Permission denied。如果把許可權改正,那麼它的執行結果與sh方式是相同的。
sh方式的不同點在於,OS會通過 sh 命令的調用直接產生一個新的Shell進程,並將 my_script.sh 當作命令行參數傳進去。新的Shell進程就會讀取、解釋並執行該腳本,而OS不關心該文件到底是什麼,自然也就不要求可執行許可權,只要求讀許可權就可以了。
Linux與Windows不同,如果用戶不指定路徑,那麼就會直接跳過對當前路徑的檢查,直接按照PATH來查找。而PATH里自然是沒有當前路徑的,command not found就順理成章了。也就是說,加 ./ 是為了告訴Shell:「我已經確定我要執行的東西在當前路徑了」。
看官可能會問,乾脆在PATH里直接加上當前路徑(即 . ),不就可以免去打 ./ 的麻煩了嗎?Linux非常不推薦這樣做,安全風險極大。舉個極端的例子:一個普通用戶在自己的家目錄新建了一個名為ls的腳本,但裡面的內容是 rm -rf /* 。然後root用戶來到該用戶的家目錄,並執行ls命令,如果PATH里有當前路徑的話,結果可想而知。
source是Shell(准確地說是Bash)的內置命令,在Bourne Shell中的等價命令是一個點 . ,即點命令州帶納。用source命令執行腳本文件時,是在當前Shell進程中執行,而不是像./與sh方式一樣在新的Shell進程中執行,因此早先設置的變數在腳本里是可以讀取到的。
source一般不用來執行業務腳本,最常見用途是在某些初始化腳本修改之後使其立即生效,即 source /etc/profile 這樣。
shebang是指腳本文件中以字元 #! 開頭的第一行,它用來指定這個腳行滑本該用哪種解釋器來解釋。上文中出現的 #!/bin/sh 就表示應該使用sh(在這里就是Bash)來解釋它。
需要注意,只有./方式執行腳本才會讀取shebang並調用指定的解釋器,而「sh方式」(sh當然可以換成任意其他的解釋器)會忽略shebang。舉個例子,新建一個python腳本,但是shebang仍然故意錯寫:
如果執行 ./my_script.py 的話,會報語法錯誤,因為Bash不能解釋Python;執行 python my_script.py 是正常的,因為會直接用Python解釋器。若把shebang改回正確的 #!/usr/bin/python ,那麼兩種方式都能正常執行。
實際上,shebang甚至可以寫成任意外部命令(當然不推薦這樣做)。舉個有趣的栗子,創建腳本rm_self.sh:
執行 sh rm_self.sh ,會輸出"I am still here!",並且rm_self.sh文件本身還在。但若是執行 ./rm_self.sh ,則沒有任何輸出,並且rm_self.sh文件本身消失了。
② shell腳本執行source報錯
在Ubuntu 16.04機器在執行shell腳本時,報source: not found
原因是shell腳本執培困行的時候配稿念用的不是bash,而是dash,可以使用下面方法修改。
出現對話框後,選擇no,再查看一次
重新執行腳本敬塌,問題解決
③ linux下的Source命令的基本功能
source命令用法:source FileName
作用:在當前bash環境下讀取並執行FileName中的命令。
註:該命令通常用命令".」來替代。
使用範例:
1、source filename
2、. filename#(中間有空格)
source命令(從 C Shell 而來)是bash shell的內置命令。點命令,就是個點符號,(從Bourne Shell而來)是source的另一名稱。
同樣的,當前腳本中配置的變數也將作為腳本的環境,source(或點)命令通常用於重新執行剛修改的初始化文檔,如 .bash_profile 和 .profile 等等。
例如,假如在登錄後對 .bash_profile 中的 EDITER 和 TERM 變數做了修改,則能夠用source命令重新執行 .bash_profile 中的命令而不用注銷並重新登錄。
比如在一個腳本里export $KKK=111,假如用./a.sh執行該腳本,執行完畢後,運行echo $KKK,發現沒有值,假如用source來執行 ,然後再echo,就會發現KKK=111。
因為調用./a.sh來執行shell是在一個子shell里運行的,所以執行後,結構並沒有反應到父shell里,但是source不同他就是在本shell中執行的,所以能夠看到結果。
source命令(從 C Shell 而來)是bash shell的內置命令。點命令,就是一個點符號,(從Bourne Shell而來)是source的另一名稱。
這兩個命令都以一個腳本為參數,該腳本將作為當前shell的環境執行,即不會啟動一個新的子進程。所有在腳本中設置的變數將成為當前Shell的一部分。
文件建立好之後,以後每次編譯核心,只需要在/usr/src/linux-2.4.20下輸入source make_command就行了。這個文件也完全可以做成腳本,只需稍加改動即可。
shell編程中的命令有時和C語言是一樣的。&&表示與,||表示或。把兩個命令用&&聯接起來,如make mrproper && make menuconfig,表示要第一個命令執行成功才能執行第二個命令。
對執行順序有要求的命令能保證一旦有錯誤發生,下面的命令不會盲目地繼續執行。
④ SHELL腳本運行的幾種方法以及區別
給腳本加上執行許可權chmod
u+x
a.sh,
而後就可以直接用全路徑來執行腳本了,比如當前文件夾下用./a.sh,如果如果腳本所在目錄在path環境變數之中,
則直接用a.sh即可(這和運行我們自己編寫的程序是一個道理)sh/bash
./a.sh
這種情況不需要腳本具有執行許可權以上兩種執行方式都是在子shell中執行的,也就是說當前shell需要啟動另外一個shell,用來執行a.sh內的命令source
./a.sh
.
./a.sh(注意前面的
.
)以上兩種執行方式是在當前shell下執行,並不需要建立子shellsource和
.
命令的作用:用來執行一個腳本
前兩種方式和後兩種方式的另外區別:如果你在一個腳本里export
$kkk=111
,如果你用./a.sh執行該腳本,執行完畢後,你運行
echo
$kkk
,發現沒有值,如果你用source來執行
,然後再echo
,就會發現kkk=111。因為調用./a.sh來執行shell是在一個子shell里運行的,所以執行後,結構並沒有反應到父shell里,但是
source不同它就是在本shell中執行的,所以可以看到結果。
⑤ Linux中source命令的使用方式
source 命令 是一個內置的 shell 命令 ,用於從當前shell會話中的文件讀取和執行命令。source命令通常用於保留、更改當前shell中的環境變數。簡而言之,source一個 腳本 ,將會在當前shell中運行execute命令。
source命令可用於:
刷新當前的shell環境
在當前環境使用source執行Shell 腳本
從腳本中導入環境中一個Shell函數
從另一個Shell腳本中讀取變數
source命令的語法
source命令它需要一個文件,如果提供了參數,那麼將用作傳遞腳本的位置參數。
source FILENAME [ARGUMENTS]
也可以使用.替代source命令:
. FILENAME [ARGUMENTS]
如何使用source命令
1. 刷新當前的shell環境
可以在當前的shell環境中定義一個別名。為ls -al定義一個別名為ll:
[root@localhost ~]# echo "alias ll='ls -al'" >> ~/.bashrc
在~/.bashrc文件中定義完別名,可以使用source命令刷新當前shell環境:
[root@localhost ~]# source ~/.bashrc
現在可以使用ll別名列出當前目錄里所有文件了,包括隱藏文件。
2. 在當前環境使用source執行Shell腳本
Shell腳本不知道螞首你在當前Shell環境中定義的變數。source命令可用於在當前會話中執行你的Shell腳本。
下面在定義一個變數:
[root@localhost ~]# website=https://www. linux probe.com
創建一個腳本:
[root@localhost ~]# vim web.sh
#!/bin/bash
echo $website
使用source在當前shell會話中執悶仿數行它:
[root@localhost ~]# source web.shhttps://www.linuxprobe.com
當使用sh運行腳本時,找不到環境中定義的變數:
3. 從腳本中導入環境中一個Shell函數
首先創建一個腳本,定義一個函數:
[root@localhost ~]# vim func.sh
#!/bin/bash
foo(){
echo "test function!"
}
要在當前的shell會話中導入上述腳本的功能,使用下面命令:
[root@localhost ~]# source func.sh
下面在終端中執行以下func.sh腳本中的foo函數試試:
[root@localhost ~]# foo
test function!
source完腳本之後,可以看到在當前回話的終端中可以執行腳本裡面的函數。
4. 從另一個Shell腳本中讀取變數
首先創建帶有一些變數的shell腳本,請輸入:
[root@localhost ~]# vim var.sh
#!/bin/bash
a=1
b=2
c=3
再創大歲建一個腳本,該腳本讀取上一個腳本var.sh中的變數:
[root@localhost ~]# vim read.sh
#!/bin/bash
source ~/var.sh
echo $a
echo $b
echo $c
在腳本中首先使用source將var.sh中的變數到處到當前回話,然後echo顯示變數值。下面執行read.sh看一下:
5. 讀取並執行命令
source命令可以從文件讀取和執行命令。下面的一個文本文件中帶有兩個命令,使用source命令運行該文件,看看是否會執行裡面的命令。
下面創建一個文件cmd.txt,保存兩個命令:
[root@localhost ~]# cat cmd.txt
ip ad
date
下面使用source執行這個文件:
[root@localhost ~]# source cmd.txt
總結
source命令在當前shell中執行腳本,而exec命令在新的shell中運行。
⑥ python 以source方式調用shell腳本,發現參數沒有正確傳入. 命令行下則沒有問題
[willie@localhost pys]$ python a.py
this is a test shell with arguments
arg1 = a; arg2 = b;
以上是運行結果,感覺沒什麼問題啊
⑦ shell命令中用source 和sh(或者bash)執行腳本的區別,以及export的作用
用戶登錄到Linux系統後,系統將啟動一個用戶shell,我們暫且稱這個shell為shell父。在這個shell父中,可以使用shell命令或聲明變數,也可以創建並運行shell腳本程序。
當使用sh或者bash運行shell腳本程序時,系統將創建一個子shell,我們暫且稱為shell子。此時,系統中將有兩個shell,一個是登錄時系統啟動的shell父,另一個是系統為運行腳本程序創建的shell子。
當一個腳本程序運行完畢,腳本shell子將終止,返回到執行該腳本之前的shell父。這時腳本中創建的變數或者環境變數(export的變數)是在shell子中創建的,只在shell子中有效,在shell父中是無法訪問的source(或者.)的作用是文件包含,當使用source運行腳本程序時,系統並不會創建子shell,而是將腳本中的命令放到shell父中運行,這時腳本中創建的變數或者環境變數(export的變數)相當於是在shell父中創建的,在shell父中是可以訪問的。
因此使用source執行修改後的配置文件會直接生效,不需要重啟export 的作用是為當前shell設置環境變數,這樣變數在其子shell也可以訪問,當然,在其父shell中還是無法訪問的普通的變數只在當前shell中可以訪問,在父shell或者子shell中都無法訪問。
export 也是 bash 的一個內置命令。它主要是用來將父 shell 里的變數導出供子 shell 使用。
它有如下特徵:
⑧ 如何在shell腳本中修改添加替換指定文件中的內容
1、可以藉助.shell命令執行另一個腳本文件或者用變數保存。比如a.sh和b.sh,a.sh中調用b.sh的代碼,一起輸出"hello world"的字元串。b.sh的代碼如下echo " world!"。
⑨ 如何獲得sh或source執行的shell腳本位置
1) 支持從其他目錄執行,如 source xxx/yyy/test.sh
1) 支持 sh 和 source 執行
2) 支持路徑中有空格
3) 支持 zsh 跟 bash
#!/bin/sh
if [ "$0" = "bash" ]; then
cd "$(dirname "$BASH_SOURCE")"
CUR_FILE=$(pwd)/$(basename "$BASH_SOURCE")
CUR_DIR=$(dirname "$CUR_FILE")
cd - > /dev/null
else
echo "$0" | grep -q "$PWD"
if [ $? -eq 0 ]; then
CUR_FILE=$0
else
CUR_FILE=$(pwd)/$0
fi
CUR_DIR=$(dirname "$CUR_FILE")
fi
echo $CUR_DIR
⑩ 執行shell腳本三種方法的區別:(sh、exec、source)
使用$ sh script.sh執行腳本時,當前shell是父進程,生成一個子shell進程,在子shell中執行腳本。腳本執行完畢,退出子shell,回到當前shell。
./script.sh與 sh script.sh等效。
使用$ source script.sh方式,在當前上下文中執行腳本,不會生成新的進程。腳本執行完畢,回到當前shell。
source方式也叫點命令。
. script.sh與 source script.sh等效。
使用exec command方式,會用command進程替換當前shell進程,並且保持PID不變。執行完畢,直接退出,不回到之前的shell環境。
二、測試驗證
vi loop.sh
顯示當前進程
sh的方式:執行loop.sh列印執行進程
source方式:執行loop.sh列印執行進程
exec方式:執行loop.sh列印執行進程
按下ctrl+C
sh方式:父進程是6770,執行loop.sh時的子進程是13736。執行完畢後回到父進程shell。
source方式:父進程和子進程都是6770(執行時沒有新的進程),執行完畢會回到父進程shell。
exec方式:進程PID沒有改變都是6770,執行完畢(ctrl+C強制關閉)時直接退出了shell。腳本執行時替換了父進程的shell,執行完畢後直接退出,沒有回到之前的shell。