shell相關知識1

2022-04-11 07:21:40 字數 3580 閱讀 3547

**

組命令,就是將多個命令劃分為一組,或者看成乙個整體。

用法區別

shell 組命令的寫法有兩種:

(command1; command2;. . . )

由花括號{}包圍起來的組命名在當前 shell 程序中執行,而由小括號()包圍起來的組命令會建立乙個子 shell,所有命令都在子 shell中執行。

使用花括號{}時,花括號與命令之間必須要有乙個空格,並且最後乙個命令必須用乙個分號或乙個換行符結束

組命令可以將多條命令的輸出結果合併在一起,在使用重定向和管道時會特別方便。

兩種寫法的重要不同:{}包圍的組命令在當前 shell 程序中執行,由()包圍的組命令會建立乙個子shell,所有命令都會在這個子 shell 中執行

在子 shell 中執行意味著,執行環境被複製給了乙個新的 shell 程序,當這個子 shell 退出時,新的程序也會被銷毀,環境副本也會消失,所以在子 shell 環境中的任何更改都會消失(包括給變數賦值)。因此,在大多數情況下,除非指令碼要求乙個子 shell,否則使用{}比使用()更受歡迎,並且{}的進行速度更快,占用的記憶體更少

舉栗將多條命令的輸出重定向到out.txt檔案

1.普通模式

ls -l > out.txt #>表示覆蓋

echo "test432" >> out.txt #>>表示追加

cat test.txt >> out.txt

2.使用組命令

>out.txt

(ls -l ;echo "test432";cat test.txt)>out.txt

組命令與管道結合

(ls -l ;echo "test432";cat ../test.txt)|wc -l

2.1 什麼是子程序

子程序的概念是由父程序的概念引申而來的。在 linux 系統中,系統執行的應用程式幾乎都是從 init(pid為 1 的程序)程序派生而來的,所有這些應用程式都可以視為 init 程序的子程序,而 init 則為它們的父程序。

shell 指令碼是從上至下、從左至右依次執行的,即執行完乙個命令之後再執行下乙個。如果在 shell 指令碼中遇到子指令碼(即指令碼巢狀,但是必須以新程序的方式執行)或者外部命令,就會向系統核心申請建立乙個新的程序,以便在該程序中執行子指令碼或者外部命令,這個新的程序就是子程序。子程序執行完畢後才能回到父程序,才能繼續執行父指令碼中後續的命令及語句。

使用pstree -p命令就可以看到 init 及系統中其他程序的程序樹資訊(包括 pid):

systemd(1)─┬─modemmanager(796)─┬─(821)

│ └─(882)

├─networkmanager(975)─┬─(1061)

│ └─(1077)

├─abrt-watch-log(774)

├─abrt-watch-log(776)

├─abrtd(773)

├─accounts-daemon(806)─┬─(839)

│ └─(883)

├─alsactl(768)

├─at-spi-bus-laun(1954)─┬─dbus-daemon(1958)───(1960)

│ ├─(1955)

│ ├─(1957)

│ └─(1959)

├─at-spi2-registr(1962)───(1965)

├─atd(842)

├─auditd(739)─┬─audispd(753)─┬─sedispatch(757)

│ │ └─(759)

│ └─(752)

2.2 建立子程序

建立子程序的方式

說明使用 fork() 函式建立乙個子程序相當於對父程序進行了轉殖,除了 pid(程序id)等極少的引數不同外,子程序的一切都來自父程序,包括**、資料、堆疊、開啟的檔案等,就連**的執行位置(狀態)都是一樣的。

但是,後期隨著各自的發展軌跡不同,兩者會變得不一樣,但是在 fork() 出來的那一刻,兩者都是一樣的。

組命令、命令替換、管道

舉栗:在 ~/bin 目錄下有兩個可執行檔案分別叫 a.out 和 b.out。現在執行 a.out,就會產生乙個程序,比如叫做 a。在程序 a 中我又呼叫 fork() 函式建立了乙個程序 b,那麼 b 就是 a 的子程序,此時它們是一模一樣的。但是,我呼叫 fork() 後立即又呼叫 exec() 去載入 b.out,這可就壞事了,b 程序中的一切(包括**、資料、堆疊等)都會被銷毀,然後再根據 b.out 重建建立一切。這樣一折騰,b 程序除了 id 沒有變,其它的都變了,再也沒有屬於 a 的東西了。

以新程序的方式執行指令碼檔案,比如bash ./test.sh;chmod +x ./test.sh; ./test.sh

在當前 shell 中使用 bash 命令啟動新的 shell

2.3 子程序總結

子 shell 雖然能使用父 shell 的的一切,但是如果子 shell 對資料做了修改,比如修改了全域性變數,這種修改也只能停留在子 shell,無法傳遞給父 shell。不管是子程序還是子 shell,都是「傳子不傳父」。

子 shell 才是真正繼承了父程序的一切,這才像「乙個模子刻出來的」;普通子程序和父程序是完全不同的兩個程式,只是維持著父子關係而已。

echo $$輸出當前程序id,echo $ppid輸出父shell id

命令結果

結論輸出當前程序與父程序id

echo $$;echo $ppid

子程序形式輸出程序id

子程序bash

echo $$;echo $ppid

exit

在普通的子程序中,$ 被展開為子程序的 id

組命令形式輸出程序id

子shell

(echo $$;echo $ppid)

子shell和父shell中的id是一樣的

這是因為$ 變數在子 shell 中無效!base 官方文件說,在普通的子程序中,$ 確實被展開為子程序的 id;但是在子 shell 中,$ 卻被展開成父程序的 id

管道形式輸出程序id

子shell

echo "test" |

程序替換形式輸出程序id

read < <(echo $$ $ppid)

$ echo $reply

34451 34450

shell變數相關知識

一 幾個常用命令 1.set 輸出所有變數,包含全域性變數和區域性變數 2.env 只顯示全域性變數 3.declare 輸出所有的變數,函式,整數和已經匯出的變數 4.unset 消除本地變數和環境變數 5.source etc profile 載入環境變數,使環境變數生效 二 普通變數定義賦值有...

陣列相關知識1

一.陣列建立的方式 1.new array arg arg可以為想要建立陣列的長度也可以是具體的值。也可以直接省略new關 鍵字2.字面量表示法 var a 1 2 3 二.陣列長度 var arr new array first second three 這是陣列的長度ar.length 3,但是...

Oracle相關知識(1)

系統使用者登入 系統自帶的使用者 sys,system,scott 格式 sqlplus username password servicename as sysdba 示例 sqlplus system a123456 orcl as sysdba as sysdba 表示用管理員賬戶登入 注意 ...