父 shell,子 shell ,export 與 變數傳遞
在我們所執行的腳本里,我們還可以啟動新的子 shell 程序,這些子 shell 程序使指令碼並行地執行著多個子任務。一般而言,在一個腳本里執行一個外部命令(普通的可執行檔案)時,shell 會 fork 出一個子程序,然後再用 exec 來執行這個程式;但是,bash shell 的內建命令(builtin)卻不會這樣,它們是直接執行的。所以,等價的內建命令的執行速度會比執行外部命令要來的快。
在一對括號 (...) 裡可以放置一組指令,這些指令是在一個子 shell 裡執行的。在子 shell 裡的變數不能被這段子 shell 外的程式碼直接訪問,也就是說子 shell 裡的變數不能被父 shell 所存取,實際上它們是區域性變數。這裡可以參考:
下面用一段程式碼進行測試:
#!/bin/bash echo "Subshell level = $BASH_SUBSHELL" outer_variable=Outer outer_variable2=Outer2 ( echo "Subshell level INSIDE subshell = $BASH_SUBSHELL" inner_variable=Inner outer_variable2=Outer_var_changein_subshell echo "From Subshell,\"inner_variable\"=$inner_variable" echo "From parent shell,\"outer\"=$outer_variable" echo "From parent shell, \"outer\"=$outer_variable2" ) echo "In parent shell, check \"outer_variable\" value:$outer_variable" echo "In parent shell, check \"outer_variable2\" value:$outer_variable2" echo echo "Subshell level OUTSIDE subshell = $BASH_SUBSHELL" echo if [ -z "$inner_variable" ] then echo "inner_variable undefined in main body of shell" else echo "From main body of shell,\"inner_variable\"=$inner_variable" fi exit 0
執行輸出:
[email protected]:~/shell$ ./subshell.sh Subshell level = 0 Subshell level INSIDE subshell = 1 From Subshell,"inner_variable"=Inner From parent shell,"outer"=Outer From parent shell, "outer"=Outer_var_changein_subshell In parent shell, check "outer_variable" value:Outer In parent shell, check "outer_variable2" value:Outer2 Subshell level OUTSIDE subshell = 0 inner_variable undefined in main body of shell
在上面的程式碼中,BASH_SUBSHELL 是一個環境變數,它表示進入子 shell 的層級,比如處於當前 shell 時,該變數值為 0;當在當前 shell 派生的子 shell 裡時,該變數值為 1;如果該子 shell 又派生出一個子 shell,那麼該變數在此間的值就為 3,以此類推。
在程式碼中,( ) 裡的程式碼段是在子 shell 裡執行的,而 inner_variable 作為區域性變數,它的值可以在 ( ) 這段程式碼裡 echo 出來,但是一旦返回到父shell 時,它就是未定義的,所以會輸出“ inner_variable undefined in main body of shell”。也就是說,區域性變數不能被外部程式碼所訪問。
從輸出可以看到,在子 shell 中和父 shell 中變數 outer_variable 的輸出值是一樣的;相對應的 outer_variable2 變數即使在子 shell 中進行了修改,但是當返回到父 shell 對其輸出時,它卻還是父 shell 中原來所賦的值。從這裡可以看出,子 shell 可以 “感知” 父 shell 中的變數,但它不能修改它。其本質的原因和 fork() 函式的原理有關。在 UNIX/LINUX 中,fork 出來的子程序實際上是對父程序的一種拷貝,而子 shell 就是父shell fork 出來的一個子程序,所以它理所當然的有了父shell 中的一片拷貝。所以,子 shell 裡的 outer_variable 和 outer_variable2 變數雖然和父 shell 的同名,但它們並不是同一個變數,而是父 shell 裡的一個副本。
說到父shell 和 子 shell,那麼會想到 export 這個命令。export 也是 bash 的一個內建命令。它主要是用來將父 shell 裡的變數匯出供子 shell 使用。它有如下特徵:1. 用 export 匯出的變數放在“匯出變數列表”中,它可以被子 shell (子 shell 的子 shell 也是如此)拷貝並使用。2. 被 export 出來的變數雖然可以被子 shell 使用,但它也只是一個拷貝,而不會影響到父 shell 中的值以及其它子 shell 中的值。
看下面示例;
-
先在當前 shell 裡 export 一個變數:
[email protected]:~/shell$ export exp8temp="hello world" [email protected]:~/shell$ echo $exp8temp hello world
-
執行一個指令碼 echo 此變數(該指令碼只有一句話即 echo $exp8temp ):
$ ./exp8.sh hello world
由上可見,父 shell 裡 export 的變數可以被子 shell 讀取。
-
測試一下子 shell 更改此變數是否會影響父 shell 裡的值,子 shell 程式碼如下:
#!/bin/bash exp8temp="hello shell" echo $exp8temp
檢驗上面的情景:
[email protected]:~/shell$ ./exp8.sh hello shell [email protected]:~/shell$ echo $exp8temp hello world
可見子 shell 對父 shell 裡 export 出來的變數進行修改並不能影響到父 shell。這說明了,子 shell 只是在“匯出變數列表“裡對該變數進行了一個拷貝。但反過來,父shell再次更改此變數時,子 shell 再去讀時,讀到的是新值,而不是原來的值。
4. 如果在子 shell 裡 export 出的變數,父 shell 是否能讀到呢?先將下面一段程式碼放在後臺執行:
#!/bin/bash export exp9temp="hello world" sleep 30 exit 0
然後在在 30 秒內在父 shell 裡讀取一下 $exp9temp 的值,發現輸出為空。所以我們得出結論,export 出來的變數不能匯出到父程序或者是父程序的環境裡。一個自己稱可以繼承父程序的東西,而不能反過來去影響父程序。
那麼子 shell 有什麼辦法可以向父 shell 傳遞自己的變數嗎?下面方法可以考慮:
-
通過一箇中間檔案進行:
#!/bin/bash ( subvar="hello shell" echo "$subvar" > temp.txt ) read pvar < temp.txt echo $pvar 執行輸出: $ sh subandp.sh hello shell
-
通過命令替換:
#!/bin/bash pvar=`subvar="hello shell";echo $subvar` echo $pvar
- 執行輸出: ::
- $ ./subandp.shhello shell
執行命令替換符(兩個反單引號)之間的命令也是在子 shell 來完成的。
-
使用命名管道:
#!/bin/bash mkfifo -m 777 npipe ( subsend="hello world" echo "$subsend" > npipe & ) read pread < npipe echo "$pread" exit 0
執行輸出:
[email protected]:~/shell$ ./var.sh hello world
關於有名管道建立命令 mkfifo 可參考:http://www.groad.net/bbs/read.php?tid-3707.html
-
使用 here 文件:
#!/bin/bash read pvar << HERE `subvar="hello shell" echo $subvar` HERE echo $pvar
執行輸出:
$ ./subandp.sh hello shell
方法應該還有很多,這些方法的本質原理基於程序間的通訊。
轉載自:
相關推薦
父 shell,子 shell ,export 與 變數傳遞
在我們所執行的腳本里,我們還可以啟動新的子 shell 程序,這些子 shell 程序使指令碼並行地執行著多個子任務。一般而言,在一個腳本里執行一個外部命令(普通的可執行檔案)時,shell 會 fork 出一個子程序,然後再用 exec 來執行這個程式;但是,bash shell 的內建命令(builti
Linux編程 9 (shell類型,shell父子關系,子shell用法)
需要 cli 返回 root 查看 centos 7 bsh 其它 amp 一. shell類型 1.1 交互式 bin/ shell程序 當用戶登錄到某個虛擬控制臺終端或是在GUI中啟動終端仿真器時,默認的shell程序就會開始運行。系統啟動什麽樣的shel
Linux程式設計 9 (shell型別,shell父子關係,子shell用法)
一. shell型別 1.1 互動式 bin/ shell程式 當用戶登入到某個虛擬控制檯終端或是在GUI中啟動終端模擬器時,預設的shell程式就會開始執行。系統啟動什麼樣的shell程式取決於你個人的使用者ID配置,在etc/passwd檔案中。如下圖所示,root使用者使用bash she
JQuery 各節點獲取函數:父節點,子節點,兄弟節點
集合 exp pos 完全 children content 文本 內容 clas jQuery.parent(expr) //找父元素 jQuery.parents(expr) //找到所有祖先元素,不限於父元素 jQuery.chi
Vue.js如何獲得兄弟元素,子元素,父元素(DOM操作)
<button @click = “clickfun($event)”>點選</button> methods: { clickfun(e) { // e.target 是你當前點選的元素 // e.currentTarget 是你繫結事件的元素 } }, #獲得點選元素的
Vue.js 獲得兄弟元素,子元素,父元素(DOM操作)
pre lin col bsp 操作 attr current 綁定 tar e.target 是你當前點擊的元素 e.currentTarget 是你綁定事件的元素 e.currentTarget.previousEle
windows視窗分析,父視窗,子視窗,所有者視窗
https://blog.csdn.net/u010983763/article/details/53636831 在Windows應用程式中,視窗是通過控制代碼HWND來標識的,我們要對某個視窗進行操作,首先就要獲取到這個視窗的控制代碼,這就是視窗和控制代碼的聯絡。 (本文嘗試通過一些簡單
html dom父節點,子節點,兄弟節點
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head
JAVA中父類,子類,內部類
一個.java原始檔中可以有多個類(不包含內部類),但是隻有一個類是Public的,如 public class Test { public class A{//內部類 } public class B{//內部類 } // /** // * @param arg
vue父元件呼叫子元件,為子元件傳值,prop用法
1.父元件呼叫子元件 子元件children.vue程式碼如下: <template> <div>我是子元件</div> </template> 父元件parent.vue程式碼如下: <template>
Jquery找父元素,祖先,子元素,子孫,兄弟節點
jQuery.parent(expr) //找父元素 jQuery.parents(expr) //找到所有祖先元素,不限於父元素 jQuery.children(expr) //查詢所有子元素,只會找到直接的孩子節點,不會返回所有子孫 jQuery.co
js對節點的操作,新增,刪除,獲得父節點,子節點,兄弟節點
<pre name="code" class="javascript">var chils= s.childNodes; //得到s的全部子節點 var par=s.parentNod
父視窗開啟子視窗,子視窗關閉後自動重新整理父視窗
可以在任何地方插入程式碼 <script language="javascript"> window.onunload = function(){ window.opener.locat
部署AD林根域,子域,域樹
com png 一個 安裝 分享 樹根 sha 新的 oss 林,域樹,子域之間的聯系 首先無論是林根域,子域,域樹,必須要有一個靜態的ip地址,DNS必須指向林根域的ip地址。互相之間必須連通。創建時與安裝AD域步驟大多數一樣創建他們之間的區別是這樣的1、創建林根域
mysql資料庫的多表查詢,子查詢,聯合查詢
/*多表查詢*//*交叉連線*(表1條數*表2條數)*/SELECT * FROM emp JOIN dept;/*內連線(在交叉連線基礎上加條件)*/SELECT * FROM emp JOIN dept ON deptid=id;SELECT * FROM emp JOIN dept ON emp.dep
【CodeForces - 266C】Below the Diagonal (遞迴,子問題,貪心模擬)
題幹: You are given a square matrix consisting of n rows and n columns. We assume that the rows are numbered from 1 to
mysql連線查詢,子查詢,聯合查詢
一、連線查詢(多表查詢) emp表 dept表 1.交叉連線 實際上,交叉連線是將兩個表不設定任何條件的連線結果。 交叉連線通常也被叫做“笛卡爾積”——數學上可能比較多。 語法: from 表1 [cross] join 表2
mysql連接查詢,子查詢,聯合查詢
mysql 應該 等於 outer 重復項 左連接 卡爾 nio round 一、連接查詢(多表查詢) emp表 dept表 1.交叉連接 實際上,交叉連接是將兩個表不設定任何條件的連接結果。 交叉連接通常也被叫做“笛卡爾積”——數學上可能比較多。 語法: from
降取樣,過取樣,欠取樣,子取樣,下采樣,上取樣,你學會了嗎?【總結】
降取樣:2048HZ對訊號來說是過取樣了,事實上只要訊號不混疊就好(滿足尼奎斯特取樣定理),所以可以對過取樣的訊號作抽取,即是所謂的“降取樣”。在現場中取樣往往受具體條件的限止,或者不存在300HZ的取樣率,或除錯非常困難等等。若R>>1,則Rfs/2就遠大於音
c# XML讀取建立修改節點,子節點,和值
在c#端使用XML。 //建立 public void CreateXmlFile() { XmlDocument xmlDoc = new XmlDocument(); //建立型別宣告節點 XmlNode