(3) 取得到目標主機系統功能的相關訊息,例如要啟用的檔案系統;
(4) 取得核心原始碼套件;
www.kernel.org
準備開發環境:
#套件組(CentOS 6):
Server Platform Development
Development Tools
#目標主機硬體裝置相關資訊:
CPU:
~]# cat /proc/cpuinfo#
~]# x86info -a
~]# lscpu
PCI裝置裝置:
~]# lspci#
-v
-vv
~]# lsusb
-v
-vv
~]# lsblk
了解全部硬體裝置資訊#
~]# hal-device
#簡單依據範本檔案的製作過程:
#~]# tar xf linux-3.10.67.tar.xz -C /usr/src#
~]# cd /usr/src
~] # ln -sv linux-3.10.67 linux
~]# cd linux
~]# cp /boot/config-$( uname -r) ./.config
~]# make menuconfig
#~]# screen
~]# make -j
#
~]# make modules_install
~]# make install
#重啟系統,並測試使用新核心;
Linux核心編譯(2 )
編譯核心的步驟:
#(1) 設定核心選項
支援「更新」模式進行設定:
(a) make config:基於命令列以遍歷的方式去設定核心中可設定的每個選項;
(b) make menuconfig:基於curses的文字視窗介面;
(c) make gconfig:基於GTK開發環境的視窗介面;
(d) make xconfig:基於Qt開發環境的視窗介面;
支援「全新配置」模式進行設定:
(a) make defconfig:基於核心為目標平台提供的「預設」設定進行設定;
(b) make allnoconfig: 所有選項都回答為"no";
(2) 編譯
make [-j #]
如何只編譯核心中的一部分功能:
(a) 只編譯某子目錄中的相關程式碼:
# cd /usr/src/linux
## make dir/
(b) 只編譯一個特定的模組:
# cd /usr/src/linux
# make dir/file.ko
例如:只為e1000編譯驅動程式:
# make drivers/net/ethernet/intel/e1000/ e1000.ko
#######
如何交叉編譯核心:
編譯的目標平台與目前平台不相同;
make ARCH=arch_name
要取得特定目標平台的使用說明
# make ARCH =arch_name help
如何在已經執行過編譯作業的核心原始碼樹做重新編譯:
事先清理操作:
# make clean:清理大多數編譯產生的文件,但會保留config檔等;
# make mrproper: 清理所有編譯產生的檔案、config及某些備份檔;
# make distclean:mrproper、patches以及編輯器備份檔;
screen指令:
開啟新的screen:
screen
退出並關閉screen:
# exit
#剝離目前screen:
Ctrl +a,d
顯示所有已經開啟的screen:
#screen -ls
#恢復某screen
screen -r [SESSION]
CentOS系統安裝
bootloader-->kernel(initramfs)-->rootfs-->/sbin/init
anaconda: 安裝程式
tui: 基於curses的文字視窗;
#gui: 圖形視窗;
##CentOS的安裝程式啟動過程:
MBR:boot.cat
stage2: isolinux/isolinux.bin
設定檔:isolinux/isolinux.cfg
#每個對應的選單選項:
載入核心:isolinuz/vmlinuz
#向核心傳遞參數:append initrd=initrd.img ...
裝載根檔案系統,並啟動anaconda
預設啟動GUI介面
若是明確指定使用TUI介面:
向核心傳遞「text」參數即可;
#boot: linux text
注意:上述內容一般應位於引導裝置;而後續的anaconda及其安裝用到的套件等有幾種方式可用:
本地光碟
本機硬碟
ftp server: yum repository
http server: yum repostory
nfs server
#如果想要手動指定安裝來源:
boot: linux method
anaconda應用程式的工作過程:
##安裝前設定階段
#安裝程序使用的語言
鍵盤類型
#安裝目標儲存裝置
####安裝目標儲存裝置######### ###Basic Storage:本機磁碟############特種裝置:iSCSI#############設定主機名稱######### ##設定網路介面############時區#############管理員密碼############設定分割區方式及MBR的安裝位置##################建立一個普通使用者##################選定要安裝的程式套件############安裝階段###
在目標磁碟建立分割區,執行格式化操作等
#將選定的套件安裝至目標位置
安裝bootloader
首次啟動
#iptables
##selinux
#。
##core dump
anaconda的設定方式:
(1) 互動式配置方式;
(2) 透過讀取事先給定的設定檔自動完成設定;
##按特定語法給予的設定選項;
kickstart檔;
安裝引導選項:
# #boot:
text: 文字安裝方式
#method: 手動指定使用的安裝方法
與網路相關的開機選項:
ip=IPADDR
#netmask=MASK
gateway=GW
dns=DNS_SERVER_IP
ifname=NAME:MAC_ADDR
#與遠端存取功能相關的引導選項:
vnc
#vncpassword='PASSWORD'
#指明kickstart檔案的位置
ks=
#DVD drive: ks=cdrom:/PATH/TO/KICKSTART_FILE
Hard drive: ks=hd:/device/drectory/KICKSTART_FILE
HTTP server: ks=http://host:port/path/to/KICKSTART_FILE
FTP server: ks=ftp://host:port/path/to/KICKSTART_FILE
HTTPS server: ks=https://host :port/path/to/KICKSTART_FILE
啟動緊急救援模式:
rescue
官方文件:《Installation Guide》
#kickstart檔案的格式:
命令段:指明各種安裝前配置,如鍵盤類型等;
套件段:指明要安裝的套件組或套件,不安裝的套件等;
%packages
@group_name
package
######################## # -package############%end###################################腳本段:############%pre: 安裝前腳本# ###########執行環境:執行於安裝媒體上的微型Linux環境##################%post: 安裝後腳本### #########執行環境:安裝完成的系統;#########################指令段中的指令:### #########必備指令############authconfig: 認證方式設定############authconfig --useshadow --passalgo=sha512 ############bootloader:bootloader的安裝位置及相關設定############bootloader --location=mbr --driveorder=sda --append="crashkernel =auto crashkernel=auto rhgb rhgb quiet quiet"#############keyboard: 設定鍵盤類型############lang: 語言類型####### ######part: 建立分割區############rootpw: 指明root的密碼############timezone: 時區######## #######################可選指令#############install OR upgrade###########################install OR upgrade######### ###text: 文字安裝介面############network###
firewall
selinux
halt
##poweroff
reboot
repo
#user:安裝完成後為系統建立新使用者
url: 指明安裝來源
#建立kickstart檔案的方式:
(1) 直接手動編輯;
依據某範本修改;
(2) 可使用建立工具:system-config-kickstart ( CentOS 6)
依據某範本修改並產生新設定;
http://172.16.0.1/ centos6.x86_64.cfg
#檢查ks檔的語法錯誤:ksvalidator
# ksvalidator /PATH/TO/ KICKSTART_FILE
建立引導光碟:
# mkisofs -R -J -T -v --no-emul -boot --boot-load-size 4 --boot-info-table -V "CentOS 6.6 x86_64 boot" -b isolinux/isolinux.bin -c isolinux/boot.cat -o /root/boot.iso myiso/
回顧:CentOS系統安裝
#kickstart檔:
指令段
必備:authconfig, bootloader, ...
可選:firewall, selinux, reboot, ...
套件段
%packages
#@group_name
##package
-package
%end
腳本段
%pre
...
#%end
%post
...
#%end
建立工具:system-config-kickstart
語法檢查:ksvalidator
##安裝過程如何取得kickstart檔:
DVD: ks=cdrom:/PATH/TO/KS_FILE
##HTTP: ks=http://HOST: PORT/PATH/TO/KS_FILE
SELinux:
##SELinux: Secure Enhanced Linux ,工作於Linux核心中
DAC:自主存取控制;
MAC:強制存取控制;
SELinux有兩種工作等級:
#strict: 每個行程都受到selinux的控制;
targeted: 僅有限個程序受到selinux控制;
#只監控容易被入侵的進程;
##sandbox:
subject operation object
subject: 進程
object: 進程,文件,
」檔:open, read, write, close, chown, chmod
#subject: domain
object: type
SELinux為每個檔案提供了安全標籤,也為進程提供了安全標籤;
user:role:type
user: SELinux的user;
role: 角色;
type: 類型;
############### SELinux規則庫:############規則:哪個域能存取哪種或哪些類型內檔案;##################配置SELinux:###
SELinux是否啟用;
給檔案重新打標;
設定某些布型特性;
SELinux的狀態:
enforcing: 強制,每個受限的程序都必然受限;
permissive: 啟用,每個受限的程序違規操作不會被禁止,但會被記錄於審計日誌;
disabled : 關閉;
相關指令:
getenforce: 取得selinux目前狀態;
#setenforce 0|1
0: 設定為permissive
1: 設定為enforcing
#此設定:重新啟動系統後無效;
#設定檔:/etc/sysconfig/selinux, /etc /selinux/config
SELINUX={disabled|enforcing|permissive}
##給檔案重新打標:
chcon
chcon [OPTION]... CONTEXT FILE...
chcon [ OPTION]... [-u USER] [-r ROLE] [-t TYPE] FILE...
chcon [OPTION]... --reference=RFILE FILE. ..
-R:遞迴打標;
# #還原檔案的預設標籤:
restorecon [-R] /path/to/somewhere
布林型規則:
getsebool
#setsebool
getsebool指令:
getsebool [-a] [boolean]
setsebool指令:
setsebool [ -P] boolean value | bool1=val1 bool2=val2 ...
##bash腳本程式設計:
#程式語言:
#資料結構
順序執行
選擇執行
條件測試
#執行指令或[[ EXPRESSION ]]
執行狀態傳回值;
if
#case
循環執行
將某程式碼段重複執行多次;
#重複運行多少次?
循環次數事先已知:
循環次數事先未知;
##必須有進入條件和退出條件:
for, while, until
函數:結構化程式設計及程式碼重複使用;
function
for迴圈語法:
for NAME in LIST; do
迴圈體
##done
清單產生方式:
#########(1) 整數清單############{start..end}## ##########$(seq start [[step]end])#############(2) glob###########/ etc/rc.d/rc3.d/K*############(3) 指令##################透過ping指令探測172.16.250.1-254範圍內的所有主機的線上狀態;#############!/bin/bash#####################################################################################################
net='172.16.250'
#uphosts=0
##downhosts=0
for i in {1..20}; do
# ping -c 1 -w 1 ${net}.$ {i} &> /dev/null
if [ $? -eq 0 ]; then
echo "${net}. ${i} is up."
let uphosts++
else
else
echo "$ {net}.${i} is down."
let downhosts++
fi
# fi
#done
#echo "Up hosts: $uphosts."
echo "Down hosts: $downhosts."
while循環:
##while CONDITION; do
迴圈體
done
#CONDITION:迴圈控制條件;進入循環之前,先做一次判斷;每次循環之後會再次做判斷;
#條件為“true”,則執行一次循環;直到條件測試狀態為“false”終止迴圈;
因此:CONDTION一般應該有迴圈控制變數;而此變數的值會在迴圈體不斷地修正;
範例:求100以內所有正整數總和;
#!/bin/bash
declare -i sum=0
#declare -i i=1
##while [ $i -le 100 ]; do
let sum+=$i
let i++
done
echo "$i"
echo "Summary: $sum."
新增10位使用者
user1-user10
#!/bin/bash
##declare -i i=1
declare -i users=0
#while [ $i -le 10 ]; do
# if ! id user$i &> /dev/null; then
useradd user$i
#echo "Add user: user$i."
let users++
## fi
# fi
## let i++
done
#echo "Add $users users."
###透過ping指令偵測172.16.250.1-254範圍內的所有主機的線上狀態;(用while循環)############# #!/bin/bash##########################declare -i i=1##################declare -i i=1###########declare - i uphosts=0############declare -i downhosts=0############net='172.16.250'########## #########while [ $i -le 20 ]; do############ if ping -c 1 -w 1 $net.$i &> /dev/null ; then############echo "$net.$i is up."############let uphosts++########### # else###
echo "$net.$i is down."
let downhosts++
## fi
let i++
#done
echo "Up hosts: $uphosts. "
echo "Down hosts: $downhosts."
列印九九乘法表;(分別使用for和while循環實作)
#!/bin/bash
for j in {1..9}; do
for i in $(seq 1 $j); do
echo -e -n "${i}X${j}=$[$i*$j]\t"
done
# echo
done
#!/bin/bash
#declare -i i=1
declare -i j=1
while [ $j -le 9 ]; do
while [ $i -le $j ]; do
echo -e -n "${i}X${j}=$[$i*$j]\t"
let i++
done
echo
let i=1
let j++
#done
使用RANDOM產生10個隨機數字,輸出這個10數字,並顯示其中的最大者和最小者;
##!/bin/bash
#declare -i max=0
#declare -i min=0
declare -i i=1
while [ $i -le 9 ]; do
rand=$RANDOM
echo $rand
if [ $i -eq 1 ]; then
max=$rand
min=$rand
fi
if [ $rand -gt $max ]; then
max=$rand
## fi
if [ $rand -lt $min ]; then
min=$rand
fi
let i++
done
echo "MAX : $max."
echo "MIN: $min."
回顧:selinux, while
##selinux: 內核,安全加強;
# 開啟:
/etc/sysconfig/selinux, /etc/selinux/config############# setenforce############## getenforce######################################################################## ##打標:############chcon [-t TYPE]############-R############ #####布林型:############getsebool [-a]############setsebool [-P]######## ##########while迴圈:############while CONDITION; do############迴圈體######## #####done############sed:編輯器##########
sed: Stream EDitor, 行編輯器;
#用法:
sed [option]... 'script' inputfile...
#script:
'位址指令'
常用選項:
-n:不將模式中的內容輸出至螢幕;
#-e: 多點編輯;
-f /PATH/TO/SCRIPT_FILE: 從指定檔案中讀取編輯腳本;
-r: 支援使用擴充正規表示式;
-i: 原處編輯;
位址定界:
(1) 不給位址:對全文進行處理;
##(2) 單一位址:
#: 指定的行;
/pattern/:被此處模式所能夠匹配到的每一行;
(3) 位址範圍:
#,
##,+
##/pat1/,/pat2/
#,/pat1/
(4) ~:步驟
1~2
2~2
編輯指令:
d: 刪除
p: 顯示模式空間中的內容
a \text :在行後面追加文字;支援使用\n實作多行追加;
i \text:在行前面插入文字;支援使用\n實作多行插入;
c \text:取代行為單行或多行文字;
#w /path/to/somefile: 儲存模式空間符合到的行至指定文件中;
r /path/from/somefile:讀取指定檔案的文字流至模式空間中符合的行的行後;
=: 為模式空間中的行印出行號;
!: 取反條件;
s/// :支援使用其它分隔符,s@@@,s;
取代標記:
g: 行內全域替換;
p: 顯示已取代成功的行;
#w /PATH/TO/SOMEFILE:將取代成功的結果儲存至指定檔案中;
1:刪除/boot/grub/grub.conf檔案中所有以空白開頭的行行首的空白字元;
~]# sed 's@^[[:space:]]\+@@' /etc/grub2.cfg
2:刪除/etc/fstab檔案中所有以#開頭,後面至少跟一個空白字元的行的行首的#和空白字元;
~]# sed 's@ ^#[[:space:]]\+@@' /etc/fstab
#3:echo一個絕對路徑給sed指令,取出其基底名;取出其目錄名稱;
~]# echo "/etc/sysconfig/" | sed 's@[^/]\+/\?$@@'
高階編輯指令:
#h: 將模式空間中的內容覆寫至保持空間中;
############################# #######H:把模式空間中的內容追加至保持空間中;############g: 從保持空間取出資料覆寫至模式空間;##### #######G:從保持空間取出內容追加至模式空間;############x: 把模式空間中的內容與保持空間中的內容互換;# ###########n: 讀取符合到的行的下一行至模式空間;############N:追加符合到的行的下一行至模式空間;############d: 刪除模式空間中的行;#############D:刪除多行模式空間中的所有行;### ######
sed -n 'n;p' FILE:顯示偶數行
#sed '1!G;h;$!d' FILE:逆向顯示檔案內容
sed '$!N;$!D' FILE: 取出檔案後兩行;
sed '$!d' FILE:取出文件最後一行;
sed 'G' FILE:
sed '/^$/d;G' FILE:
sed 'n;d' FILE: 顯示奇數行;
sed -n '1!G;h;$p' FILE:反向顯示檔案中的每一行;
bash腳本程式設計
while CONDITION; do
迴圈體
done
# 進入條件:CONDITION為true;
退出條件:false
until CONDITION; do
循環體
done
#進入條件:false
#退出條件:true
範例:求100以內所正整數總和;
#!/bin/bash
#declare -i i=1
declare -i sum=0
until [ $i -gt 100 ]; do
let sum+=$i
# let i++
done
#echo "Sum: $sum"
#範例:列印九九乘法表
##!/bin/bash
##declare -i j=1
#declare -i i=1
until [ $j -gt 9 ]; do
until [ $i -gt $j ]; do
#echo -n -e "${i}X${j}=$[$i*$j]\t"
let i++
# done
echo
let i=1
# let j++
done
迴圈控制語句(用於迴圈體中):
#continue [N]:提前結束第N層的本輪循環,而直接進入下一輪判斷;
while CONDTIITON1; do
#CMD1
...
if CONDITION2; then
continue
#。
#fi
CMDn
...
done
break [N]:提前結束循環;
##while CONDTIITON1; do
CMD1
###...###########if CONDITION2; then##### #######break############fi#############CMDn###########...# ###########done###################範例1:求100以內所有偶數總和;要求循環遍歷100以內的所正整數;#############!/bin/bash#########################declare -i i=0# ##
declare -i sum=0
#until [ $i -gt 100 ]; do
# let i++
if [ $[$i%2] -eq 1 ]; then
#continue
fi
let sum+=$i
done
#echo "Even sum: $sum"
#建立死迴圈:
while true; do
循環體
done
until false; do
循環體
#done
done
範例2 :每隔3秒鐘到系統上取得已經登入的使用者的資訊;如果docker登入了,則記錄於日誌中,並登出;
!/bin/bash
#read -p "Enter a user name: " username
##while true; do
if who | grep "^$username" &> /dev/null; then
#break
fi
sleep 3##done
#echo "$username logged on." >> /tmp/user.log
第二種實作:
#!/bin/bash
#read -p "Enter a user name: " username
until who | grep "^$username" &> /dev/null; do
# sleep 3
done
echo "$username logged on." >> /tmp/user.log
while迴圈的特殊用法(遍歷檔案的每一行):
while read line; do
迴圈體
done < /PATH/FROM/SOMEFILE
依序讀取/PATH/FROM/SOMEFILE檔案中的每一行,並且將行賦值給變數line:
#範例:找出其ID號碼為偶數的所有用戶,顯示其用戶名稱及ID號碼;
#!/bin/bash
while read line;do
if [ $[`echo $line | cut -d: -f3` % 2] -eq 0 ];then
echo -e -n "username: `echo $line | cut -d: -f1`\t"
# echo "uid: `echo $line | cut -d: -f3 `"
fidone < /etc/passwd
for迴圈的特殊格式:
for ((控制變數初始化;條件判斷表達式;控制變數的修正表達式)); do
循環體############done###################################################################### ########控制變數初始化:僅在運行到循環程式碼段時執行一次;############控制變數的修正表達式:每輪迴圈結束會先控制變數修正運算,而後再做條件判斷;##################範例:求100以內所正整數之和;######################################################################## ##!/bin/bash###
#declare -i sum=0
##for ((i =1;i<=100;i++)); do
let sum+=$i
#done
echo "Sum: $sum."
#範例2:列印九九乘法表;
#!/bin/bash
##for((j= 1;j<=9;j++));do
for((i=1;i<=j;i++))do
# echo -e -n "${i}X${j}=$[$i*$j]\t"
done
我# echo
done
(1) 顯示一個下列選單:
##(1) 顯示一個下列選單:
cpu) show cpu information;
mem) show memory information;
disk) show disk information;
quit) quit
(2) 提示用戶選擇選項;(3) 顯示用戶選擇的內容;
#!/bin/bash
##cat << EOF
cpu) show cpu information;
mem) show memory information;
disk) show disk information;
#quit) quit
========== ===================
EOF
read -p "Enter a option: " option
while [ "$option" != 'cpu' -a "$option" != 'mem' -a "$option" ! = 'disk' -a "$option" != 'quit' ]; do
read -p "Wrong option, Enter again: " option
#done
if [ "$option" == 'cpu' ]; then
lscpu
elif [ "$option" == 'mem' ]; then
cat /proc/meminfo
elif [ "$option" == 'disk' ]; then
# fdisk -l
else
echo "Quit"
exit 0
fi
#進一步:
使用者選擇,並顯示完成後不退出腳本;而是提示使用者繼續選擇顯示其它內容;直到使用quit方始退出;
條件判斷:case語句
#case 變數引用in
PAT1)
分支1
;;
##PAT2)
分支2
;;
#...
# *)
預設分支
;;
##esac
#範例:
#!/bin/bash
#cat << EOF#############cpu) show cpu information;###mem) show memory information;
disk) show disk information;
quit) quit
============================
# EOF
read -p "Enter a option: " option
while [ "$option" != ' cpu' -a "$option" != 'mem' -a "$option" != 'disk' -a "$option" != 'quit' ]; do
read -p "Wrong option, Enter again: " option
done
case "$option" in
cpu)
lscpu
;;
mem)
cat /proc/meminfo
;;
disk)
fdisk -l
;;
##*)
echo "Quit..."
exit 0
;;
#esac
#(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_NAME is stopped...」;
##其中:SCRIPT_NAME為目前腳本名稱;
#總結:until, while, for, case
##bash腳本程式設計:
#case語句:
##case變數引用in
PAT1)
#分支1
##;;PAT2)
分支2
#;;
##. ..
*)
分支n
;;
#esac
case支援glob風格的通配符:
########*: 任意長度任意字符;############?: 任意單一字元;#############[]:指定範圍內的任意單一字元;######## ####a|b: a或b##################function:函數############過程式設計:程式碼重複使用# ###########模組化程式設計############結構化程式設計##################語法一: ############function f_name {############...函數體...############} ## #######語法二:
f_name() {
##...函數體...
}
呼叫:函數只有被呼叫才會執行;
# #呼叫:給定函數名稱
函數名稱出現的地方,會被自動替換為函數代碼;
函數的生命週期:被呼叫時創建,返回時終止;
return命令返回自訂狀態結果;
0:成功
1-255:失敗
#!/bin/bash
function adduser {
# if id $username &> /dev/null; then
# echo "$username exists."
return 1
#。
#}
for i in {1..10}; do
username=myuser$i
adduser
done
#範例:服務腳本
#!/bin/bash
chkconfig : - 88 12
# description: test service script
#prog=$ (basename $0)
lockfile=/var/lock/subsys/$prog
start() {
if [ -e $lockfile ]; then
echo "$prog is aleady running."
#return 0
else
touch $lockfile
##[ $? -eq 0 ] && echo "Starting $prog finished."
fi
##}
#stop() {
if [ -e $lockfile ]; then
rm -f $lockfile && echo " Stop $prog ok."
else
echo "$prog is stopped yet."
# fi
}
status() {
if [ -e $lockfile ]; then
echo "$prog is running."
else
echo "$prog is stopped."
fi
}
usage() {
echo "Usage: $prog {start|stop|restart|status}"
# }
if [ $# -lt 1 ]; then
usage
# exit 1
##fi
case $1 in
###################################################################################### ##start)############start###
;;
stop)
#stop
## ;;
restart)
stop
;;
status)
status
##;;
*)
usage
#esac
##函數傳回值:
函數的執行結果傳回值:
(1) 使用echo或print指令進行輸出;
(2) 函數體中呼叫指令的執行結果;
函數的退出狀態碼:
(1) 預設取決於函數體中執行的最後一條指令的退出狀態碼;
(2) 自訂退出狀態碼:
return
函數可以接受參數:
傳遞參數給函數:呼叫函數時,在函數名後面以空白分隔給定參數列表即可;例如「testfunc arg1 arg2 ...」
在函數體中當中,可使用$1, $2, ...呼叫這些參數;也可以使用$@, $*, $#等特殊變量;
範例:新增10個使用者
#!/bin/bash
#function adduser {
## if [ $# -lt 1 ]; then
return 2
# 2: no arguments
fi
# if id $1 &> /dev/null; then
echo "$1 exists."
#return 1
else
useradd $1
[ $? -eq 0 ] && echo "Add $1 finished." && return 0
fi
}
for i in {1..10}; do
# adduser myuser$i
done
印出NN乘法表,使用函數實作;
##變數作用域:
本機變數:目前shell程序;為了執行腳本會啟動專用的shell程序;因此,本機變數的作用範圍是目前shell腳本程式檔;
局部變數:函數的生命週期;函數結束時變數被自動銷毀;
如果函數中有局部變量,其名稱同本地變數;
在函數中定義局部變數的方法:
#local NAME=VALUE
##函數遞迴:
函數直接或間接呼叫自己;
##N!= N(n-1)(n-2)...1
n(n-1)! = n(n-1)(n-2)!
#!/bin/bash
#fact() {
if [ $1 -eq 0 -o $1 -eq 1 ]; then
echo 1
else
echo $[$1*$(fact $[$1-1])]
fi
}
fact 5
#求n階斐波那契數列;
#!/bin/bash
#fab() {
# if [ $1 -eq 1 ]; then
#echo 1
elif [ $1 -eq 2 ]; then
echo 1
else
echo $[$(fab $[$1-1])+$(fab $[$1-2])]
fi
}
fab 7
#Systemd:
POST --> Boot Sequence --> Bootloader --> kernel + initramfs(initrd) --> rootfs --> /sbin/init
init:
#CentOS 5: SysV init
CentOS 6: Upstart
CentOS 7: Systemd
Systemd新功能:
系統引導時實現服務並行啟動;
##按需激活進程;
系統狀態快照;
基於依賴關係定義服務控制邏輯;
核心概念:unit
設定檔進行識別與設定;檔案中主要包含了系統服務、監聽socket、儲存的系統快照以及其它與init相關的訊息;
儲存至:
/usr/lib/systemd/system
##/ run/systemd/system
/etc/systemd/system
Unit的類型:
Service unit: 檔案副檔名為.service, 用於定義系統服務;
Target unit: 檔案副檔名為.target,用於模擬實作“運行等級」;
Device unit: .device, 用於定義核心識別的裝置;
Mount unit: .mount, 定義文件系統掛載點;
Socket unit: .socket, 用來識別進程間通訊用的socket檔;
Snapshot unit: . snapshot, 管理系統快照;
Swap unit: .swap, 用於標識swap設備;
Automount unit: .automount,檔案系統的自動掛載點;
Path unit: .path,用於定義檔案系統中的一個檔案或目錄;
##關鍵特性:
基於socket的啟動機制:socket與服務程式分離;
基於bus的啟動機制:
基於device的激活機制:############基於path的激活機制:###########系統快照:保存各unit的目前狀態資訊於持久性儲存設備中;############向後相容sysv init腳本;################################################################不相容:############systemctl指令固定不變#############非由systemd啟動的服務,systemctl無法與之通訊###### ############管理系統服務:############CentOS 7: service unit############注意:能相容於早期的服務腳本##################指令:systemctl COMMAND name.service#########
啟動:service name start ==> systemctl start name.service
停止:service name stop ==> systemctl stop name.service
重啟:service name restart ==> systemctl restart name.service
狀態:service name status ==> systemctl status name. service
條件式重新啟動:service name condrestart ==> systemctl try-restart name.service
##重載或重新啟動服務:systemctl reload-or-restart name.service
重載或條件式重新啟動服務:systemctl reload-or-try-restart name.service
禁止設定為開機自啟動:systemctl mask name.service
取消禁止設定為開機自啟動:systemctl unmask name.service
查看某服務目前啟動與否的狀態:systemctl is-active name.service
查看所有已經啟動的服務:
systemctl list-units --type service
查看所有服務:
systemctl list -units --type service --all
chkconfig指令的對應關係:
設定某服務開機自啟動:chkconfig name on ==> systemctl enable name.service
禁止:chkconfig name off ==> systemctl disable name.service
##查看所有服務的開機自啟動狀態:
chkconfig --list ==> systemctl list-unit-files --type service
#查看服務是否開機自啟動:systemctl is-enabled name.service
其它指令:
# #查看服務的依賴關係:systemctl list-dependencies name.service
target units:
#unit設定檔:.target
運行等級:
0 ==> runlevel0.target , poweroff.target
1 ==> runlevel1.target, rescue.target
2 ==> runlevel2.target, multi -user.target
3 ==> runlevel3.target, multi-user.target
4 ==> runlevel4.target , multi-user.target
5 ==> runlevel5.target, graphical.target
6 ==> runlevel6.target , reboot.target
等級切換:
init N ==> systemctl isolate name.target
查看等級:
runlevel ==> systemctl list-units --type target
#取得預設運行等級:
/etc/inittab ==> systemctl get-default
##修改預設等級:
/etc/inittab ==> systemctl set-default name.target
#切換至緊急救援模式:
systemctl rescue
切換至emergency模式:
systemctl emergency
其它常用指令:
##關機:systemctl halt、systemctl poweroff
重啟:systemctl reboot
掛起:systemctl suspend########### #快照:systemctl hibernate############快照並掛起:systemctl hybrid-sleep#################回顧: bash腳本程式設計、 systemd#########
函數:模組化程式設計
function f_name {
...函數本體...
}
f_name() {
...函數體...
}
#return指令;
參數:
函數體中呼叫參數:$1, $2, ...
$*, $@, $
#向函數傳遞參數:
函數名稱參數清單
systemd:系統及服務
unit:
#類型:service, target
.service, . target
systemctl
#bash腳本程式設計:
##陣列:
變數:儲存單一元素的記憶體空間;
陣列:儲存多個元素的連續的記憶體空間;
#陣列名稱
索引:編號從0開始,屬於數值索引;
注意:索引也可支援使用自訂的格式,而不僅僅是數值格式;
bash的陣列支援稀疏格式;
引用數組中的元素:${ARRAY_NAME[INDEX]}
聲明數組:
declare -a ARRAY_NAME
declare -A ARRAY_NAME: 關聯陣列;
陣列元素的賦值:
##(1) 一次只賦值一個元素;
ARRAY_NAME[INDEX]=VALUE
weekdays[0]=" Sunday"
weekdays[4]="Thursday"
(2) 一次賦值全部元素:
#ARRAY_NAME=("VAL1" "VAL2" "VAL3" ...)
(3) 只賦值特定元素:
ARRAY_NAME=([0]="VAL1" [3]="VAL2" ...)
(4) read -a ARRAY
引用陣列元素:${ARRAY_NAME[INDEX]}
#注意:省略[INDEX]表示引用下標示為0的元素;
陣列的長度(陣列中元素的數量):${#ARRAY_NAME[*]}, ${#ARRAY_NAME[@]}
範例:產生10個隨機數儲存於陣列中,並找出其最大值和最小值;
#!/ bin/bash
##declare -a rand
declare -i max=0
for i in {0..9}; do
rand[$i]=$RANDOM
echo ${rand[$i]}
[ ${rand[$i]} -gt $max ] && max=$ {rand[$i]}
done
#echo "Max: $max"
定義一個數組,數組中的元素是/var/log目錄下所有以.log結尾的檔案;要統計其下標為偶數的檔案中的行數總和;
##!/bin/bash
#declare -a files
###files=(/var/log/*.log)######### ###declare -i lines=0##################for i in $(seq 0 $[${#files[*]}-1]); do ###
if [ $[$i%2] -eq 0 ];then
let lines+=$(wc -l ${files[$i ]} | cut -d' ' -f1)
fi
done
echo "Lines: $lines."
#引用陣列中的元素:
所有元素:${ARRAY[@]}, ${ARRAY[*]}
#陣列切片:${ARRAY[@] :offset:number}
offset: 要跳過的元素個數
number: 要取出的元素個數,取偏移量之後的所有元素:${ARRAY[@]:offset};
#向陣列中追加元素:
ARRAY[${#ARRAY[*]}]
#刪除陣列中的某元素:
unset ARRAY[INDEX]
關聯數組:
declare -A ARRAY_NAME
#ARRAY_NAME=([index_name1]='val1' [index_name2]='val2' ...)
bash的字串處理工具:
字串切片:
${var: offset:number}
取字串的最右邊幾個字元:${var: -lengh}
注意:冒號後必須有一空白字元;
基於模式取子字串:
##${var#*word}:其中word可以是指定的任意字元;功能:自左而右,尋找var變數所儲存的字串中,第一次出現的word, 刪除字串開頭至第一次出現word字元之間的所有字元;
${var##*word}:同上,不過,刪除的是字串開頭至最後一次由word指定的字元之間的所有內容;
#file="/var/log/messages"
${file##*/}: messages
##${var%word*}:其中word可以是指定的任意字元;功能:自右而左,查找var變數所儲存的字串中,第一次出現的word, 刪除字串最後一個字元向左至第一次出現word字元之間的所有字元;
file="/var/log/messages"
${file%/*}: /var/log
#${var%%word*}:同上,只不過刪除字串最右側的字元向左至最後一次出現word字元之間的所有字元;
#範例:url=:80
${url##*:}
${url%%:*}
找替換:
${var/pattern/substi}:查找var所表示的字串中,第一次被pattern所匹配到的字串,以substi替換之;
${var//pattern/substi}: 查找var所表示的字串中,所有能被pattern所匹配到的字串,以substi替換之;
${var/#pattern/substi}:在尋找var所表示的字串中,行首被pattern所匹配到的字串,以substi替換之;
${var/%pattern/substi}:查找var所表示的字串中,行尾被pattern所匹配到的字串,以substi替換之;
找出並刪除:
${var/pattern}:找出var所表示的字串中,刪除第一次被pattern配對到的字串
${var//pattern}:
${var/#pattern}:
${var/%pattern}:
#字元大小寫轉換:
#${var^^}:把var中的所有小寫字母都轉換成大寫;###
${var,,}:把var中的所有大寫字母轉換成小寫;
變數賦值:
${var:-value}:如果var為空或未設置,那麼傳回value;否則,則傳回var的值;
## ${var:=value}:如果var為空或未設置,那麼返回value,並將value賦值給var;否則,則返回var的值;
##${var:+value}:如果var不空,則返回value;
#${var:?error_info}:如果var為空或未設置,那麼返回error_info;否則,則傳回var的值;
#為腳本程式使用設定檔:
##(1)定義文字文件,每行定義「name=value」
(2) 在腳本中source此文件即可
指令:
mktemp指令:
#mktemp [OPTION]... [TEMPLATE]
TEMPLATE: filename.XXX
XXX至少要出現三個;
##OPTION:
##-d: 建立臨時目錄;
--tmpdir=/PATH/TO/SOMEDIR:指明臨時檔案目錄位置;
install指令:
install [OPTION]... [-T] SOURCE DEST
install [ OPTION]... SOURCE... DIRECTORY
install [OPTION]... -t DIRECTORY SOURCE...
install [ OPTION]... -d DIRECTORY...
選項:
#- m MODE
-o OWNER
-g GROUP
GNU awk:
#文字處理三工具:grep, sed, awk
grep, egrep, fgrep:文字過濾工具;pattern
sed: 行編輯器
模式空間、保持空間
awk:報告產生器,格式化文字輸出;
AWK: Aho , Weinberger, Kernighan --> New AWK, NAWK
#GNU awk, gawk
#gawk - pattern scanning and processing language
基本用法:gawk [options] 'program' FILE ...
#program: PATTERN{ACTION STATEMENTS}
#語句之間用分號分隔
print, printf
選項:
-F:指明輸入時所用到的欄位分隔符號;
#-v var=value: 自訂變數;
1、print
##1、print
print item1, item2, ...
#要點:
##(1) 逗號分隔符號;
(2) 輸出的各item可以字串,也可以是數值;目前記錄的欄位、變數或awk的表達式;
(3) 如省略item,相當於print $0;
#2、變數
## 2.1 內建變數
FS:input field seperator,預設為空白字元;
######OFS:output field seperator,預設為空白字元; ###
RS:input record seperator,輸入時的換行符;
ORS:output record seperator,輸出時的換行符;
NF:number of field,欄位數
#{print NF}, {print $NF}
NR:number of record, 行數;
FNR:各檔案分別計數;行數;
##FILENAME:目前檔名;
ARGC:指令列參數的個數;
ARGV :數組,保存的是命令列所給定的各參數;
#2.2 自訂變數
( 1) -v var=value
變數名區分字元大小寫;
(2) 在program中直接定義
3、printf指令
格式化輸出:printf FORMAT, item1, item2, ...
#(1) FORMAT必須給出;
# (2) 不會自動換行,需要明確給出換行控制符,\n
(3) FORMAT中需要分別為後面的每個item指定一個格式化符號;
格式符號:
%c: 顯示字元的ASCII碼;
%d, %i: 顯示十進位整數;
#%e, %E: 科學計數法數值顯示;
# %f:顯示為浮點數;
%g, %G:以科學計數法或浮點數顯示數值;
##% s:顯示字串;
%u:無符號整數;
%%: 顯示%本身;
修飾符:
#[.#]:第一個數字控制顯示的寬度;第二個#表示小數點後的精確度;
%3.1f
#-: 左對齊
+:顯示數值的符號
4、運算子
算術運算子:
x+y, x-y, x*y, x/y, x^y, x%y
#-x
+x: 轉換為數值;
字串運算子:沒有符號的運算符,字串連接
賦值運算子:
=, +=, -=, *=, /=, %=, ^=
++, --
比較運算子:
>, > =, <, <=, !=, ==
#模式匹配:
##~:是否符合
!~:是否不符合
邏輯運算子:
#&&
||
!
函數呼叫:
function_name(argu1, argu2, ...)
##條件式:
selector?if-true-expression:if-false-expression
# awk -F: '{$3> =1000?usertype="Common User":usertype="Sysadmin or SysUser";printf "%15s:%-s\n",$1,usertype}' /etc/passwd
#5、PATTERN
(1) empty:空模式,符合每一行;
(2) /regular expression/:僅處理能夠被此處的模式匹配到的行;
(3) relational expression: 關係式;結果有「真」有「假」;結果為「真」才會被處理;
真:結果為非0值,非空字串;
(4) line ranges:行範圍,
startline,endline :/pat1/,/pat2/
注意: 不支援直接給出數字的格式
~] # awk -F: '(NR>=2&&NR<=10){print $1}' /etc/passwd
(5) BEGIN/END模式
#BEGIN{}: 僅在開始處理文件中的文字之前執行一次;
#END{}:僅在文字處理完成之後執行一次;
6、常用的action
#(1) Expressions
(2) Control statements:if, while等;
(3) Compound statements:組合語句;
(4) input statements
(5) output statements
7、控制語句
if(condition) {statments}
if(condition) {statments} else {statements}
while(conditon) {statments}
do {statements} while(condition)
for(expr1;expr2;expr3) {statements }
break
continue
delete array[index]
delete array
exit
{ statements }
7.1 if-else
語法:if(condition) statement [else statement]
~]# awk -F: '{if($3>=1000) {printf "Common user: %s\n",$1} else {printf "root or Sysuser: %s\n", $1}}' /etc/passwd
~]# awk -F: '{if($NF=="/bin/bash") print $1 }' /etc/passwd
~]# awk '{if(NF>5) print $0}' /etc/fstab
~]# df -h | awk -F[%] '/^\/dev/{print $1}' | awk '{if($NF>=20) print $1}'
使用場景:對awk所取得的整行或某個欄位做條件判斷;
7.2 while循環
語法:while(condition) statement
條件“真”,進入循環;條件“假”,退出循環;
使用場景:對一行內的多個字段逐一類似處理時使用;對數組中的各元素逐一處理時使用;
~]# awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {print $i,length($i); i++}}' /etc/grub2.cfg
#~]# awk '/^[[:space:] ]*linux16/{i=1;while(i<=NF) {if(length($i)>=7) {print $i,length($i)}; i++}}' /etc/grub2. cfg
7.3 do-while迴圈
語法:do statement while(condition)
意義:至少執行一次迴圈體
#7.4 for迴圈
語法:for( expr1;expr2;expr3) statement
for(variable assignment;condition;iteration process) {for-body}
#~]# awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i,length($i)} }' /etc/grub2.cfg
特殊用法:
能夠遍歷數組中的元素;
語法:for(var in array) {for-body}
#
7.5 switch語句
語法:switch(expression) {case VALUE1 or /REGEXP/: statement; case VALUE2 or /REGEXP2/: statement; . ..; default: statement}
7.6 break和continue
break [n]
#continue
7.7 next
提前結束對本行的處理而直接進入下一行;
~]# awk -F: '{if($3%2!=0) next; print $1,$3 }' /etc/passwd
8、array
關聯陣列:array[ index-expression]
index-expression:
(1) 可使用任意字串;字串要使用雙引號;
(2) 如果某數組元素事先不存在,在引用時,awk會自動建立此元素,並將其值初始化為「空串」;
若要判斷數組中是否存在某元素,要使用"index in array"格式進行;
weekdays[mon]="Monday"
#若要遍歷陣列中的每個元素,要使用for迴圈;
for(var in array) {for-body}
#~]# awk 'BEGIN{weekdays["mon"] ="Monday";weekdays["tue"]="Tuesday";for(i in weekdays) {print weekdays[i]}}'
#注意:var會遍歷array的每個索引;
state["LISTEN"]++
state["ESTABLISHED"]++
~]# netstat -tan | awk '/^tcp\>/{state[$NF]++}END{for(i in state ) { print i,state[i]}}'
~]# awk '{ip[$1]++}END{for(i in ip ) {print i,ip[i]}}' /var/log/httpd/access_log
#1:統計/etc/fstab檔案中每個文件系統類型出現的次數;
~]# awk '/^UUID/{fs[$3]++}END{for(i in fs) {print i,fs[i ]}}' /etc/fstab
2:統計指定檔案中每個單字出現的次數;
~]# awk '{for(i=1;i<=NF;i++){count[$i]++}}END{for(i in count) {print i,count[i]}}' / etc/fstab
9、函數
9.1 內建函數
數值處理:
rand():傳回0和1之間一個隨機數字;
#字串處理:
length([s]):傳回指定字串的長度;
sub(r, s,[t]):以r表示的模式來找出t所表示的字元中的匹配的內容,並將其第一次出現替換為s所表示的內容;
gsub(r,s,[t]):以r表示的模式來找出t所表示的字元中的匹配的內容,並將其所有出現均替換為s所表示的內容;
split(s,a[,r]):以r為分隔符號切割字元s,並將切割後的結果儲存至a所表示的陣列中;
~]# netstat -tan | awk '/^tcp\>/{split($5,ip,":");count[ip[1] ]++}END{for (i in count) {print i,count[i]}}'
#9.2 自訂函數
《sed與awk》
########## ########################################################### ################
#
####### #### ####################################################### ####DNF新一代的RPM 套件管理器。 ###DNF套件管理器克服了YUM套件管理器的一些瓶頸,提升了包括使用者體驗、記憶體佔用、依賴分析、運行速度等多方面的內容。使用RPM、libsolv和hawkey 函式庫進行套件管理操作。發行版版本號是 1.0,發行日期是 2015 年 5 月 11 日。 #############YUM 的依賴解析是一場噩夢,在DNF 中使用SUSE 庫“libsolv”和Python 包裝器以及C Hawkey 進行了解決。文檔化的API。一個耗時的過程.############################################ ##### ############################################## ####### ############################################ ######### ########################################## #######