一些基礎腳本知識
阿新 • • 發佈:2018-09-21
inode not found 引號 each 序列 不能 pid res website
編程基礎:
程序:指令+數據
程序編程風格:
過程式:以指令為中心,數據服務於指令。 小軟件過程,大軟件對象。
對象式:以數據為中心,指令服務於數據
shell程序:提供了編程能力,解釋執行
shell腳本基礎:
shell腳本:
包含一些命令或聲明,並符合一定格式的文本文件
格式要求:首行shebang機制
#!/bin/bash
#!/usr/bin/python
#!/usr/bin/perl
shell腳本的用途有:
自動化常用命令
執行系統化管理和故障排除
創建簡單的應用程序
處理文本或文件
創建shell腳本 第一步:使用文本編輯器來創建文本文件 第一行必須包括shell聲明序列:#! #!/bin/bash 添加註釋 註釋以#開頭 第二步:運行腳本 給予執行權限,在命令行上指定腳本的絕對或相對路徑 直接運行解釋器,將腳本作為解釋器程序的參數運行 腳本規範: 腳本代碼開頭約定: 1、第一行一般為調用使用的語言 2、程序名,避免更改文件名為無法找到正確的文件 3、版本號 4、更改後的時間 5、作者相關信息 6、該程序的作用,及註意事項 7、最後是各版本的更新簡要說明 腳本的基本結構: 腳本的基本結構 #!SHEBANG CONFIGURATON_VARIABLES FUNCTION_DEFINITIONS MAIN_CODE shell腳本示例 #!/bin/bash # ------------------------------------------ # Filename: hello.sh # Revision: 1.1 # Date: 2017/06/01 # Author: wang # Email: [email protected] # Website: www.magedu.com # Description: This is the first script # ------------------------------------------ # Copyright: 2017 wang # License: GPL echo “hello world”
腳本調試
檢測腳本中的語法錯誤
bash -n /path/to/some_script
調試執行
bash -x /path/to/some_script
bash -n 只能檢查語法錯誤
變量
變量:命名的內存空間
數據存儲方式:
字符:
數值:×××,浮點型
變量:變量類型
作用:
1、數據存儲格式
2、參與的運算
3、表示的數據範圍
類型:
字符
數值:×××、浮點型
加" "可以改變格式 如: echo="name"
變量: 強類型:變量不經過強制轉換,它永遠是這個數據類型,不允許隱式的類型轉 換。一般定義變量時必須制動類型、參與運算必須符合類型要求;調用未聲明 變量會產生錯誤 如 java,c# 弱類型:語言的運行時回隱形做數據類型轉換。無須指定類型,默認均為字符型; 參與運算會自動進行隱式類型轉換;變量無需事先定義可直接調用 如:bash不支持浮點數,php 可以用數字但是不能放在前面
變量命名法則:
1、不能使程序中的保留字:列如if,for
2、只能使用數字、字母及下劃線,且不能以數字開頭
3、見名知義
4、統一命名法則:駱峰命名法:把多個首字母大寫,小駝峰:第一個首字母大寫,
bash中變量的種類: 根據變量的生效範圍等標準劃分下面變量類型: 局部變量:生效範圍為當前shell進程;對當前shell之外的其他shell進程,包括 當前shell的子shell進程均無效 環境變量:生效範圍為當前shell進程及其子進程 本地變量:生效範圍為當前shell進程中某代碼片段,通常指函數 位置變量:$1,$2,...來表示,用於讓腳本在腳本代碼中調用通過命令行傳遞給它 的參數 特殊變量:$>,$0,$@,$#,$$ 局部變量: echo $$ echo $PPID:父子進程 局部變量只能在當前shell有效 在下級子進程變量不能往上傳別的進程 全局變量:使用要加關鍵字 export :把當前變量轉換環境變量 它允許往下傳 父進程可以傳給子進程 bash 後臺執行 declare -x 也可以生成所有環境變量 env也能顯示環境變量 unset name 刪除當前環境變量 set :本劇變量 全局變量都有 常量:固定值 readonly -p:顯示常量 ():用於一次性任務 執行一個小subsheell 不影響環境, {}:和小括號有區別 位置變量:能讓腳本寫死 $1 $2 $3 1 存的就是第一個字符串 10 個以上就得用{} 如:e‘cho "ALL args are {$10}" scp :可以遠程復制 scp.sh shift:從右往左擠掉 ping -c:指定網絡拼一次
總結:
shell
變量:局部和環境 $1,$@ $*,$#,$0
set unset exprot declare -i -r -x env
環境變量:
變量聲明、賦值:
export name=VALUE
declare -x name=VALUE
變量引用:$name,${name}
顯示所有環境變量:
env
printenv
export
declare -x
刪除變量:
unset name
環境變量:
bash內建的環境變量:
PATH
SHELL
UID
USER
HOME
PWD
SHLVL
LANG
MAIL
HOSTNAME
HISTSIZE
—:下劃線
只讀和位置變量:
只讀變量:只能聲明,但不能修改和刪除
聲明只讀變量:
readonly name
declare -r name
查看只讀變量:
readonly -p
位置變量:在腳本代碼中調用命令行傳遞給腳本的參數
$1,$2,...:對應第1,第2等參數,shift [n]換位置
$0:命令本身
$*;傳遞給腳本的所有參數,全部參數合為一個字符串
$@:傳遞給腳本的所有參數,每個參數為獨立字符串
$#:傳遞給腳本的參數的個數
$@$*只在被雙引號抱起來的時候才會有差異
set -- 清空所有位置變量
退出狀態:
進程使用退出狀態來報告成功或失敗
0代表成功,1 - 255代表失敗
$?:變量保存最近的命令退出狀態
列如:
ping -c1 -w1 hostdown &>/dev/null
echo$?
退出狀態碼:
bash自定義退出狀態碼
exit[n]:自定義退出狀態碼
註意:腳本中一旦遇到exit命令,腳本會立即終止;終止退出狀態取決於exit命
令後面的數字
註意:如果未給腳本指定退出狀態碼,整個腳本的退出狀態碼取決於腳本中執行
的最後一條命令的狀態碼
算數運算:
bash中的算數運算:help let
+,-,*,%取模(取余),**(乘方)
實現算數運算:
1、let var=算數表達式
2、var=$[算數表達式]
3、var=$((算數表達式))
4、var=$(expr arg1 arg2 arg3...)
5、declare -i var =數值
6、echo ‘算數表達式‘ | bc
乘法符號有些場景中需要轉義,如*
bash有內建的隨機數生成器:$RANDOM(0-32767)
echo $[$RANDOM%50】 :0-49之間隨機數
賦值:
增強型賦值:
+=,-=,*=,/=,%=
let varOPERvare
列如:let count+=3
自加3後減值
自增,自減:
let var+=1
let var++
let var-=1
let var--
邏輯運算;
true,false
1,0
與:
1與1=1 & 並且 and
1與0=0 | 或者 or
0與1=0 cmd1 && cmd2 如果cmd1為假,cmd2不需要執行,反之cmd1為真,需要cmd2執行
0與0=0 cmd1 || cmd2如果為真,cmd2不需要執行,反之cmd1為假,需要cmd2執行
或: XOR 異或
1或1=1 0^1=1
1或0=1 0^0=0
0或1=1 1^0=1
0或0=0 1^1=0
邏輯運算:
非:!
!1=0
!0=1
短路運算:
短路與
第一個為0,結果必定為0
第一個為1,第二個必須要參與運算
短路或
第一個為1,結果必定為1
第一個為0,第二個必須要參與運算
異或:^
異或的兩個值,相同為假,不必為真
條件測試;
判斷某需求是否滿足,需要由測試機制來實現
專用的測試表達式需要由測試命令輔助完成測試過程
評估布爾聲明,以便用條件執行中
若真,澤返回0
若假,則返回1
測試命令:
testEXPRESSION
[ EXPRESSION]
[[ EXPRESSION]]
註意:EXPRESSUON前後必須有空白字符
條件性的執行操作符:
根據退出狀態而定,命令可以有條件地運行
&&代表條件行的AN THEN
|| 代表條件行的OR ELSE
例如:
grep -q no_such_user /etc/passwd || echo ‘No such user‘
No such user
ping -c1 -W2 station1 &> /dev/null > && echo "station1 is up" > || (echo ‘station1 is unreachable‘; exit 1)
station1 is up
test命令
? 長格式的例子:
test "$A" == "$B" && echo "Strings are equal"
test “$A” -eq “$B” && echo "Integers are equal"
? 簡寫格式的例子:
[ "$A" == "$B" ] && echo "Strings are equal"
[ "$A" -eq "$B" ] && echo "Integers are equal"
bash的數值測試
?-v VAR
變量VAR是否設置
?數值測試:
-gt 是否大於
-ge 是否大於等於
-eq 是否等於
-ne 是否不等於
-lt 是否小於
-le 是否小於等於
bash的字符串測試
?字符串測試:
== 是否等於
> ascii碼是否大於ascii碼
< 是否小於
!= 是否不等於
=~ 左側字符串是否能夠被右側的PATTERN所匹配
註意: 此表達式一般用於[[ ]]中;擴展的正則表達式
-z "STRING“ 字符串是否為空,空為真,不空為假
-n "STRING“ 字符串是否不空,不空為真,空為假
? 註意:用於字符串比較時的用到的操作數都應該使用引號
Bash的文件測試
?存在性測試
-a FILE:同-e
-e FILE: 文件存在性測試,存在為真,否則為假
?存在性及類別測試
-b FILE:是否存在且為塊設備文件
-c FILE:是否存在且為字符設備文件
-d FILE:是否存在且為目錄文件
-f FILE:是否存在且為普通文件
-h FILE 或 -L FILE:存在且為符號鏈接文件
-p FILE:是否存在且為命名管道文件
-S FILE:是否存在且為套接字文件
Bash的文件權限測試
?文件權限測試:
-r FILE:是否存在且可讀
-w FILE: 是否存在且可寫
-x FILE: 是否存在且可執行
?文件特殊權限測試:
-u FILE:是否存在且擁有suid權限
-g FILE:是否存在且擁有sgid權限
-k FILE:是否存在且擁有sticky權限
Bash的文件屬性測試
?文件大小測試:
-s FILE: 是否存在且非空
?文件是否打開:
-t fd: fd 文件描述符是否在某終端已經打開
-N FILE:文件自從上一次被讀取之後是否被修改過
-O FILE:當前有效用戶是否為文件屬主
-G FILE:當前有效用戶是否為文件屬組
Bash的文件屬性測試
?雙目測試:
FILE1 -ef FILE2: FILE1是否是FILE2的硬鏈接
FILE1 -nt FILE2: FILE1是否新於FILE2(mtime)
FILE1 -ot FILE2: FILE1是否舊於FILE2
Bash的組合測試條件
?第一種方式:
COMMAND1 && COMMAND2 並且
COMMAND1 || COMMAND2 或者
! COMMAND 非
如:[[ -r FILE ]] && [[ -w FILE ]]
?第二種方式:
EXPRESSION1 -a EXPRESSION2 並且
EXPRESSION1 -o EXPRESSION2 或者
! EXPRESSION
必須使用測試命令進行
?示例:
[ -z “$HOSTNAME” -o $HOSTNAME "=="localhost.localdomain" ] && hostname www.magedu.com
[ -f /bin/cat -a -x /bin/cat ] && cat /etc/fstab
使用read命令來接受輸入
?使用read來把輸入值分配給一個或多個shell變量
-p 指定要顯示的提示
-s 靜默輸入,一般用於密碼
-n N 指定輸入的字符長度N
-d ‘字符’ 輸入結束符
-t N TIMEOUT為N秒
read 從標準輸入中讀取值,給每個單詞分配一個變量
所有剩余單詞都被分配給最後一個變量
read -p “Enter a filename: “ FILE
bash如何展開命令行
?把命令行分成單個命令詞
?展開別名
?展開大括號的聲明({})
?展開波浪符聲明(~)
?命令替換$() 和 ``)
?再次把命令行分成命令詞
?展開文件通配(*、?、[abc]等等)
?準備I/0重導向(<、>)
?運行命令
防止擴展
?反斜線(\)會使隨後的字符按原意解釋
$ echo Your cost: \$5.00
Your cost: $5.00
?加引號來防止擴展
? 單引號(’)防止所有擴展
? 雙引號(”)也防止所有擴展,但是以下情況例外:
?$(美元符號) - 變量擴展
?`(反引號) - 命令替換
?\(反斜線) - 禁止單個字符擴展
?!(嘆號) - 歷史命令替換
bash的配置文件
?按生效範圍劃分,存在兩類:
?全局配置:
/etc/profile
/etc/profile.d/*.sh
/etc/bashrc
?個人配置:
~/.bash_profile
~/.bashrc
bashrc bash run command
source 這種寫法在當前腳本中運行
一般配置文件用source
變量普通腳本是不能支持別名的
10:16
shell登錄兩種方式
?交互式登錄:
(1)直接通過終端輸入賬號密碼登錄
(2)使用“su - UserName” 切換的用戶
執行順序:/etc/profile --> /etc/profile.d/*.sh --> ~/.bash_profile -->
~/.bashrc --> /etc/bashrc
?非交互式登錄:
(1)su UserName
(2)圖形界面下打開的終端
(3)執行腳本
(4)任何其它的bash實例
執行順序: ~/.bashrc --> /etc/bashrc --> /etc/profile.d/*.sh
Profile類
?按功能劃分,存在兩類:
profile類和bashrc類
?profile類:為交互式登錄的shell提供配置
全局:/etc/profile, /etc/profile.d/*.sh
個人:~/.bash_profile
功用:
(1) 用於定義環境變量
(2) 運行命令或腳本
Bashrc類
?bashrc類:為非交互式和交互式登錄的shell提供配置
全局:/etc/bashrc
個人:~/.bashrc
功用:
(1) 定義命令別名和函數
(2) 定義本地變量
編輯配置文件生效
?修改profile和bashrc文件後需生效
兩種方法:
1重新啟動shell進程
2 . 或source
例:
. ~/.bashrc
Bash 退出任務
?保存在~/.bash_logout文件中(用戶)
?在退出登錄shell時運行
?用於
? 創建自動備份
? 清除臨時文件
$-變量
?h:hashall,打開這個選項後,Shell 會將命令所在的路徑hash下來,避免每次
都要查詢。通過set +h將h選項關閉
?i:interactive-comments,包含這個選項說明當前的 shell 是一個交互式的
shell。所謂的交互式shell,在腳本中,i選項是關閉的。
?m:monitor,打開監控模式,就可以通過Job control來控制進程的停止、繼
續,後臺或者前臺執行等。
?B:braceexpand,大括號擴展
?H:history,H選項打開,可以展開歷史列表中的命令,可以通過!感嘆號來完
成,例如“!!”返回上最近的一個歷史命令,“!n”返回第 n 個歷史命令
read x y z <<< "i j k"
echo $.
9:42
49
11:34
如何判斷命令是否存在?
which mkisofs >& /dev/null
if [ "$?" != 0 ] ; then
echo "mkisofs Not Found"
echo "yum install mkisofs"
fi
判斷文件是否存在?
if [ -f $2 ]; then
echo "....."
exit 1
fi
test(選項)
選項
-b<文件>:如果文件為一個塊特殊文件,則為真;
-c<文件>:如果文件為一個字符特殊文件,則為真;
-d<文件>:如果文件為一個目錄,則為真;
-e<文件>:如果文件存在,則為真;
-f<文件>:如果文件為一個普通文件,則為真;
-g<文件>:如果設置了文件的SGID位,則為真;
-G<文件>:如果文件存在且歸該組所有,則為真;
-k<文件>:如果設置了文件的粘著位,則為真;
-O<文件>:如果文件存在並且歸該用戶所有,則為真;
-p<文件>:如果文件為一個命名管道,則為真;
-r<文件>:如果文件可讀,則為真;
-s<文件>:如果文件的長度不為零,則為真;
-S<文件>:如果文件為一個套接字特殊文件,則為真;
-u<文件>:如果設置了文件的SUID位,則為真;
-w<文件>:如果文件可寫,則為真;
-x<文件>:如果文件可執行,則為真。
實例
linux中shell編程中的test常見用法:
判斷表達式
if test #表達式為真
if test ! #表達式為假
test 表達式1 –a 表達式2 #兩個表達式都為真
test 表達式1 –o 表達式2 #兩個表達式有一個為真
test 表達式1 ! 表達式2 #條件求反
判斷字符串
test –n 字符串 #字符串的長度非零
test –z 字符串 #字符串的長度是否為零
test 字符串1=字符串2 #字符串是否相等,若相等返回true
test 字符串1!=字符串2 #字符串是否不等,若不等反悔false
判斷整數
test 整數1 -eq 整數2 #整數相等
test 整數1 -ge 整數2 #整數1大於等於整數2
test 整數1 -gt 整數2 #整數1大於整數2
test 整數1 -le 整數2 #整數1小於等於整數2
test 整數1 -lt 整數2 #整數1小於整數2
test 整數1 -ne 整數2 #整數1不等於整數2
判斷文件
test File1 –ef File2 兩個文件是否為同一個文件,可用於硬連接。主要判斷兩個文件是否指向同一個inode。
test File1 –nt File2 判斷文件1是否比文件2新
test File1 –ot File2 判斷文件1比是否文件2舊
test –b file #文件是否塊設備文件
test –c File #文件並且是字符設備文件
test –d File #文件並且是目錄
test –e File #文件是否存在 (常用)
test –f File #文件是否為正規文件 (常用)
test –g File #文件是否是設置了組id
test –G File #文件屬於的有效組ID
test –h File #文件是否是一個符號鏈接(同-L)
test –k File #文件是否設置了Sticky bit位
test –b File #文件存在並且是塊設備文件
test –L File #文件是否是一個符號鏈接(同-h)
test –o File #文件的屬於有效用戶ID
test –p File #文件是一個命名管道
test –r File #文件是否可讀
test –s File #文件是否是非空白文件
test –t FD #文件描述符是在一個終端打開的
test –u File #文件存在並且設置了它的set-user-id位
test –w File #文件是否存在並可寫
test –x File #文件屬否存在並可執行
expr用法
expr命令一般用於整數值,但也可用於字符串。一般格式為:
#expr argument operator argument
expr也是一個手工命令行計數器。
#$expr 10 + 10
20
#$expr 1500 + 900
2500
#$expr 30 / 3
10
#$expr 30 / 3 / 2
5
(註意運算符左右都有空格)
使用乘號時,必須用反斜線屏蔽其特定含義。因為shell可能會誤解顯示星號的意義。
#$expr 30 * 3
90
17.5.1 增量計數
expr在循環中用於增量計算。首先,循環初始化為0,然後循環值加1,反引號的用法意
即替代命令。最基本的一種是從(expr)命令接受輸出並將之放入循環變量。
$LOOP=0
#$LOOP=`expr $LOOP + 1`
17.5.2 數值測試
可以用expr測試一個數。如果試圖計算非整數,將返回錯誤。
$rr=1.1
#$expr $rr + 1
#expr: non-numeric argument
$rr=2
$expr $rr + 1
3
(註意:這個例子與原文不同)
這裏需要將一個值賦予變量(不管其內容如何),進行數值運算,並將輸出導入dev/null,
然後測試最後命令狀態,如果為0,證明這是一個數,其他則表明為非數值。
$value=12
#$expr $value + 10 > /dev/null 2>&1
$echo $?
0
這是一個數。
$value=hello
#$expr $value + 10 > /dev/null 2>&1
$echo $?
2
這是一個非數值字符。
expr也可以返回其本身的退出狀態,不幸的是返回值與系統最後退出命令剛好相反,成功返回1,任何其他值為無效或錯誤。下面的例子測試兩個字符串是否相等,這裏字符串為“hello”和“hello”。
$value=hello
$expr $value = "hello"
1
$echo $?
0
expr返回1。不要混淆了,這表明成功。現在檢驗其最後退出狀態,返回0表示測試成功,
“hello”確實等於“hello”。
17.5.3 模式匹配
expr也有模式匹配功能。可以使用expr通過指定冒號選項計算字符串中字符數。.*意即任何字符重復0次或多次。
$value=accounts.doc
$expr $value : ‘.*‘
12
在expr中可以使用字符串匹配操作,這裏使用模式. d o c抽取文件附屬名。
$expr $value : ‘(.*).doc‘
accounts
一些基礎腳本知識