第七天
運行腳本的條件:
1、加執行權限或者bash+腳本名
2、寫路徑(絕對、相對均可) 加執行權限以后,如果沒有放在PATH變量下的路徑內,運行腳本需要寫路徑
3、如果不想寫路徑,可以將腳本放在PATH變量中的任何位置均可,通常放/root/bin下,/bin需要增加創建
腳本調試
只檢測腳本中的語法錯誤
bash -n /path/to/some_script
跟蹤調試執行
bash -x /path/to/some_script (+代表有命令,++代表命令套命令)
總結:
如果腳本中命令錯誤,錯誤的命令不執行,但是其他的命令均執行
如果腳本中存在語法錯誤,從語法錯誤的命令開始往下均不執行,在語法錯誤之上的命令均執行
變量
引用變量一般加$符號,最好加雙引號,如echo “$USER”,命令能識別變量就不加$
例:name=”mage” name這個變量名,存的是mage這個字符串
name=`hostname` echo $name 顯示的是主機名
name=`cat /etc/fstab` echo $name 格式有問題,沒有保留原格式
name=`cat /etc/fstab` echo “$name” 格式與cat /etc/fstab一樣
name1=mage name2=wang name3=$name1 echo $name3 顯示的是mage,
此時name1=zhangsir echo $name3 顯示的是mage,
如果重新為name3賦值,name3=$name1 echo $name3 顯示的時zhangsir
在shell腳本里面,i=100,并沒有把它當成數字100,而是把它當成字符串
bash 不支持浮點數(即小數)
變量命名法則:
1、不能使用程序中的保留字:例如if, for
2、只能使用數字、字母及下劃線,且不能以數字開頭
3、見名知義
4、統一命名規則:駝峰命名法(每個單詞的首字母大寫是大駝峰,第一個單詞的首字母小寫,其他單詞的首字母大寫是小駝峰)
bash中變量的種類
根據變量的生效范圍等標準劃分下面變量類型:
局部變量:1、生效范圍為當前shell進程,對當前shell之外的其它shell進程,包括當前shell的子shell進程均無效,在下級進程里面定義的變量不會影響上級進程的變量。說白了局部變量傳不下去也傳不上來
例:輸入命令bash,相當于開了個子bash
echo $$ 顯示的是當前進程的進程編號
echo $PPID 顯示的是父進程的進程編號
想看進程關系,輸入pstree -p
2、其他終端會話上也無效
變量賦值:name=‘value’
可以使用引用value:
(1) 可以是直接字串; name=“root”
(2) 變量引用:name=”$USER”
(3) 命令引用:name=` COMMAND ` name =$(COMMAND)
變量引用:${name} $name
“”:弱引用,其中的變量引用會被替換為變量值
”:強引用,其中的變量引用不會被替換為變量值,而保持原字符串
顯示已定義的所有變量:set
刪除變量:unset name 刪除name變量
環境(全局)變量:生效范圍為當前shell進程及其子進程(只能往下傳不能往上傳)
子進程的變量可以使用父進程的變量,子進程的變量也可以修改,但是不會影響父進程的變量。
export name=wang 將name變量賦值為wang并定義該變量為全局變量
export 顯示的是系統中目前的全部環境變量
declare -x name=xixi 也是定義全局變量
env 顯示系統中的全局變量
變量聲明、賦值:
export name=VALUE
declare -x name=VALUE
變量引用:$name, ${name}
顯示所有環境變量:
env
export
declare -x
echo -e “\e[1;31mstart backup\e[0m” 加顏色
例:編寫腳本/root/bin/backup.sh,可實現每日將/etc/目錄備份到/root/etcYYYY-mm-dd中
echo -e “\e[1;31mstart backup\e[0m”
sleep 2
cp -av /etc /root/etc`date +%F`
echo “backup is finished”
本地變量:生效范圍為當前shell進程中某代碼片斷,通常指函數
特殊變量:$?, $0, $*, $@, $#,$$
bash內建的環境變量:
PATH
SHELL
USER
UID
HOME
PWD
SHLVL shell的嵌套深度
LANG
MAIL
HOSTNAME
HISTSIZE
— 代表前面命令的最后一個參數
如:echo a b c
echo $_ 顯示的是c
如:ls /boot /data /root
echo $_ 顯示的是/root
只讀和位置變量
只讀變量:只能讀,但不能修改和刪除
聲明只讀變量:
readonly name 例:readonly name=liu
declare -r name 例:declare -r name=liu
只讀變量退出再進來就消失了
查看只讀變量:
readonly –p
declare -r
()的作用:在當前shell環境下開啟一個新空間,shell進程編號未變,小括號里面的變量不影響外面,外面的變量可以影響小括號里面。
加小括號的意思是執行一次小括號里面的命令就完事了
所以將來編腳本的時候如果需要用到一次性的任務,不想影響周邊的環境,就可以用小括號寫法
如:我只想這一次創建一個權限為000的文件,后面的文件默認權限不變
(umask 666;touch /data/f1)
ll /data/f1
———-. 1 root root 0 Apr 9 22:26 f1
touch f2
ll /data/f2
-rw-r–r–. 1 root root 0 Apr 9 22:26 f2
如:在root家目錄下輸入:(cd /data;rm -f f3)
意思是執行完刪除/data下的f3文件后又返回原目錄。
{}的作用:不開啟子shell,將影響當前的shell環境,注意{}的寫法,前后有空格,且最后有分號
{ name=mage;$name; } 顯示wang
echo $name 顯示還是wang
()與{}的共同點是將括號內作為一個整體,把括號內的多個命令統一執行
小括號:當前的shell環境下開啟一個新空間,shell進程編號未變,小括號里面不影響外面,外面可以影響小括號里面
例題:x=1;echo “pid=$$”;(echo “subpid=$$”;echo “subx=$x”;x=2;echo “sub2x”);echo x=$x
顯示的是
pid=51503
subpid=51503
subx=1
sub2x=2
x=1
位置變量:在腳本代碼中調用通過命令行傳遞給腳本的參數
$1, $2, …:對應第1、第2等參數,shift [n]換位置
$0: 命令本身(包括路徑及腳本名) 使用軟鏈接運行腳本的時候,$0顯示的就是軟鏈接的路徑和軟鏈接名,這是特殊需要記憶的
$* 傳遞給腳本的所有參數,全部參數合為一個字符串
$@: 傳遞給腳本的所有參數,每個參數為獨立字符串
$#: 傳遞給腳本的參數的個數
$@ $* 只在被雙引號包起來的時候才會有差異
set — 清空所有位置變量
例如:編一個腳本arg.sh
echo “1st arg is $1”
echo “2st arg is $2”
echo “3st arg is $3”
echo “all arg is $*”
echo “all arg is $@”
echo “the args number is $#”
echo “the script name is `basename $0`”
輸入:arg.sh xxx yy zzzz
顯示:
1st arg is xxx
2st arg is yy
3st arg is zzzz
all arg is xxx yy zzzz
all arg is xxx yy zzzz
the arg number is 3
the script is arg.sh
例如:
echo “9st arg is $9”
echo “10st arg is $10”
輸入:arg.sh a b c d e f g h i j
顯示:9st arg is i
10st arg is a0
如果想表示第十個參數則必須加{},所以應該改成
echo “10st arg is ${10}”
scp f1 wang@172.20.102.77:/home/wang/bin 遠程復制,將f1文件復制到ip為172.20.102.77的wang用戶的/home/wang/bin下,該網址是橋接網卡的網址
編寫一個腳本,腳本的作用是我每次運行這個腳本跟上文件名就能將文件傳給wang@172.20.102.77這個用戶
vim scp.sh
echo “start copy…”
scp $* wang@172.20.102.77:/home/wang/bin
echo “copy finish”
編寫完后chmod +x scp.sh
運行scp.sh /etc/centos-release
$*與$@的區別:只在被雙引號包起來的時候才會有差異
例:編寫fi.sh和f2.sh
vim f1.sh
echo “f1.sh:all arg are $*”
./f2.sh “$*” “$*”作為一個整體 “$@”不作為一個整體
vim f2.sh
echo “f2.sh:1st arg is $1”
運行f1.sh腳本
f1.sh a b c
顯示:
f1.sh:all arg are a b c
f2.sh:1st arg is a b c
例:
vim f1.sh
echo “f1.sh:all arg are $*”
set —
echo “f1.sh:all arg are $*”
運行f1.sh腳本
f1.sh a b c
顯示:
f1.sh:all arg are a b c
f1.sh:all arg are
例如:編一個腳本arg.sh
echo “1st arg is $1”
echo “2st arg is $2”
echo “3st arg is $3”
echo “all arg is $*”
echo “all arg is $@”
echo “the args number is $#”
echo “the script name is `basename $0`”
創建一個agr.sh的軟鏈接
ln -s agr.sh link.sh
運行link.sh a b c 注:使用軟鏈接運行腳本的時候,$0顯示的就是軟鏈接的路徑和軟鏈接名
顯示
1st arg is a
2st arg is b
3st arg is c
all arg is a b c
all arg is a b c
the arg number is 3
the script is link.sh
例:
echo “1st arg is $1”
echo “2st arg is $2”
echo “3st arg is $3”
echo “all arg is $@”
echo “the args number is $#”
shift
echo “1st arg is $1”
echo “2st arg is $2”
echo “3st arg is $3”
echo “all arg is $@”
echo “the args number is $#”
shift
echo “1st arg is $1”
echo “2st arg is $2”
echo “3st arg is $3”
echo “all arg is $@”
echo “the args number is $#”
運行arg.sh a b c
1st arg is a
2st arg is b
3st arg is c
all arg is a b c
the arg number is 3
1st arg is b
2st arg is c
3st arg is
all arg is b c
the arg number is 2
1st arg is c
2st arg is
3st arg is
all arg is c
the arg number is 1
總結:shift命令默認將參數左移頂掉一位,可以移多位,shift后面跟上相應的數字即可
退出狀態
進程使用退出狀態來報告成功或失敗
0 代表成功,1-255代表失敗
$? 變量保存最近的命令退出狀態
例如:
ping -c1 -W1 hostdown &> /dev/null
echo $?
-c1 意思是ping一次
對于腳本來講,如
hostname
echo “$?” 這個$?顯示的是上一條命令的執行結果
如果腳本中有錯誤命令,如編制腳本f3.sh
histnam
ls
運行f3.sh腳本
echo $? 顯示的是0
如果將f3.sh腳本內容變為
ls
hostnam
運行f3.sh腳本
echo $? 顯示的不是0
總結:說明腳本運行后查看$?,$?的值是由腳本中最后一條命令決定的,最后一條命令沒問題,$?就是0,否則就不是0
如果腳本中存在語法錯誤,則$?為非0
退出狀態碼
bash自定義退出狀態碼
exit [n]:自定義退出狀態碼 如exit 5 echo “$?”如果成功顯示的就是5
注意:腳本中一旦遇到exit命令,腳本會立即終止,后面的命令就不執行了;終止退出狀態取決于exit命令后面的數字
注意:如果未給腳本指定退出狀態碼,整個腳本的退出狀態碼取決于腳本中執行的最后一條命令的狀態碼
總結:
我們去編制一個腳本的時候就相當于在當前的shell里開啟了一個子進程
例如:我們定義一個變量,可以在新建的腳本中顯示出來嗎?
name=wang
vim f3.sh
echo “f3.sh:$name”
運行f3.sh腳本
顯示
f3.sh: 原因是局部變量父不傳子,如果name定義為全局變量,就可以顯示f3.sh:wang
算術運算
bash中的算術運算:help let
+, -, *, /, %取模(取余), **(乘方)
實現算術運算:
(1) let var=算術表達式 例如:let result=100%3 echo $result 顯示的是1,也可以寫成result=$[100%3] echo $result let中乘號需要轉義
(2) var=$[算術表達式] 例如:m=2 n=3 sum=$[$m+$n] echo $sum 顯示的是5 備注:這個公式乘號不需要轉義
(3) var=$((算術表達式))
(4) var=$(expr arg1 arg2 arg3 …)例:var=$(expr 1 + 2) echo ${var} 也可以做乘積var=$(expr 1 \* 2) echo $var *需要轉義 expr是表達式
(5) declare –i var = 數值 例:declare -i a=10;declare -i b=20;declare -i c=$a+$b;echo $c
(6) echo ‘算術表達式’ | bc
乘法符號有些場景中需要轉義,如*(let和expr中乘號需要轉義)
bash有內建的隨機數生成器:$RANDOM(0-32767)
echo $[$RANDOM%50] :0-49之間隨機數
例如:
x=10
y=20
let z=$x+$y
echo $z 顯示30
賦值
增強型賦值:
+=, -=, *=, /=, %=
let varOPERvalue
例如:let count+=3
自加3后自賦值
自增,自減:
let var+=2 相當于var=var+2
let var++ 相當于var=var+1
let var-=1
let var–
例:編制colour.sh腳本,將colour打印出來,每次顏色隨機
colour=$[RANDOM%7+31]
echo -e “\e[1;${colour}mcolour\e[0m”
通常認為0是假,1是真
&相當于并且,取交集
0&0 0
0&1 0
1&0 0
1&1 1
|相當于或
0|0 0
0|1 1
1|0 1
1|1 1
非:!
!1 = 0
!0 = 1
短路與 &&
短路或 ||
0&&0 0 cmd1&&cmd2 如果cmd1為假,cmd2為真還是為假不影響結果,cmd2不需要執行
0&&1 0
1&&0 0 cmd1&&cmd2 如果cmd1為真,需要執行cmd2
1&&1 1
0||0 0
0||1 1 cmd1||cmd2 如果cmd1為假,需要執行cmd2
1||0 1 cmd1||cmd2 如果cmd1為真,不需要執行cmd2
1||1 1
XOR 異或(如果兩個值相同,結果為假,如果兩個值不同,結果為真)
0^1=1
0^0=0
1^0=1
1^1=0
異或的時候是二進制計算
例如:
a=2
b=3
let c=$a^$b
echo $c 顯示的是1
為什么是1?解析如下
首先需要將2和3轉換為二進制,即
10 (2的二進制表示)
11 (3的二進制表示)
01 (對位異或)
所以結果為1
例如
b=4
a=6
let c=$a^$b
echo $c 顯示的是2
110 (6的二進制表示)
100 (4的二進制表示)
010 (對位異或) 二進制的10就是十進制的2
延伸:將a和b互換
原始方法找一個臨時變量
tmp=$a
a=$b
b=$tmp
通過異或來實現對調a=5 b=6
a=$[a^b];b=$[a^b];a=$[a^b];echo $a $b
練習:
1、編寫腳本/root/bin/sumid.sh,計算/etc/passwd文件中的第10個用戶和第
20用戶的ID之和
x=`head -n $1 /etc/passwd | tail -n 1 | cut -d: -f 3`
y=`head -n $2 /etc/passwd | tail -n 1 | cut -d: -f 3`
let z=$x+$y
echo $z
運行sumid.sh 10 20 即可得出結論
2、編寫腳本/root/bin/sumspace.sh,傳遞兩個文件路徑作為參數給腳本,計
算這兩個文件中所有空白行之和
a=`sed -r ‘/^[[:space:]]*$/!d’ $1 | wc -l`
b=`sed -r ‘/^[[:space:]]*$/!d’ $2 | wc -l`
let c=$a+$b
echo $c
3、編寫腳本/root/bin/sumfile.sh,統計/etc, /var, /usr目錄中共有多少個一級
子目錄和文件
a=`ls -1 $1 | wc -l`
b=`ls -1 $2 | wc -l`
c=`ls -1 $3 | wc -l`
let d=$a+$b+$c
echo $d
條件測試
判斷某需求是否滿足,需要由測試機制來實現
專用的測試表達式需要由測試命令輔助完成測試過程
評估布爾聲明,以便用在條件性執行中
若真,則返回0
若假,則返回1
測試命令:
test EXPRESSION
[ EXPRESSION ]
[[ EXPRESSION ]]
注意:EXPRESSION前后必須有空白字符
例:str1=aaa str2=bbb 比較下這兩個字符串是否相同?
test $str1 = $str2 (注意等號前后有空格)
是否相等,輸入echo $?
如果是0則相等,如果是1則不相等
還可以寫成
str1=aaa str2=bbb
[ $str1 = $str2 ] (注意中括號內的空格問題)
echo $?
例:判斷某個變量是否為空
[ -z $var ] 等價于test -z $var -z意為zero
echo $?
如果為0,則變量var未賦值,如果為1,則變量var有值
例:判斷某個變量是否為非空
[ -n $var ] -n可以省略
echo $?
如果顯示0則說明var變量有值,如果為1則說明var變量為空
[ “abc” ] echo $?顯示的是0
[ “” ] echo $?顯示的是1
[] echo $?顯示的是1
例:
x=haha;y=xixi;[ $x = $y ] && echo “equal” || echo “no equal”
邏輯關系是如果[ $x = $y ]為真,則執行echo “equal”
如果[ $x = $y ]為假,則執行echo “no equal”
例:
m=10;n=20
[ $m -eq $n ] && echo “equal” || echo “no equal” 數字相比是否相同使用-eq
數值測試:
-gt 是否大于 great
-ge 是否大于等于 great equal
-eq 是否等于 equal
-ne 是否不等于 not equal
-lt 是否小于 little
-le 是否小于等于 little equal
bash的字符串測試
字符串測試:
== 是否等于 特殊:[[ == * ]],這里的*是通背符,代表任意字符串,不是正則表達式中的*
> ascii碼是否大于ascii碼
< 是否小于
!= 是否不等于
=~ 左側字符串是否能夠被右側的PATTERN所匹配
注意: 此表達式一般用于[[ ]]中;擴展的正則表達式
-z “STRING“ 字符串是否為空,空為真,不空為假
-n “STRING“ 字符串是否不空,不空為真,空為假
注意:用于字符串比較時用到的操作數都應該使用引號
例如:編制腳本diskcheck.sh檢查分區磁盤最大的那個是否大于等于80,如果大于80就報警,顯示最大分區占用率
x=`df | grep “sda” |tr -s ” ” “%” | cut -d “%” -f 5 | sort -nr | head -n1`
[ “$x” -ge 80 ] && echo “disk full” || echo “disk no full”
echo $x
例:如果光打下面的命令
[ $n -ge 80 ] && echo warning會提示
bash: [: -ge: unary operator expected
因為變量n為空,所以建議加””
[ “$n” -ge 80 ] && echo warning
總結:變量在中括號里面或者與test命令搭配時最好加上雙引號,避免提示錯誤
例:編寫腳本/root/bin/sumid.sh,計算/etc/passwd文件中的第10個用戶和第
20用戶的ID之和。
[ $# -ne 2 ]&& echo “arg are two” && exit
x=`head -n $1 /etc/passwd | tail -n 1 | cut -d: -f 3`
y=`head -n $2 /etc/passwd | tail -n 1 | cut -d: -f 3`
z=$[$x+$y]
echo $z
運行sumid.sh 10 20
例如
n=12
[[ “$n” =~ ^[[:digit:]]+ ]] && echo digit || echo “no digit” 引用正則表達式必須是[[]]
n這個變量的值能否被右邊的digit匹配到,如果能匹配到執行echo digit,如果匹配不到,執行echo “no digit”
也可以寫成[[ “$n” =~ ^[0-9]+$ ]] && echo digit || echo “no digit”
如果寫成[[ ! “$n” =~ ^[0-9]+$ ]] && echo digit || echo “no digit”
! “$n” =~ ^[0-9]+$ 表示$n不是數字的話
表示如果”$n” =~ ^[0-9]+$是真,!”$n” =~ ^[0-9]+$就為假,則輸出echo “no digit”
例:編寫腳本/root/bin/sumid.sh,計算/etc/passwd文件中的第10個用戶和第
20用戶的ID之和。
[ $# -ne 2 ]&& echo “arg are two” && exit
[[ ! “$1” =~ ^[0-9]+$ ]] && echo “$1 is not digit”&& exit 表示$1不是數字的話,輸出$1 is not digit并且退出
[[ ! “$2” =~ ^[0-9]+$ ]] && echo “$2 is not digit”&& exit 表示$2不是數字的話,輸出$2 is not digit并且退出
x=`head -n $1 /etc/passwd | tail -n 1 | cut -d: -f 3`
y=`head -n $2 /etc/passwd | tail -n 1 | cut -d: -f 3`
z=$[$x+$y]
echo $z
例如:編寫f.sh腳本
[[ $f1 =~ .+\.sh$ ]] && echo sh || echo no
保存退出
將f1=a.sh 后運行f1.sh顯示no
原因是未將變量f1定義為全局變量,父進程定義的變量值無法傳到子進程
以后寫腳本的時候盡量不要在腳本中調用父進程的變量,如果要調請將變量定義為全局變量
Bash的文件測試
存在性測試
-a FILE:同-e ,判斷文件是否存在 例如:[ -a /etc/fstab ] && echo exist
-e FILE: 文件存在性測試,存在為真,否則為假
存在性及類別測試
-b FILE:是否存在且為塊設備文件
-c FILE:是否存在且為字符設備文件
-d FILE:是否存在且為目錄文件 例:[ -d /etc/ ] && echo ture [ -d /bin ] && echo ture 顯示ture,但是實際不是文件夾是個軟鏈接,需要注意下
-f FILE:是否存在且為普通文件
-h FILE 或 -L FILE:存在且為符號鏈接文件
-p FILE:是否存在且為命名管道文件
-S FILE:是否存在且為套接字文件
-L FILE:是否為軟鏈接 [ -L /bin ] && echo ture 顯示為ture [ -L /bin/ ] && echo ture 沒有顯示
-w FILE:是否有寫權限,以實際權限為準,不是看ll那一欄 如[ -w /etc/shadow ] && echo ture || echo false
-r FILE:是否有讀權限
-x FILE:是否有執行權限
例如:想創建用戶,但是事先得先判斷下用戶是否已經存在,如果存在不創建,如果不存在則創建,同時指定用戶口令
id $1 &> /dev/null
[ $? -ne 0 ] && useradd $1 || { echo exist ; exit; } 備注:這塊必須用大括號,注意大括號的格式,大括號的作用是讓括號內的命令作為一個整體且影響整個shell環境,
echo magedu | passwd –stdin $1 如果使用小括號,意味著退出echo那個進程后會繼續往下執行其余命令
例如:假如為假我希望兩個命令都執行,為真都不執行
false || echo cmd1 && echo cmd2 顯示的是cmd1 cmd2
true || echo cmd1 && echo cmd2 顯示的是cmd2 這就不對了,有違初衷
如果為真都不執行則
true || { echo cmd1;echo cmd2; }
例如:看看大括號和小括號的區別
false || { echo cmd1;exit; } 顯示的是cmd1 logout,退出當前進程,所以寫腳本必須用大括號
false || ( echo cmd1;exit ) 顯示的是cmd1 退出echo這個進程,后續如果有命令繼續執行
例如:-a并且 -o或 -v是否此變量已經被設置
[ -r /etc/issue -a -w /etc/issue ]&& echo “read and write” 意思是判斷對/etc/issue能讀并且能寫,如果為真顯示read and write
[ -r /etc/issue -o -w /etc/issue ]&& echo “read or write” 意思是判斷對/etc/issue能讀或者能寫,如果為真顯示read or write
[ -v “$var1″ ] && echo set 如果有值顯示set
var1=”” [ -v “$var1” ] && echo set || echo “no set” 顯示的是no set
電腦認為是賦值了,只不過為空字符串而已
例:判斷變量是否為空的方法
[ -z “$var” ]
[ -n “$var” ]
[ “$var” = “” ]
[ x”$var” = “x” ]
使用read命令來接受輸入
使用read來把輸入值分配給一個或多個shell變量
-p 指定要顯示的提示
-s 靜默輸入,一般用于密碼 read -p -s “please input your password:” password passwd前面必須有空格,否則賦不上值
-n N 指定輸入的字符長度N read -n 3 name 為name變量賦值最多三個字符
-d‘字符’ 輸入結束符 read -d a name 為name賦值,什么時候有a就退出
-t N TIMEOUT為N秒 read – t 5 name 如果五秒鐘不輸出自動退出
read 從標準輸入中讀取值,給每個單詞分配一個變量
所有剩余單詞都被分配給最后一個變量
read -p “Enter a filename: “ FILE
read var1敲回車等待輸入,輸入的值就是變量var1的值,echo $var1
如:編一個read.sh腳本,功能是提示輸入姓名并把姓名顯示出來
echo -e “please input you name:\c” \c取消換行符
read name
echo “your name is $name”
或者
read -p “please input your name:” name
echo “your name is $name”
例如:雞兔同籠,頭35 腳94 請問雞多少只,兔子多少只
read -p “head number:” head
read -p “feet number:” feet
let rabbit=($feet-2\*$head)/2
let chook=$head-$rabbit
echo $chook
echo $rabbit
例如:
read x y z 回車輸入a b c
echo $x 顯示a
echo $y 顯示b
echo $z 顯示c
echo a b c > f1
read x y z < f1
echo $x 顯示a
echo $y 顯示b
echo $z 顯示c
f1內存有a b c
read x y z < f1
echo $x 顯示a
echo $y 顯示b
echo $z 顯示c
echo aa bb cc | read x y z
echo $x 顯示a
echo $y 顯示b
echo $z 顯示c
cat > f1
aaa
bbb
ccc
cat f1 | read x y z
echo $x 顯示a
echo $y 顯示b
echo $z 顯示c
cat > f1
aaa
bbb
ccc
read x y z < f1
echo $x 顯示aaa
echo $y 沒有顯示
echo $z 沒有顯示
read x y z <<< “ii jj kk” 用這種方法好用
echo $x 顯示的是ii
echo $y 顯示的是jj
echo $z 顯示的是kk
第八天
.和source后面一般跟的是配置文件
如:在命令行輸入
CMD=”hostname”
echo $CMD 顯示的是hostname
$CMD 顯示的是centos6.magedu.com(主機名)
如果cmd=`hostname`
echo $CMD 顯示的是centos6.magedu.com(主機名)
如果用于字符串的精確匹配,那么我們一般用[],例如:[ “var” = “haha” ]
如果用正則表達式,則[[]]
如:假設cmd2始終為真
cmd1 || cmd2 && cmd3 如果cmd1為真,cmd2不執行,cmd3執行。如果cmd1為假,執行cmd3
cmd1 && cmd2 || cmd3 如果cmd1為真,不執行cmd3,如果cmd1為假,執行cmd3
如果想cmd1為假,我希望cmd2和cmd3都執行,則
cmd1 || { cmd2;cmd3; }
例如:判斷輸入是yes還是no
read -p “Do you agree?yes or no:” ans
[[ $ans =~ ^([yY]|[Yy][eE][Ss])$ ]] &&{ echo yes;exit; }
[[ $ans =~ ^([nN]|[Nn][oO])$ ]] && { echo no; exit; }
#[[ $ans =~ ^([^Yy]|[^nN]) ]] && echo please input yes or no:
[[ ! $ans =~ (^([yY]|[Yy][eE][Ss])$ | ^([nN]|[Nn][oO])$) ]] && echo please input yes or no:
bash的配置文件
按生效范圍劃分,存在兩類:
全局配置:
/etc/profile
/etc/profile.d/*.sh
/etc/bashrc
個人配置:
~/.bash_profile
~/.bashrc bashrc相當于bash run command
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
.和source 與運行腳本bash或者直接執行腳本的區別
source表示在當前shell運行,不是開啟子進程
例如: vim f1.sh
name=haha
echo “f1.sh:name=$name”
在父進程定義name=xixi
source f1.sh
顯示的是f1.sh:name=haha
echo $name
顯示的是haha,并不是xixi
所以:腳本運行用bash或者直接加執行權限,配置文件一般用source或者.立即生效
.vimrc 不是bash的配置文件,所以不能用.或source
默認別名不能放在腳本里面,腳本不支持別名,在腳本里定義別名也失效
Profile類
按功能劃分,存在兩類:
profile類和bashrc類
profile類:為交互式登錄的shell提供配置
全局:/etc/profile, /etc/profile.d/*.sh
個人:~/.bash_profile
功用:
(1) 用于定義環境變量
(2) 運行命令或腳本
Bashrc類
bashrc類:為非交互式和交互式登錄的shell提供配置
全局:/etc/bashrc
個人:~/.bashrc
功用:
(1) 定義命令別名和函數
(2) 定義本地變量
Bash 退出任務
保存在~/.bash_logout文件中(用戶)
在退出登錄shell時運行
用于:創建自動備份和清除臨時文件
.bash_logout 存放的是退出的時候做點什么事,例如在.bash_logout存放rm -f /root/dir1/*
$-變量
h:hashall,打開這個選項后,Shell 會將命令所在的路徑hash下來,避免每次
都要查詢。通過set +h將h選項關閉
i:interactive-comments,包含這個選項說明當前的 shell 是一個交互式的
shell。所謂的交互式shell,在腳本中,i選項是關閉的。
m:monitor,打開監控模式,就可以通過Job control來控制進程的停止、繼
續,后臺或者前臺執行等。
B:braceexpand,大括號擴展 例如echo f{1..10}
H:history,H選項打開,可以展開歷史列表中的命令,可以通過!感嘆號來完
成,例如“!!”返回上最近的一個歷史命令,“!n”返回第 n 個歷史命令
練習
1、讓所有用戶的PATH環境變量的值多出一個路徑,例如:/usr/local/apache/bin
vim /etc/profile.d/env.sh
PATH=/etc/profile.d/env.sh:$PATH
etc/sysconfig/network-scripts/ifcfg-ens33 centos7上修改網卡設置的路徑
etc/sysconfig/network-scripts/ifcfg-eth0 centos6上修改網卡設置的路徑
2、用戶root登錄時,將命令指示符變成紅色,并自動啟用如下別名:
rm=‘rm –i’
cdnet=‘cd /etc/sysconfig/network-scripts/’
editnet=‘vim /etc/sysconfig/network-scripts/ifcfg-eth0’
editnet=‘vim /etc/sysconfig/network-scripts/ifcfg-eno16777736 或 ifcfg-ens33 ’ (如果系
統是CentOS7)
答:
PS1=”\[\e[1;31m\][\u@\h \W]\\$\[\e[0m\]”
alias rm=’rm –i’
alias cdnet=’cd /etc/sysconfig/network-scripts/’
alias editnet=’vim /etc/sysconfig/network-scripts/ifcfg-ens33′
3、任意用戶登錄系統時,顯示紅色字體的警示提醒信息“Hi,dangerous!”
^[[1;31mHi,dangerous!^[[0m
4、編寫生成腳本基本格式的腳本,包括作者,聯系方式,版本,時間,描述等
5、編寫用戶的環境初始化腳本reset.sh,包括別名,登錄提示符,vim的設置,
環境變量等
答:vim reset.sh
echo “alias cdnet=’cd /etc/sysconfig/network-scripts/'” >> /etc/profile.d/env.sh
echo “alias editnet=’vim /etc/sysconfig/network-scripts/ifcfg-ens33′” >> /etc/profile.d/env.sh
echo “export name=liubaoyu” >> /etc/profile.d/env.sh
echo ‘PS1=”\[\e[1;32m\][\u@\h \W]\\$\[\e[0m\]”‘ >> /etc/profile.d/env.sh
運行一次reset.sh腳本即可
總結:
1、在初始化的配置文件中如果調用某個腳本,如果腳本中是追加,那么每次啟動都會追加一次,導致配置文件內文件多次重復、
2、如果不在初始化配置文件中調用某個腳本,可以編制某個腳本,腳本內將設置內容追加到配置文件內,而且只能運行一次該腳本,否則會重復追加已有內容
3、如果在配置文件中調用腳本,腳本中內容為覆蓋,會導致將配置文件中的調用腳本覆蓋,而且只留腳本中最后一個命令。
4、也可以在.bash_logout設置刪除配置文件的所有內容,然后每次啟動手動運行一次reset腳本
bash如何展開命令行
把命令行分成單個命令詞
展開別名
展開大括號的聲明({}) 例如f{1..10}
展開波浪符聲明(~)
命令替換$() 和 “)
再次把命令行分成命令詞
展開文件通配(*、?、[abc]等等)
準備I/0重導向(<、>)
運行命令
文件查找和壓縮及解壓縮
文件查找
在文件系統上查找符合條件的文件
文件查找:locate, find
非實時查找(數據庫查找):locate
實時查找:find
locate
查詢系統上預建的文件索引數據庫(數據庫不是實時更新,如果剛建的文件,數據庫沒有更新則利用locate找不到,可以手動更新updatedb)
/var/lib/mlocate/mlocate.db
依賴于事先構建的索引
索引的構建是在系統較為空閑時自動進行(周期性任務),管理員手動更新數據庫(updatedb)
索引構建過程需要遍歷整個根文件系統,極消耗資源
工作特點:
查找速度快
模糊查找 locae f1 路徑中包含f1都顯示
非實時查找
搜索的是文件的全路徑,不僅僅是文件名
可能只搜索用戶具備讀取和執行權限的目錄
locate命令
locate KEYWORD
有用的選項
-i 不區分大小寫的搜索
-n N 只列舉前N個匹配項目
-r 使用正則表達式 在/etc/下搜以.conf結尾的文件: locate -r “^/etc/.*[.]conf$”
示例
搜索名稱或路徑中帶有“conf”的文件
locate conf
使用Regex來搜索以“.conf”結尾的文件
locate -r ‘\.conf$’
find
實時查找工具,通過遍歷指定路徑完成文件查找
工作特點:
查找速度慢
精確查找
實時查找
可能只搜索用戶具備讀取和執行權限的目錄
對服務器壓力較大
find 后面先跟路徑,再跟條件及處理動作,find命令自動帶遞歸屬性
語法:
find [OPTION]… [查找路徑] [查找條件] [處理動作]
查找路徑:指定具體目標路徑;默認為當前目錄
查找條件:指定的查找標準,可以文件名、大小、類型、權限等標準進行;
默認為找出指定路徑下的所有文件
處理動作:對符合條件的文件做操作,默認輸出至屏幕
查找條件
指搜索層級 默認是遞歸搜索
-maxdepth level 最大搜索目錄深度,指定目錄為第1級
例如:find /etc/ -maxdepth 2 -name passwd 查找名為passwd的文件在etc下尋找,最大深度為2
-mindepth level 最小搜索目錄深度
例如:find /etc/ -mindepth 2 -name passwd 查找名為passwd的文件在etc下尋找,最小深度為2
例如:find /etc/ -maxdepth 2 -mindepth 2 -name passwd 在etc下第二層目錄內尋找名為passwd的文件
根據文件名和inode查找:
-name “文件名稱”:
find /data -name f1 精確匹配,尋找data目錄下名為f1的文件
find /data -name “*f1*” 模糊匹配,尋找data目錄下名包含f1的文件,模糊匹配必須加雙引號
支持使用glob:*, ?, [], [^]
-iname “文件名稱”:不區分字母大小寫
-inum n 按inode(節點編號)號查找 例如: find /data -inum 30 在/data目錄下尋找節點編號為30的文件
-samefile name 相同inode號的文件 例如:find /data -samefile f1 在data目錄下搜索與f1節點編號相同的文件
-links n 鏈接數為n的文件 例如:find /data -links 2 在data目錄下搜索鏈接數為2的文件
-regex “PATTERN”:以PATTERN匹配整個文件路徑字符串,而不僅僅是文件名稱
例如:find /etc -regex “.*[.]conf$” 查找在etc下的以.conf結尾的文件
查找條件
根據屬主、屬組查找: -ls 是以列表形式顯示
-user USERNAME:查找屬主為指定用戶(UID)的文件
例如:find /home -user liu -ls 在home下查找擁有者為liu的文件并詳細顯示
find /home -user liu -name “*.sh” -ls 在home下查找擁有者為liu并且為.sh結尾的文件,并以列表形式顯示
-group GRPNAME: 查找屬組為指定組(GID)的文件
-uid UserID:查找屬主為指定的UID號的文件
-gid GroupID:查找屬組為指定的GID號的文件
-nouser:查找沒有屬主的文件 find /home -nouser -ls
-nogroup:查找沒有屬組的文件
例如:
find /home -nouser -nogroup -ls 在home下搜索既沒有所有者也沒有所屬組的文件
find /home -nouser -ls -o -nogroup -ls 在home下搜索沒有所有者或者沒有所屬組的文件
等價于find /home \( -nouser -o -nogroup \) -ls
-a 并且的意思,可以省略
查找條件
根據文件類型查找:-type TYPE
f: 普通文件
d: 目錄文件
l: 符號鏈接文件
s:套接字文件
b: 塊設備文件
c: 字符設備文件
p: 管道文件
空文件或目錄:-empty 例如:find /app -type d -empty
例如 find /home -type -d -ls 搜索home下的文件夾并詳細顯示出來(默認遞歸了)
如果我只想搜索home下的文件夾,不想遞歸,則
find /home -type d -maxdepth 1 -ls
查找條件
組合條件:
與:-a
或:-o
非:-not, !
例如:find /home -empty -not -type f -ls 在home下搜索空的但不是普通文件,并詳細顯示
find /home !-empty -type f -ls 非空的并且是普通的文件
德·摩根定律:
(非 A) 或 (非 B) = 非(A 且 B)
(非 A) 且 (非 B) = 非(A 或 B)
示例:
!A -a !B = !(A -o B)
!A -o !B = !(A -a B)
例如
find /home ! -empty ! -type f 非空并且不是普通文件
等價find /home ! \( -empty -o -type f \) find命令中()需要轉義
find -name snow.png 搜索名為snow.png的文件
find -iname snow.png 搜索名忽略大小寫,名為snow.png的文件
find / -name “*.txt” 在/下搜索以.txt結尾的文件
find /var –name “*log*” 在var下搜索路徑包含log的文件
find -user joe -group joe 搜索所有者為joe并且所屬組為joe的文件
find -user joe -not -group joe 搜索所有者為joe,并且所屬組不是Joe的文件
find -user joe -o -user jane 搜索所有者為joe或者所有者為jane的文件
find -not \( -user joe -o -user jane \) 搜索所有者不是Joe并且所有者不是Jane的文件
find / -user joe -o -uid 500 搜索所有者為Joe或者uid為500的人的文件
找出/tmp目錄下,屬主不是root,且文件名不以f開頭的文件
find /tmp \( -not -user root -a -not -name ‘f*’ \) -ls
find /tmp -not \( -user root -o -name ‘f*’ \) –ls
排除目錄
示例:
查找/etc/下,除/etc/sane.d目錄的其它所有.conf后綴的文件
find /etc -path “/etc/sane.d” -a –prune -o -name “*.conf”
查找/etc/下,除/etc/sane.d和/etc/fonts兩個目錄的所有.conf后綴的文件
find /etc \( -path “/etc/sane.d” -o -path “/etc/fonts” \) -a prune -o -name “*.conf”
查找條件
根據文件大小來查找:
-size [+|-]#UNIT
常用單位:k, M, G,c(byte)
#UNIT: (#-1, #]
如:6k 表示(5k,6k]
-#UNIT:[0,#-1]
如:-6k 表示[0,5k]
+#UNIT:(#, ∞ )
如:+6k 表示(6k ,∞ )
查找條件
根據時間戳:
以“天”為單位;
-atime [+|-]#,
#: [#,#+1)
+#: [#+1, ∞ ]
-#: [0,#)
-mtime
-ctime
以“分鐘”為單位:
-amin
-mmin
-cmin
條件查找
根據權限查找:-perm [/|-]MODE
MODE: 精確權限匹配
/MODE:任何一類(u,g,o)對象的權限中只要能一位匹配即可,或關系,+從centos7開始淘汰
如:find -perm /666 -ls 搜索(u,g,o)只要有一個滿足6就可以
-MODE:每一類對象都必須同時擁有指定權限,與關系
如:find -perm -666 -ls 表示所有者包含6權限,并且所屬組包含6權限,并且other包含6權限,包含即可,并不是精確匹配,如果有文件的權限是777也能搜索出來
666的意思是
110 110 110 是1就檢查,0表示不關心,不檢查
find -perm 755 會匹配權限模式恰好是755的文件
只要當任意人有寫權限時,find -perm +222就會匹配
只有當每個人都有寫權限時,find -perm -222才會匹配
只有當其它人(other)有寫權限時,find -perm -002才會匹配
處理動作
-print:默認的處理動作,顯示至屏幕
-ls:類似于對查找到的文件執行“ls -l”命令
-delete:刪除查找到的文件
-fls file:查找到的所有文件的長格式信息保存至指定文件中
find -perm /222 -fls /root/f2.log 將搜索出來的信息存放在f2.log文件內
-ok COMMAND {} \; 對查找到的每個文件執行由 COMMAND 指定的命令,對于每個文件執行命令之前,都會交互式要求用戶確認
-exec COMMAND {} \; 對查找到的每個文件執行由COMMAND指定的命令,即批量處理
{}: 用于引用查找到的文件名稱自身
find傳遞查找到的文件至后面指定的命令時,查找到所有符合條件的文件一次性傳遞給后面的命令
find -name “f*” -ok rm {} \; rm與find命令配合,{}代表前面搜索出來的內容,帶ok選項必須以\;結尾
意思是搜索以f開頭的文件并刪除,且刪除時要求用戶確認,輸入y刪除
find -name “f*” -exec rm {} \; 批量執行刪除命令不再詢問
find -name “f*” -ok mv {} /mnt/ \; 將搜索出來的文件移動到mnt文件夾內
find -name “f*” -ok mv {} {}.bak \; 將搜索出來的文件改名為.bak后綴
find -name “f*” -ok cp {} /data/{}.org \; 將搜索出來的文件復制到data目錄下并改名為.org后綴
參數替換xargs
由于很多命令不支持管道|來傳遞參數,而日常工作中有這個必要,所以就有了
xargs命令
xargs用于產生某個命令的參數,xargs 可以讀入 stdin 的數據,并且以空格符
或回車符將 stdin 的數據分隔成為arguments
注意:文件名或者是其他意義的名詞內含有空格符的情況
有些命令不能接受過多參數,命令執行可能會失敗,xargs可以解決
示例:
ls f* |xargs rm
find /sbin -perm +700 |ls -l 這個命令是錯誤的
find /sbin -perm +7000 | xargs ls –l
find和xargs格式:find | xargs COMMAND
echo f{1..10000000} | xargs -n 100 touch -n 100的意思是每100個為一行傳給touch
echo f{1..10000000} | xargs -n 100 rm -f
find示例
備份配置文件,添加.orig這個擴展名
find -name “*.conf” -exec cp {} {}.orig \;
提示刪除存在時間超過3天以上的joe的臨時文件
find /tmp -ctime +3 -user joe -ok rm {} \;
在家目錄中尋找可被其它用戶寫入的文件并將寫權限去掉
find ~ -perm -002 -exec chmod o-w {} \;
查找/data下的權限為644,后綴為sh的普通文件,增加執行權限
find /data –type f -perm 644 -name “*.sh” –exec chmod 755 {} \;
查看/home的目錄
find /home –type d -ls
壓縮、解壓縮及歸檔工具(解壓縮對后綴要求很嚴)
file-roller 在圖形界面terminal內輸入file-roller,是圖形化的壓縮解壓縮
compress/uncompress: .Z
gzip/gunzip: .gz
bzip2/bunzip2: .bz2
xz/unxz: .xz
zip/unzip
tar
cpio
壓縮:壓縮的是文件,可以一次壓縮多個文件,但是壓縮結果也是多個,不會打包成一個文件
compress/uncompress
compress [-dfvcVr] [-b maxbits] [file …] 默認不僅壓縮而且還會把原文件刪除
-d: 解壓縮,相當于uncompress
-c: 結果輸出至標準輸出,不刪除原文件 (即壓縮完后并沒有放到文件里面,而是在屏幕顯示)
compress -c f1 > f1.Z 相當于壓縮,但會保留原文件
-v: 顯示詳情
uncompress 解壓縮
zcat file.Z >file 使用zcat解壓縮,然后重定向到文件里
gzip/gunzip
gzip [OPTION]… FILE … 默認不僅壓縮而且還會把原文件刪除
-d: 解壓縮,相當于gunzip
-c: 將壓縮或解壓縮的結果輸出至標準輸出(即壓縮完后并沒有放到文件里面,而是在屏幕顯示)
gzip -c f1 > f1.gz 相當于壓縮,但會保留原文件
-#:1-9,指定壓縮比,值越大壓縮比越大
zcat:不顯式解壓縮的前提下查看文本文件內容
實例:
gzip -c messages >messages.gz
gzip -c -d messages.gz > messages
zcat messages.gz > messages
bzip2/bunzip2/bzcat 默認不僅壓縮而且還會把原文件刪除
bzip2 [OPTION]… FILE …
-k: keep, 保留原文件
-d:解壓縮
-#:1-9,壓縮比,默認為9
bzcat:不顯式解壓縮的前提下查看文本文件內容
bzcat f1.bz2 > f1
xz/unxz/xzcat
xz [OPTION]… FILE …
-k: keep, 保留原文件
-d:解壓縮
-#:1-9,壓縮比,默認為6
xzcat: 不顯式解壓縮的前提下查看文本文件內容
zip/unzip
打包壓縮
zip –r /testdir/sysconfig /etc/sysconfig/ 把后面的文件夾壓縮到前面的文件內
zip m.zip mmm 將mmm文件壓縮到m.zip內 文件不用r,文件夾用r
解包解壓縮
unzip sysconfig.zip
cat /var/log/messages | zip messages –
unzip -p message > message
壓縮能力排比:.xz>.bz2>.gz>.zip>.Z
tar工具
tar(Tape ARchive,磁帶歸檔的縮寫)
tar [OPTION]…
(1) 創建歸檔
tar -cpvf /PATH/TO/SOMEFILE.tar FILE… 將后面的多個文件打包到/PATH/TO/SOMEFILE.tar里去
-c:打包 -f:打包到哪個文件里 -v:看到過程 -p:保留原有屬性
(2) 追加文件至歸檔: 注:不支持對壓縮文件追加
tar -r -f /PATH/TO/SOMEFILE.tar FILE… 將FILE文件追加到歸檔文件內
(3) 查看歸檔文件中的文件列表
tar -t -f /PATH/TO/SOMEFILE.tar
(4) 展開歸檔
tar -x -f /PATH/TO/SOMEFILE.tar 默認在當前目錄下解包解包
tar -x -f /PATH/TO/SOMEFILE.tar -C /PATH/ 解包到指定/PATH/目錄內,跟-C選項
(5) 結合壓縮工具實現:歸檔并壓縮
-j: bzip2, -z: gzip, -J: xz
tar -zcpvf data.tar.gz /data 將/data目錄打包并壓縮為 data.tar.gz
tar -xvf data.tar.gz -C /mnt 將data.tar.gz 解壓到/mnt下
-T選項指定輸入文件,-X選項指定包含要排除的文件列表
tar -zcvf mybackup.tgz -T /root/includefilelist -X /root/excludefilelist
分割大的 tar 文件為多份小文件:
split –b Size –d tar-file-name prefix-name
split -b 1M –d mybackup.tgz mybackup-parts 將mybackup.tgz文件切割成每個大小為1M的,每個小文件的前綴名稱為mybackup-parts,后綴為數字。-d代表數字,不加-d則后綴為英文字母
split -b 1M mybackup.tgz mybackup-parts
合并:cat mybackup-parts* > mybackup.tar.gz
例如:
vim list.txt
/etc/
/boot/
vim exlist.txt
/etc/shadow
/boot/initramfs
tar -Jcpvf list.tar.xz -T list.txt -X exlist.txt 打包打包文件列表中的文件,但是排除掉排除打包列表中的文件,打包并壓縮為list.tar.xz
例如:
tar -tf data.tar
data/
data/.log
data/.f2.swp
data/test.txt
data/.fstab.swp
data/.f1.swp
data/dir1/
data/48_scp.sh
data/f1
tar -tvf data.tar
drwxr-xr-x root/root 0 2018-04-12 16:32 data/
-rw-r–r– root/root 0 2018-03-31 11:54 data/.log
-rw-r–r– root/root 12288 2018-04-07 16:54 data/.f2.swp
-rw-r–r– root/root 10 2018-04-07 17:20 data/test.txt
-rw-r–r– root/root 12288 2018-04-07 18:00 data/.fstab.swp
-rw-r–r– root/root 12288 2018-04-07 18:53 data/.f1.swp
drwxr-xr-x root/root 0 2018-04-08 16:32 data/dir1/
-rwxr-xr-x root/root 93 2018-04-09 11:55 data/48_scp.sh
-rw-r–r– root/root 0 2018-04-12 16:32 data/f1
du -sh /root 查看大小
cpio
功能:復制文件從或到歸檔
cpio命令是通過重定向的方式將文件進行打包備份,還原恢復的工具,它可以
解壓以“.cpio”或者“.tar”結尾的文件
cpio [選項] > 文件名或者設備名
cpio [選項] < 文件名或者設備名
選項
-o 將文件拷貝打包成文件或者將文件輸出到設備上
-i 解包,將打包文件解壓或將設備上的備份還原到系統
-t 預覽,查看文件內容或者輸出到設備上的文件內容
-v 顯示打包過程中的文件名稱。
-d 解包生成目錄,在cpio還原時,自動的建立目錄
-c 一種較新的存儲方式
例如:
將etc目錄備份:
find /etc -print |cpio -ov >etc.cpio -print可有可無
內容預覽
cpio –tv < etc.cpio
解包文件
cpio –idv < etc.cpio 打包的時候如果帶絕對路徑那么解包就解到原來路徑
文本處理工具sed
Stream EDitor, 行編輯器
sed是一種流編輯器,它一次處理一行內容。處理時,把當前處理的行存儲在臨時
緩沖區中,稱為“模式空間”(pattern space),接著用sed命令處理緩沖區中的
內容,處理完成后,把緩沖區的內容送往屏幕。然后讀入下行,執行下一個循環。
如果沒有使諸如‘D’的特殊命令,那會在兩個循環之間清空模式空間,但不會清
空保留空間。這樣不斷重復,直到文件末尾。文件內容并沒有改變,除非你使用重
定向存儲輸出。
功能:主要用來自動編輯一個或多個文件,簡化對文件的反復操作,編寫轉換程序等
參考: http://www.gnu.org/software/sed/manual/sed.html
sed工具
用法:
sed [option]… ‘script’ inputfile… 默認自動打印到屏幕上
常用選項:
-n:不輸出模式空間內容到屏幕,即不自動打印
-e: 多點編輯(即操作多次) 例如:sed -n -e ‘2p’ -e ‘6p’ f1 顯示f1中第二行和第六行
-f:/PATH/SCRIPT_FILE : 從指定文件中讀取編輯腳本
例如:cat > sedscript.txt
2~2p
sed -n -f sedscript.txt f1 相當于把”中的條件放到文件中,從文件中調取
-r: 支持使用擴展正則表達式(默認支持基本正則表達式)
-i.bak: 備份文件并原處編輯
script:’地址命令’
sed工具
地址定界:
(1) 不給地址:對全文進行處理
(2) 單地址:
#: 指定的行,$:最后一行
/pattern/:被此處模式所能夠匹配到的每一行
(3) 地址范圍:
#,# 10,20 從第10行到第20行
#,+# 10,+15 從第10行到第25行
/pat1/,/pat2/ 從滿足pat1的行開始到滿足pat2的行結束
#,/pat1/ 從第#行開始到滿足pat1的行結束
(4) ~:步進
1~2 奇數行 sed -n ‘1~2p’ f1 顯示f1文件中的奇數行
2~2 偶數行 sed -n ‘2~2p’ f1 顯示f1文件中的偶數行
編輯命令:
d: 刪除模式空間匹配的行,并立即啟用下一輪循環 例如:sed ‘2d’ f1 將f1中的第二行刪除
p:打印當前模式空間內容,追加到默認輸出之后
a [\]text:在指定行后面追加文本(實際并沒有追加,只是顯示出來而已,想真正追加配合i.bak選項) sed ‘2,5a===’ f1 在第二行到第五行后面追加===
支持使用\n實現多行追加
i [\]text:在行前面插入文本 \表示開始的意思,\線后面全是追加的內容
c [\]text:替換行為單行或多行文本
w /path/somefile: 保存模式匹配的行至指定文件
r /path/somefile:讀取指定文件的文本至模式空間中匹配到的行后
=: 為模式空間中的行打印行號 例如:sed -n ‘/root/=’ /etc/passwd 將匹配到的行號顯示出來
!:模式空間中匹配行取反處理 例如:sed ‘2!d’ f1 將f1中的除了第二行都刪了
例如:seq 5 > f1
cat f1
1
2
3
4
5
sed ‘2p’ f1
1
2
2
3
4
5
sed -n ‘2p’ f1
2
ifconfig ens33 | sed -n ‘2p’
inet 192.168.30.142 netmask 255.255.255.0 broadcast 192.168.30.255
在/etc/passwd下搜索包括root的行并顯示
sed -n ‘/root/p’ /etc/passwd
在/etc/passwd下搜索以root開頭的行
sed -n ‘/^root/p’ /etc/passwd
在/etc/passwd中搜索以b開頭為開始到以f開頭的行結束
sed -n ‘/^b/,/^f/p’ /etc/passwd
例如:sed ‘2,5a===’ f1 在第二行到第五行后面追加===
1
2
===
3
===
4
===
5
===
例如:在.bashrc里面追加一個別名
sed ‘/aliases/aalias p=poweroff’ ./.bashrc(并沒有真正追加,只是顯示出來而已,想實現真正追加需要配合i.bak選項)
sed -i.bak ‘/aliases/aalias p=poweroff’ .bashrc(真正追加,并且將原文件備份為.bak后綴的文件)
sed -i.bak2 ‘/aliases/aalias cdnet=”cd /etc/sysconfig/network-scripts/”‘ .bashrc
如果我想在f1文件內第2到第5行后面加空格,如何實現?(在a后面加個\線,\線表示開始,后面全是加的東西)
sed ‘2,5a\ ===’ f1
1
2
===
3
===
4
===
5
===
如果我想在f1文件內第2到第5行前面加空格,如何實現?(在i后面加個\線,\線表示開始,后面全是加的東西)
sed ‘2,5i\ —‘ f1
1
—
2
—
3
—
4
—
5
如果我想在f1文件內將第2到第4行替換為空格,如何實現?(在c后面加個\線,\線表示開始,后面全是加的東西)
sed ‘2,5c\ —‘ f1
1
—
5
sed ‘2,5w f2’ f1 將f1文件中滿足第2到第5行條件的存到f2文件中
cat f2
2
3
4
5
sed ‘2,5r /etc/issue’ f1 將issue文件中的內容讀入到f1文件的第二行到第五行的后面 并沒有真正追加,若想真正追加則使用-i.bak.選項
1
2
\S
Kernel \r on an \m
3
\S
Kernel \r on an \m
4
\S
Kernel \r on an \m
5
\S
Kernel \r on an \m
延伸:將別名放到一個文件里,利用sed ‘r’ 就可以一次性讀入
sed工具
s///:查找替換,支持使用其它分隔符,s@@@,s###
替換標記:
g: 行內全局替換
p: 顯示替換成功的行
w /PATH/TO/SOMEFILE :將替換成功的行保存至文件中
例如:
sed ‘s/root/administrator/’ /etc/passwd 將passwd文件中的第一個root替換為administrator
未加地址表示全文搜索,并沒有真正替換,沒有加-i.bak選項,只是顯示下
sed ‘s/root/administrator/g’ /etc/passwd 將passwd文件中所有root替換為administrator
例如:
sed -r ‘s/(root)/\1er/g’ /etc/passwd 將passwd文件中所有的root替換為rooter
-r 支持擴展的正則表達式
sed -r ‘s/(root)/admini\1/g’ /etc/passwd 將passwd文件中所有的root替換為adminiroot
sed -r ‘s@(GRUB_CMDLINE_LINUX.*)(“)$@\1 xyz\2@g’ /etc/default/grub 在grub文件中在”前面加上空格xyz
或者sed -r ‘/GRUB_CMDLINE_LINUX/s/(.*)”$/\1 xyz”/g’ /etc/default/grub /GRUB_CMDLINE_LINUX為搜索條件
或者sed -r ‘/GRUB_CMDLINE_LINUX/s/”$/ xyz”/g’ /etc/default/grub
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR=”$(sed ‘s, release .*$,,g’ /etc/system-release)”
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT=”console”
GRUB_CMDLINE_LINUX=”crashkernel=auto rhgb quiet xyz”
GRUB_DISABLE_RECOVERY=”true”
利用sed命令取centos7網卡地址
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.30.142 netmask 255.255.255.0 broadcast 192.168.30.255
inet6 fe80::175d:f288:288e:96d2 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:69:a0:d0 txqueuelen 1000 (Ethernet)
RX packets 3390 bytes 310820 (303.5 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 2243 bytes 324571 (316.9 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
答:ifconfig ens33 | sed -n ‘2p’ | sed -r ‘s/.*inet (.*) net.*/\1/g’
或者ifconfig ens33 | sed -n ‘2p’ | sed -r ‘s/(.*inet )(.*)( net.*)/\2/g’
或者ifconfig ens33 | sed -r ‘2!d;s/(.*inet )(.*)( net.*)/\2/g’ 除了第二行都刪掉,取地址
或者ifconfig ens33 | sed -n ‘2p’ | sed ‘s/.*inet //’ | sed ‘s/ netmask.*//’
或者ifconfig ens33 | sed -n ‘2p’ | sed -e ‘s/.*inet //’ -e ‘s/ netmask.*//’
將/etc/httpd/conf/httpd.conf文件中的第990行和1003到1009行的#刪除
cat -n /etc/httpd/conf/httpd.conf | sed -r ‘1003,1009s/#//g’ | sed -r ‘990s/#//g’
cat -n /etc/httpd/conf/httpd.conf | sed -n -e ‘990p’ -e ‘1003,1009p’ | sed ‘s/.*#//g’
cat -n /etc/httpd/conf/httpd.conf | sed -e ‘990,1009!d’ -e ‘991,1002d’| sed ‘s/.*#//g’
cat -n /etc/httpd/conf/httpd.conf | sed ‘990,1009!d’ | sed ‘2,13d’ | sed -r ‘s/.*#//g’ ‘2,13d’代表從管道左側傳過來的第2行到第13行刪除
取/etc/sysconfig/network/的基名和目錄名
echo “/etc/sysconfig/network/” | sed -r ‘s/(.*\/)([^/].*\/?$)/\1/g’
echo “/etc/sysconfig/network/” | sed -r ‘s/(.*\/)([^/].*\/?$)/\2/g’
示例
sed ‘2p’ /etc/passwd
sed –n ‘2p’ /etc/passwd 只打印第二行
sed –n ‘1,4p’ /etc/passwd 打印1到4行
sed –n ‘/root/p’ /etc/passwd 打印包含root的行
sed –n ‘2,/root/p’ /etc/passwd 打印從2行開始到包含root的行結束
sed -n ‘/^$/=’ file 顯示空行行號
sed –n –e ‘/^$/p’ –e ‘/^$/=’ file 空行顯示并且顯示空行行號
sed ‘/root/a\superman’ /etc/passwd 行后追加\superman
sed ‘/root/i\superman’ /etc/passwd 行前追加\superman
sed ‘/root/c\superman’ /etc/passwd 代替行
sed ‘/^$/d’ file 刪除空行
sed ‘1,10d’ file 刪除1到10行
cat /etc/passwd | sed ‘2,5d’ 刪除2到5行
cat /etc/passwd | sed ‘2a tea’在第二行后面追加tea
sed ‘s/test/mytest/g’ example 將全文中的test替換為mytest
sed –n ‘s/root/&superman/p’ /etc/passwd 單詞后
sed –n ‘s/root/superman&/p’ /etc/passwd 單詞前
sed -e ‘s/dog/cat/’ -e ‘s/hi/lo/’ pets 多點替換
sed –i.bak ‘s/dog/cat/g’ pets 改了并備份
本文來自投稿,不代表Linux運維部落立場,如若轉載,請注明出處:http://www.www58058.com/96013