一、shell編程(四)
1、循環特殊用法
while 循環的特殊用法(遍歷文件的每一行):
while read line; do 循環體 done < /PATH/FROM/SOMEFILE 依次讀取/PATH/FROM/SOMEFILE文件中的每一行,且將行賦值給變量line
雙小括號方法,即((…))格式,也可以用于算術運算
雙小括號方法也可以使bash Shell 實現C語言風格的變量操作 #I=10 #((I++))
for 循環的特殊格式:
for ((控制變量初始化;條件判斷表達式;控制變量的修正表達式))do 循環體done控制變量初始化:僅在運行到循環代碼段時執行一次 控制變量的修正表達式:每輪循環結束會先進行控制變量修正運算,而后再做條件判斷
select 循環與菜單
select: select NAME [in WORDS ... ;] do COMMANDS; done select variable in list do 循環體命令 doneselect 循環主要用于創建菜單,按數字順序排列的示菜單項將顯示在標準錯誤上,并顯示PS3提示符,等待用戶輸入 PS3="would you like ?"用戶輸入菜單列表中的某個數字,執行相應的命令 用戶輸入被保存在內置變量 REPLY 中。 注意:select循環為死循環 [root@6 cd]# select name in a b c d;do echo "you choose is $name"; done 1) a 2) b 3) c 4) d #? 3 you choose is c #? 2 you choose is b #? [root@6 bin]#PS3="would you like ?" [root@6 bin]# select name in a b c d;do echo "you choose is $name"; done 1) a 2) b 3) c 4) d would you like ?2 you choose is b
select與case
select 用是個無限循環,因此要記住用 break 命令退用出循環,或用 exit 按 命令終止腳本。也可以按 ctrl+c退出循環。
break #和continue #;
break #:退出#層循環continue #:跳過#次循環 select和經常和case聯合使用 與 for循環類似,可以省略 in list,此時使用位置參量 #! /bin/bash PS3="would you like ?"select choose in a b c d;do case $choose in a) echo "THIS IS A PART." ;; b) echo "THIS IS B PART." ;; c) echo "THIS IS C PART." ;; d) echo "THIS IS D PART." ;; *) break ;; esacdone
2、函數介紹
函數function是由若干條shell命令組成的語句塊,實現代碼重用和模塊化編程。 優先級:alias》函數》內部命令》外部命令 它與shell程序形式上是相似的,不同的是它不是一個單獨的進程,不能獨立運行,而是shell 程序的一部分。 函數和shell程序比較相似,區別在于:Shell 程序在子Shell中運行 而Shell函數在當前Shell中運行。因此在當前Shell 中,函數可以對shell 中變量進行修改
定義函數
函數由兩部分組成:函數名和函數體。 語法一: function f_name { ... 函數體... } 語法二: function f_name() { ... 函數體... } 語法三: f_name (){ ... 函數體... }
函數使用
函數的定義和使用: 可在交互式環境下定義函數 可將函數放在腳本文件中作為它的一部分 可放在只包含函數的單獨文件中 調用:函數只有被調用才會執行; 調用:給定函數名 函數名出現的地方,會被自動替換為函數代碼 函數的生命周期:被調用時創建,返回時終止
函數返回值
函數有兩種返回值: 函數的執行結果返回值: (1)使用echo 或printf 命令進行輸出 (2) 函數體中調用命令的輸出結果 函數的退出狀態碼: (1)默認取決于函數中執行的最后一條命令的退出狀態碼 (2)自定義退出狀態碼, 其格式為: return 從函數中返回,用最后狀態命令決定返回值 return 0 無錯誤返回。 return 1-255 有錯誤 返回
交互式環境下定義和使用函數
示例: $dir() { > ls -l > } 定義該函數后,若在$ 后面鍵入dir ,其顯示結果同ls -l的作用相同。 $dir該dir函數將一直保留到用戶從系統退出,或執行了如下所示的unset 命令: $ unset dir
在腳本中定義及使用函數
函數在使用前必須定義,因此應將函數定義放在腳本開始部分,直至shell 首次發現它后才能使用 調用函數僅使用其函數名即可。 示例: $cat func1 #!/bin/bash # func1 hello() { echo "Hello there today's date is `date +%F`" } echo "now going to the function hello" hello echo "back from the function"
使用函數文件
可以將經常使用的函數存入函數文件,然后將函數文件載入shell。 文件名可任意選取,但最好與相關任務有某種聯系。例如:functions.main 一旦函數文件載入shell,就可以在命令行或腳本中調用函數??梢允褂胹et 命令查看所有定義的函數,其輸出列表包括已經載入shell的所有函數。 若要改動函數,首先用unset 命令從shell中刪除函數。改動完畢后,再重新載入此文件。
創建函數文件
函數文件示例: $cat functions.main #!/bin/bash #functions.main findit() { if [ $# -lt 1 ] ; then echo "Usage:findit file" return 1 fi find / -name $1 –print }
載入函數
函數文件已創建好后,要將它載入shell 定位 函數文件 并載入shell 的格式: . filename 或 source filename 注意:此即< 點> < 空格> < 文件名>這里 的文件名要帶正確路徑 示例:上例中的函數,可使用 如下命令: $ . functions.main
檢查載入函數
使用set命令檢查函數是否已載入。set 命令將在shell中顯示所有的載入函數 。 示例: $set findit=( ) { if [ $# -lt 1 ]; then echo "usage :findit file"; return 1 fi find / -name $1 -print } …
執行shell 函數
要執行函數,簡單地鍵入函數名即可 : 示例: $findit groups /usr/bin/groups /usr/local/backups/groups.bak
刪除shell函數
現在對函數做一些改動。首先刪除函數,使其對shell 不可用。使用unset 命令完成此 功能. 命令格式為:unset function_name 實例:$unset findit 再鍵入set 命令,函數將不再 顯示
函數參數
函數可以接受參數: 傳遞參數給函數:調用函數時,在函數名后面以空白分隔給定參數列表即可;例如“testfunc arg1 arg2 ...” 在函數體中當中,可使用$1, $2, ...調用這些參數;還可以使用$@, $*, $# 等特殊變量
函數變量
變量作用域: 環境變量:當前shell和子shell 有效 本地變量:只在當前shell進程有效,為執行腳本會啟動專用子shell進程;因此,本地變量的作用范圍是當前shell腳本程序文件,包括腳本中的函數。 局部變量:函數的生命周期;函數結束時變量被自動 銷毀 注意:如果函數中有局部變量,如果其名稱同本地變量, 使用局部變量。 在函數中定義局部變量的方法 local NAME=VALUE
函數遞歸實例
函數遞歸: 函數直接或間接調用自身 注意遞歸層數 遞歸實例: 階乘是基斯頓·于 卡曼于 1808 年發明的運算符號,是數學術語 一個正整數的階乘(factorial)是所有小于及等于該數的正整數的積,并且有0 的階乘為1 。自然數n 的階乘寫作n!。 。 n!=1 ×2 ×3 ×... ×n。 。 階乘亦可以遞歸方式定義:0!=1 ,n!=(n-1)! ×n。 。 n!=n(n-1)(n-2)...1 n(n-1)! = n(n-1)(n-2)!
函數 遞歸示例
示例: fact.sh#!/bin/bash#fact() { if [ $1 -eq 0 -o $1 -eq 1 ]; thenecho 1 elseecho $[$1*$(fact $[$1-1])]fi} fact $1
二、軟件包管理(二)
包查詢
rpm {-q|--query} [select-options] [query-options] [select-options] -a: 所有包-f: 查看指定的文件由哪個程序包安裝生成[root@6 yum.repos.d]# rpm -qf /bin/rpmrpm-4.8.0-55.el6.x86_64 -p rpmfile(包名):針對尚未安裝的程序包文件做查詢操作; [root@6 cd]# rpm -qp /misc/cd/Packages/tree-1.5.3-3.el6.x86_64.rpm tree-1.5.3-3.el6.x86_64 --whatprovides CAPABILITY :查詢指定的 CAPABILITY由哪個包所提供 [root@6 cd]# rpm -q --whatprovides rpm rpm-4.8.0-55.el6.x86_64 --whatrequires CAPABILITY :查詢指定的 CAPABILITY 被哪個包所依賴 [root@6 cd]# rpm -q --whatrequires rpm rpm-libs-4.8.0-55.el6.x86_64 man-1.6f-32.el6.x86_64 rpm-python-4.8.0-55.el6.x86_64 yum-3.2.29-73.el6.centos.noarch policycoreutils-2.0.83-29.el6.x86_64 python-meh-0.12.1-3.el6.noarch rpm2cpio 包文件|cpio –itv 預覽包內文件 rpm2cpio 包文件|cpio –id “*.conf” ” 釋放包內文件 [root@6 cd]# rpm2cpio /misc/cd/Packages/rpm-4.8.0-55.el6.x86_64.rpm |cpio -id /bin/rpm ##恢復刪除的文件 [query-options] --changelog :查詢rpm包的changelog-c: 查詢程序的配置文件-d: 查詢程序的文檔-i: information-l: 查看指定的程序包安裝后生成的所有文件;--scripts :程序包自帶的腳本片斷-R:查詢指定的程序包所依賴的CAPABILITY; --provides:列出指定程序包所提供的CAPABILITY; 查詢用法: -qi PACKAGE, -qf FILE, -qc PACKAGE, -ql PACKAGE, -qd PACKAGE -qpi PACKAGE_FILE, -qpl PACKAGE_FILE,... -qa 卸載: rpm {-e|--erase} [--allmatches] [--nodeps] [--noscripts] [--notriggers] [--test] PACKAGE_NAME ... rpm {-V|--verify} [select-options] [verify-options] S file Size differs M Mode differs (includes permissions and file type) 5 digest (formerly MD5 sum) differs D Device major/minor number mismatch L readLink(2) path mismatch U User ownership differs G Group ownership differs T mTime differs P capabilities differ
包校驗
包來源合法性驗正及完整性驗正: 完整性驗正:SHA256 來源合法性驗正:RSA 公鑰加密: 對稱加密:加密、解密使用同一密鑰; 非對稱加密:密鑰是成對兒的 public key: 公鑰,公開所有人 secret key: 私鑰, 不能公開 導入所需要公鑰: rpm -K|checksig rpmfile 檢查包的完整性和簽名 [root@6 cd]# rpm -K /misc/cd/Packages/tree-1.5.3-3.el6.x86_64.rpm /misc/cd/Packages/tree-1.5.3-3.el6.x86_64.rpm: rsa sha1 (md5) pgp md5 OK rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 ##導入key文件 CentOS 7 發行版光盤提供: RPM-GPG-KEY-CentOS-7 rpm -qa gpg-pubkey*
rpm數據庫
數據庫重建: /var/lib/rpmrpm {--initdb|--rebuilddb} initdb: 初始化 如果事先不存在數據庫,則新建之 否則,不執行任何操作 rebuilddb :重建 無論當前存在與否,直接重新創建數據庫
yum
CentOS: yum, dnfYUM: Yellowdog Update Modifier,rpm的前端程序,用來解決軟件包相關依賴性,可以在多個庫之間定位軟件包,up2date 的替代工具 yum repository: yum repo ,存儲了眾多rpm 包,以及包的相關的元數據文件(放置于特定目錄repodata 下) 文件服務器: ftp:// http:// file:///
yum 配置文件
yum 客戶端配置文件: /etc/yum.conf :為所有倉庫提供公共配置 /etc/yum.repos.d/*.repo :為倉庫的指向提供配置 倉庫指向的定義: [repositoryID] name=Some name for this repository baseurl=url://path/to/repository/ enabled={1|0} gpgcheck={1|0} gpgkey=URL enablegroups={1|0} failovermethod={roundrobin|priority} 默認為:roundrobin ,意為隨機挑選; cost= 默認為1000repo 文件范例 /etc/yum.repo.d/ [base] name=centos 7 baseurl=http://10.1.0.1/cobbler/ks_mirror/7/ gpgcheck=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentosOS-7 enabled=1
教學環境yum源
教室里的yum源:http://172.16.0.1/cobbler/ks_mirror/CentOS-X-x86_64/CentOS epel:http://172.16.0.1/fedora-epel/7/x86_64/yum 命令的用法: yum [options] [command] [package ...]
yum-config-manager
生成172.16.0.1_cobbler_ks_mirror_CentOS-X-x86_64_.repo yum-config-manager --add-repo=http://172.16.0.1/cobbler/ks_mirror/CentOS-X -x86_64/ yum-config-manager --disable “ 倉庫名" 禁用倉庫yum-config-manager --enable “ 倉庫名” 啟用倉庫
yum
顯示倉庫列表: repolist [all|enabled|disabled]顯示程序包: list # yum list [all | glob_exp1] [glob_exp2] [...] # yum list {available|installed|updates} [glob_exp1] [...]安裝程序包: install package1 [package2] [...] reinstall package1 [package2] [...] (重新安裝) 升級程序包: update [package1] [package2] [...] downgrade package1 [package2] [...] ( 降級) 檢查可用升級: check-update 卸載程序包: remove | erase package1 [package2] [...]查看程序包information: info [...]查看指定的特性( 可以是某文件) 是由哪個程序包所提供: provides | whatprovides feature1 [feature2] [...]清理本地緩存: clean [ packages | metadata | expire-cache |rpmdb | plugins | all ]構建緩存: makecache 搜索:search string1 [string2] [...] 以指定的關鍵字搜索程序包名及summary 信息 查看指定包所依賴的capabilities: deplist package1 [package2] [...]查看yum事務歷史: history [info|list|packages-list|packages-info| summary|addon-info|redo|undo| rollback|new|sync|stats] yum history yum history info 6 yum history undo 6 日志:/var/log/yum.log
積累應用
1 、寫 一個服務腳本/root/bin/testsrv.sh ,完成如下要求
(1) 腳本可接受參數:start, stop, restart, status
(2) 如果參數非此四者之一,提示使用格式后報錯退出
(3) 如是start:則創建/var/lock/subsys/ SCRIPT_NAME , 并顯示“啟動成功”考慮:如果事先已經啟動過一次,該如何處理?
(4) 如是stop:則刪除/var/lock/subsys/ SCRIPT_NAME , 并顯示“停止完成”考慮:如果事先已然停止過了,該如何處理?
(5) 如是restart ,則先stop, 再start考慮:如果本來沒有start ,如何處理?
(6) 如是status, 則如果/var/lock/subsys/ SCRIPT_NAME 文件存在,則顯示“ SCRIPT_NAME is running…”如果/var/lock/subsys/ SCRIPT_NAME 文件不存在,則顯示“ SCRIPT_NAMEis stopped…”其中: SCRIPT_NAME 為當前腳 本名
###函數 #! /bin/bash servername=SCRIPT_NAME START () { touch /var/lock/subsys/$servername echo "$servername已啟動." } STOP() { rm -f /var/lock/subsys/$servername echo "$servername已停止." }
###程序 #! /bin/bash #author:lvasu #description: #version:0.1 #date: source agrement PS3="請選擇參數:" servername=SCRIPT_NAME file=/var/lock/subsys/ $servername select agre in start stop restart status; do case $agre in start) if [ -f $file ];then echo "$servername已開啟,不需要啟動." else START fi ;; stop) if [ -f $file ];then STOP else echo "$servername未開啟,不需要關閉." fi ;; status) if [ -f $file ];then echo "$servername is running...." else echo "$servername is stopped..." fi ;; restart) if [ -f $file ];then echo "$servername已開啟,重啟中." STOP &> /dev/null START else echo "$servername 未啟動,啟動中." START fi ;; *) echo "你輸入的不合法." break ;; esac done
###執行效果 [root@6 bin]# ./testsrv.sh 1) start 2) stop 3) restart 4) status 請選擇參數:1 SCRIPT_NAME已啟動. 請選擇參數:2 SCRIPT_NAME已停止. 請選擇參數:3 SCRIPT_NAME 未啟動,啟動中. SCRIPT_NAME已啟動. 請選擇參數:4 SCRIPT_NAME is running....
2 、編寫一個腳本/root/bin/copycmd.sh
(1) 提示用戶輸入一個可執行命令名稱;
(2) 獲取此命令所依賴到的所有庫文件列表
(3) 復制命令至某目標目錄( 例如/mnt/sysroot) 下的對應路徑下;
如:/bin/bash ==> /mnt/sysroot/bin/bash
/usr/bin/passwd ==> /mnt/sysroot/usr/bin/passwd
(4) 復制此命令依賴到的所有庫文件至目標目錄下的對應路徑下:
如:/lib64/ld-linux-x86-64.so.2 ==> /mnt/sysroot/lib64/ld-
linux-x86-64.so.2
(5)每次復制完成一個命令后,不要退出,而是提示用戶鍵入新的要復制的命
令,并重復完成上述功能;直到用戶輸入quit 退出
###程序 #! /bin/bash #author:lvasu #description: #version:0.1 #date: while true;do read -p "請輸入一個可執行的命令" cmd addr=/mnt/sysroot case $cmd in quit) exit ;; *) type $cmd &> /dev/null if [ $? -eq 0 ];then which $cmd &> /dev/null if [ $? -eq 0 ];then path=$(which $cmd | sed -rn "/\/.*\/$cmd/p") else path=/bin/bash fi else echo "請輸入正確的命令." continue fi echo "復制命令的路徑:" echo $path echo '==============================' files=$(ldd $path| grep -o '/.*.so.[1-9]') echo "$path的庫文件:" echo "$files" | tee -a /testdir/file echo '==============================' line=$(echo "$files" |wc -l) commen1=$(echo $path | sed -nr 's@(^/.*/)[^/]+/?$@\1@p') mkdir -p $addr$commen1 &> /dev/null cp -a $path $addr$path &> /dev/null echo "$addr$path復制成功." echo '==============================' while read n;do commen2=$(echo $n|sed -nr 's@(^/.*/)[^/]+/?$@\1@p') mkdir -p $addr$commen2 &> /dev/null cp -a $n $addr$commen2 &> /dev/null echo "$addr$n復制成功." done < /testdir/file rm -f /testdir/file esac done
###執行效果 [root@6 bin]# ./copycmd.sh 請輸入一個可執行的命令cd 復制命令的路徑: /bin/bash ============================== /bin/bash的庫文件: /lib64/libtinfo.so.5 /lib64/libdl.so.2 /lib64/libc.so.6 /lib64/ld-linux-x86-64.so.2 ============================== /mnt/sysroot/bin/bash復制成功. ============================== /mnt/sysroot/lib64/libtinfo.so.5復制成功. /mnt/sysroot/lib64/libdl.so.2復制成功. /mnt/sysroot/lib64/libc.so.6復制成功. /mnt/sysroot/lib64/ld-linux-x86-64.so.2復制成功. 請輸入一個可執行的命令ip 復制命令的路徑: /sbin/ip ============================== /sbin/ip的庫文件: /lib64/libresolv.so.2 /lib64/libdl.so.2 /lib64/libc.so.6 /lib64/ld-linux-x86-64.so.2 ============================== /mnt/sysroot/sbin/ip復制成功. ============================== /mnt/sysroot/lib64/libresolv.so.2復制成功. /mnt/sysroot/lib64/libdl.so.2復制成功. /mnt/sysroot/lib64/libc.so.6復制成功. /mnt/sysroot/lib64/ld-linux-x86-64.so.2復制成功.
3 、斐波那契數列又稱黃金分割數列,因數學家列昂納多·斐波那契以兔子
繁殖為例子而引入,故又稱為“兔子數列”,指的是這樣一個數列:0 、1 、1 、2 、3 、5 、8 、13 、21 、34 、……,斐波納契數列以如下被以遞歸的
方法定義:F (0 )=0 ,F (1 )=1 ,F (n )=F(n-1)+F(n-2) (n≥2) )
寫一個函數,求n 階斐波那契數列
###函數 tuzi() { if [ $1 -eq 0 ];then echo 0 elif [ $1 -eq 1 ];then echo 1 else echo $[$(tuzi $[$1-1])+$(tuzi $[$1-2])] fi } tuzi2() { for((i=0;i<=$1;i++)) if [ $i -eq 0 ];then echo 0 elif [ $i -eq 1 ];then echo 1 else echo $[$(tuzi $[$i-1])+$(tuzi $[$i-2])] fi done }
###程序 #! /bin/bash #author:lvasu #description: #version:0.1 #date: source agrement read -p "請輸入斐波那契數列階數:" n tuzi $n echo '===================' tuzi2 $n
###執行效果 [root@6 bin]# ./feibo.sh 請輸入斐波那契數列階數:10 55 =================== 0 1 1 2 3 5 8 13 21 34 55
原創文章,作者:lvasu,如若轉載,請注明出處:http://www.www58058.com/38903