Linux內建命令

1.如何確定內建命令:type

不要試圖用腦子記住所有的命令,這不可能也不需要。判斷一個命令是不是內建命令只需要藉助於命令type即可,如下所示:

# cd命令是內建命令
[root@banana ~]# type cd
cd is a shell builtin

# ifconfig命令不是內建命令,而是一個外部文件
[root@banana ~]# type ifconfig
ifconfig is /usr/sbin/ifconfig

2.執行程序:“.”(點號)

點號用於執行某個腳本甚至腳本沒有可執行權限也可以運行。有時候在測試運行某個腳本時可能並不想爲此修改腳本權限,這時候就可以使用 “.” 來運行腳本。如果沒有運行權限的話,用“./”執行就會有報錯但是若在其前面使用點號來執行就不會報錯,如下所示:

# 新建HelloWorld.sh,並添加代碼
[root@banana ~]# vim HelloWorld.sh
echo "HelloWorld"

# 如果腳本沒有可執行權限,則會報權限錯誤
[root@banana ~]# ./HelloWorld.sh
-bash: ./HelloWorld.sh: Permission denied

# 使用點號執行沒有加執行權限的腳本可以正常運行
[root@banana ~]# . ./HelloWorld.sh
HelloWorld!

與點號類似,source命令也可讀取並在當前環境中執行腳本,同時還可返回腳本中最後一個命令的返回狀態;如果沒有返回值則返回0,代表執行成功;如果未找到指定的腳本則返回false

[root@banana ~]# source HelloWorld.sh 
HelloWorld!

3.別名:aliasalias

可用於創建命令的別名,若直接輸入該命令且不帶任何參數,則列出當前用戶使用了別名的命令。現在你應該能理解類似ll這樣的命令爲什麼與ls-l的效果是一樣的吧。

[root@banana ~]# alias
alias cp='cp -i'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l.='ls -d .* --color=auto'
alias ll='ls -l --color=auto'
alias ls='ls --color=auto'
alias mv='mv -i'
alias rm='rm -i'
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'

使用alias可以自定義別名,比如說一般的關機命令是shutdown-h now,寫起來比較長,這時可以重新定義一個關機命令,以後就方便多了。使用**alias定義的別名命令也是支持Tab鍵補全**的,如下所示:

[root@banana ~]# alias myShutdown='shutdown -h now'

注意,這樣定義alias只能在當前Shell環境中有效,換句話說,重新登錄後這個別名就消失了。爲了確保永遠生效,可以將該條目寫到用戶家目錄中的.bashrc文件中,如下所示:

[root@banana ~]# cat .bashrc 
# .bashrc

# User specific aliases and functions

alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'

# 自定義關機命令的別名
myShutdown='shutdown -h now'

# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi

4.刪除別名:unalias

該命令用於刪除當前Shell環境中的別名。有兩種使用方法:

  • 第一種用法:unalias 命令
  • 第二種用法:unalias -a 命令,刪除當前Shell環境中所有的別名

同樣,這兩種方法都是在當前Shell環境中生效的。

# 刪除ll別名
[root@banana ~]# unalias ll

# 刪除成功,發現.bashrc的ll別名被刪除了。
[root@banana ~]# ll
-bash: ll: command not found

# 恢復ll
[root@banana ~]# alias ll='ls -l --color=auto'

5.任務前後臺切換:bg、fg、jobs

該命令用於將任務放置後臺運行,一般會與Ctrl+z、fg、&符號聯合使用。典型的使用場景是運行比較耗時的任務。比如打包某個佔用較大空間的目錄,若在前臺執行,在任務完成前將會一直佔用當前的終端,而導致無法執行其他任務,此時就應該將這類任務放置後臺。

# 運行打包任務,並使用Ctrl+z組合鍵暫停前臺任務
[root@banana ~]# tar -zcvf Python3.7.5-2.tgz Python-3.7.5
^Z
[1]+  Stopped                 tar -zcf Python3.7.5-2.tgz Python-3.7.5

# 查看任務狀態
[root@banana ~]# jobs
[1]+  Stopped                 tar -zcf Python-3.7.5-2.tgz Python-3.7.5

# 繼續運行後臺任務tar,運行完之後Ctrl+c退出bg
[root@banana ~]# bg 1
^C
[1]+  Done                    tar -zcf Python-3.7.5-2.tgz Python-3.7.5

# 使用fg把後臺任務調至前臺運行
[root@banana ~]# fg 1

# 如果預知某個任務耗時很久,可以一開始就將命令放入後臺運行

[root@banana ~]# tar -zcf Python-3.7.5-2.tgz Python-3.7.5 &
[1] 2215

注意:如果tar命令加了-v參數產生輸出,即使後臺運行輸出也會在打印到前臺。此時我們可以使用 > 重定向輸出到output文件

[root@banana ~]# tar -vzcf Python-3.7.5-2.tgz Python-3.7.5 > output &
[2] 2223

延伸: 一般我們希望斷開遠程連接時,任務在後臺繼續執行,比如Web服務之類的任務。此時我們可以使用nohup 命令 &注意,nohup不是內建命令。

[root@banana ~]# nohup tar -zcf Python-3.7.5-2.tgz Python-3.7.5 &

6.改變目錄:cd

改變當前工作目錄。如果不加參數,默認會進入當前用戶的家目錄。

7.聲明變量:declare、typeset

這兩個命令都是用來聲明變量的,作用完全相同。很多語法嚴謹的語言(比如C語言)對變量的聲明都是有嚴格要求的:變量的使用原則是必須在使用前聲明、聲明時必須說明變量類型,而Shell腳本中對變量聲明的要求並不高,因爲Shell弱化了變量的類概念,所以Shell又被稱爲弱類型編程語言,聲明變量時並不需要指明類型。不過,若使用declare命令,可以用-i參數聲明整型變量,如下所示:

# 聲明整型變量
[root@banana ~]# i_num01=1
# 聲明浮點型變量
[root@banana ~]# f_num01=3.14
# 聲明字符串變量
[root@banana ~]# str01="HelloWorld"
# 使用declare聲明整型變量
[root@banana ~]# declare -i i_num02=1

使用-r聲明變量爲只讀,如下所示:

# -r聲明只讀變量
[root@banana ~]# declare -r read_only=100
# 試圖修改變量值,報錯
[root@banana ~]# read_only=200
-bash: read_only: readonly variable

使用-a聲明數組變量,如下所示:

[root@banana ~]# declare -a arr='([0]="a" [1]="b" [2]="c")'
[root@banana ~]# echo ${arr[0]}
a
[root@banana ~]# echo ${arr[1]}
b
[root@banana ~]# echo ${arr[2]}
c

使用-F、-f顯示腳本中定義的函數和函數體,如下所示:

# 創建腳本fun.sh,內容如下
[root@banana ~]# cat fun.sh 
#!/bin/bash
func_1()
{
	echo "Function 1"
}
func_2()
{
	echo "Function 2"
}
echo "declare -F:"
declare -F

echo "declare -f:"
declare -f

# 運行該腳本輸出效果如下
[root@banana ~]# bash fun.sh 
declare -F:
declare -f func_1
declare -f func_2
declare -f:
func_1 () 
{ 
    echo "Function 1"
}
func_2 () 
{ 
    echo "Function 2"
}

8.打印字符:echo

echo用於打印字符,典型用法是使用echo命令並跟上使用雙引號括起的內容(即需要打印的內容),該命令會打印出引號中的內容,並在最後默認加上換行符。使用-n參數可以不打印換行符

# 自動換行
[root@banana ~]# echo "HelloWorld"
HelloWorld

# -n參數取消換行
[root@banana ~]# echo -n "HelloWorld"
HelloWorld[root@banana ~]# 

默認情況下,echo命令會隱藏-e參數(禁止解釋打印反斜槓轉義的字符)。比如“\n”代表新的一行,如果嘗試使用echo輸出新的一行,在不加參數的情況下只會將“\n”當作普通的字符若要打印轉義字符,則需要通過使用-e參數來允許

# echo默認禁止打印反斜槓轉義的字符
[root@banana ~]# echo "\n"
\n		# "\n"被當做普通的字符

# 若要打印轉義字符,則需要通過使用-e參數來允許
# 輸出有兩行,第一行是輸出的新行,第二行的默認的換行符
[root@banana ~]# echo -e "\n"


[root@banana ~]# 

9.跳出循環:break

從一個循環(for、while、until或者select)中退出。break後可以跟一個數字n,代表跳出n層循環,n必須大於1,如果n比當前循環層數還要大,則跳出所有循環。 下面的腳本演示了使用break和break 2的區別(運行前請將對應的註釋符去掉)。


[root@banana ~]# cat break_01.sh 
#!/bin/bash
for I in A B C D
do
	# echo輸出I
	echo -n "$I:"
	# J in range(10)
	for J in `seq 10`
		do
			# 如果 J == 5,退出一層循環
			if [ $J -eq 5 ]; then
				break
				# break 2
			fi
			# echo輸出J
			echo -n " $J"
		done
	# echo默認會輸出"\n"
	echo
done
echo

# 當J值爲5時,break的輸出結果(外層運行了4次)
[root@banana ~]# bash break_01.sh 
A: 1 2 3 4
B: 1 2 3 4
C: 1 2 3 4
D: 1 2 3 4

# 當J值爲5時,break 2的輸出結果(外層僅運行了1次)
[root@banana ~]# bash break_01.sh 
A: 1 2 3 4

10.循環控制:continue

停止當前循環,並執行外層循環(for、while、until或者select)的下一次循環。continue後可以跟上一個數字n,代表跳至外部第n層循環。n必須大於1,如果n比當前循環層數還要大,將跳至最外層的循環。 下面的腳本演示了使用continue和continue 2的區別(運行前請將對應的註釋符去掉)。

# 創建演示腳本continue
[root@banana ~]# cat continue_01.sh 
#!/bin/bash
# [A,B,C,D]
for I in A B C D
do
	# echo輸出I
	echo -n "$I:"
	# J從1,10
	for J in {1..10}
		do
			# 如果J == 5,退出循環
			if [ $J -eq 5 ]; then
				continue
				# continue 2
			fi
			# echo輸出J
			echo -n " $J"
		done
	# echo換行
	echo
done
# echo換行
echo

# 判斷J值爲5時,continue的輸出結果
[root@banana ~]# bash continue_01.sh 
A: 1 2 3 4 6 7 8 9 10
B: 1 2 3 4 6 7 8 9 10
C: 1 2 3 4 6 7 8 9 10
D: 1 2 3 4 6 7 8 9 10

# 判斷J值爲5時,continue 2的輸出結果
[root@banana ~]# bash continue_01.sh 
A: 1 2 3 4B: 1 2 3 4C: 1 2 3 4D: 1 2 3 4

11.將所跟的參數作爲Shell的輸入,並執行產生的命令:eval

# eval用法例一:將字符串解析成命令執行
# 定義cmd爲一個字符串,該字符串爲"ls -l /etc/passwd"
[root@banana ~]# cmd="ls -l /etc/passwd"

# 使用eval,會將之前的字符串解析爲命令並執行
[root@banana ~]# eval $cmd
-rw-r--r-- 1 root root 1171 Jun 10 22:11 /etc/passwd


# eval用法例二:程序運行中根據某個變量確定實際的變量名
[root@banana ~]# name1=john		# 定義變量name1
[root@banana ~]# name2=wang		# 定義變量name2
[root@banana ~]# num=1			# 使用該變量確定真實的變量名name$num
[root@banana ~]# eval echo "$"name$num
john	


# eval用法例三:將某個變量的值當做另一個變量名並給其賦值
[root@banana ~]# name1=john
[root@banana ~]# name2=wang
[root@banana ~]# eval $name1="$name2"
[root@banana ~]# echo $john
wang

12.執行命令來取代當前的Shell:exec

內建命令exec並不啓動新的Shell,而是用要被執行的命令替換當前的Shell進程,並且將老進程的環境清理掉,而且exec命令後的其他命令將不再執行。 假設在一個Shell裏面執行了exec echo '‘Hello’'命令,在正常地輸出一個“Hello”後Shell會退出,因爲這個Shell進程已被替換爲僅僅執行echo命令的一個進程,執行結束自然也就退出了。如圖11-5所示,命令執行完成後,連接狀態是一個紅色的斷開符。
在這裏插入圖片描述
想要避免出現這種情況,一般將exec命令放到一個Shell腳本里面,由主腳本調用這個腳本,主腳本在調用子腳本執行時,當執行到exec後,該子腳本進程就被替換成相應的exec的命令。注意source命令或者點號,不會爲腳本新建Shell,而只是將腳本包含的命令在當前Shell執行。exec典型的用法是與find聯合使用,用find找出符合匹配的文件,然後交給exec處理,如下所示:

# 列出系統中所有以.conf結尾的文件
[root@banana ~]# find / -name "*.conf" -exec ls -l {} \;
# 刪除系統中所有的.tmp臨時文件
[root@banana ~]# find / -name "*.tmp" -exec rm -f {} \;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章