shell_01基本操作 什麼是Shell shell的念shell是一個命令直譯器echo $SHELL --通過環境變數cat /etc/shells--查看當前註冊至系統的shellshell的切換1、臨時切換# /bin/ksh 2、固定切換# vim /etc/passwd--檔案中的最後一個欄位# chsh -s /sbin/nologin username# usermod -s /bin/bash username 子shell 開啟關閉# /bin/bash# bin/kshforks --複製進程資訊,繼承父shell的定義exec --通過exec開啟子shell 為什麼使用shell解決重複操作的作業節約時間,提高工作效率功能強大不需要編譯 shell指令碼的基本元素#!<命令直譯器># --為注示shell命令流程式控制制(if/for/while/utile/case/function) man BASH_BUILTINS• shell的曆史 • 常見的Shell• Bourne Shell 最早出現的Shell的一種,大多數Unix的預設Shell,粗糙切缺乏任務控制 • nash-->initrd.img(init)• not a shell , 它不是一個SHELL,是一個設計的儘可能小的簡單命令直譯器。主要用於初始化RAM DISK時候解釋裡面的linuxrc或者init這些簡單的指令碼 • csh• 加州大學Berkeley分校作為其Unix實現的一部分而發展來的,目前最流行的互動式Shell。具有許多特性,比如任務控制、記錄,但CShell不適合編寫指令碼,並有許多潛在的缺陷• 臭名昭著的錯誤• 使用者不能進行檔案描述符的處理• 使用者不能用任何恰當的方法將內部命令放在一起,通過管道也不可以• 不可以將流量控制和命令放在一起• 某些命令看起來合理,可就是運行不了 • tcsh• C shell的擴充版本,去除了C shell中臭名昭著的錯誤 • ksh• Korn shell , 其與Bourne shell 相容,並具備C shell的大部分特性,以及象曆史編輯、重用舊命令並執行前編輯這些命令的能力。從對編程穩定性上它比csh可靠。 • bash• Bourne-again shell, 由自由軟體基金會開發,吸收了以上所有Shell好的特性,並被開源作業系統廣泛使用 • 內部命令和外部命令• Shell不需要啟動一個單獨的進程來運行內部命令• Shell需要建立(fork)和執行(exec)一個新的子進程來運行外部命令• 盡量使用內部命令有助於效能的提升 bash-->cd --解析內部命令的流程bash-->forks-->bash(子進程)-->ls --解析外部命令的流程 # type ls --外部命令ls is aliased to `ls --color=tty' # type cd --內部命令cd is a shell builtin 檔案名稱• 你可以用任何你認為合適的可見字元或不可見字元為檔案或目錄命名,但不要給自己找麻煩• 從安全和方便角度• 大小寫字元• 底線• 圓點• 逗號• 盡量不要出現“空格”• 副檔名• 方便分類,非必須• 命令通過檔案內結構判斷其類型(file) -type c File is of type c: b block (buffered) special c character (unbuffered) special d directory p named pipe (FIFO) f regular file l symbolic link; this is never true if the -L option or the -fol- low option is in effect, unless the symbolic link is broken. If you want to search for symbolic links when -L is in effect, use -xtype. s socket D door (Solaris) 萬用字元• ? 任意單個字元,不能匹配空• * 任意零個或多個字元組(不能匹配以點開頭的檔案)• [ab] a或者b• [a-z] a到z之間的任一字元,包括端點在內• 是Shell 而非命令本身處理萬用字元,命令後的萬用字元會在命令執行前就被代換了• 如果需要命令而非Shell處理萬用字元,請用“\"將萬用字元轉義,跳脫字元 # ll /dev/sd?brw-r----- 1 root disk 8, 0 03-14 09:03 /dev/sda # ll /dev/sd*-rw-r--r-- 1 root root 0 03-14 11:30 /dev/sdbrw-r----- 1 root disk 8, 0 03-14 09:03 /dev/sdabrw-r----- 1 root disk 8, 1 03-14 09:03 /dev/sda1brw-r----- 1 root disk 8, 2 03-14 09:03 /dev/sda2brw-r----- 1 root disk 8, 3 03-14 09:03 /dev/sda3brw-r----- 1 root disk 8, 4 03-14 09:03 /dev/sda4brw-r----- 1 root disk 8, 5 03-14 09:03 /dev/sda5 # ll /dev/sd?[1-5]brw-r----- 1 root disk 8, 1 03-14 09:03 /dev/sda1brw-r----- 1 root disk 8, 2 03-14 09:03 /dev/sda2brw-r----- 1 root disk 8, 3 03-14 09:03 /dev/sda3brw-r----- 1 root disk 8, 4 03-14 09:03 /dev/sda4brw-r----- 1 root disk 8, 5 03-14 09:03 /dev/sda5 # ll /dev/tty[1-5][0-9] # ll /dev/sda[13]brw-r----- 1 root disk 8, 1 03-14 09:03 /dev/sda1brw-r----- 1 root disk 8, 3 03-14 09:03 /dev/sda3 # ll /dev/sda[1-3]brw-r----- 1 root disk 8, 1 03-14 09:03 /dev/sda1brw-r----- 1 root disk 8, 2 03-14 09:03 /dev/sda2brw-r----- 1 root disk 8, 3 03-14 09:03 /dev/sda3 轉義# touch test\*\?\[\].sh 跳脫字元# ls \> /root\> a\> /b bash中的引號:雙引號 “ ” :允許通過$符號引用其他變數值,會把引號的內容當成整體來看待單引號 ‘ ’ :禁止引用其他變數值,shell中特殊符號都被視為一般字元,會把引號的內容當成整體來看待反撇號 `` : $() 在執行命令的過程中會優先執行 ; 可對一行命令進行分割,在執行過程中不考慮上一個命令執行是否是正確的&& 可對一行命令進行分割,在執行過程中考慮上一個命令執行是否是正確的||! 命令曆史 # echo "This system is "HOSTNAME""This is system is HOSTNAME# echo "This system is "$HISTNAME""This is system is # echo "This system is "$HOSTNAME""This is system is desktop8.example.com# echo 'This system is "$HOSTNAME"'This is system is "$HOSTNAME" [root@desktop8 ~]# echo $5.00.00[root@desktop8 ~]# echo \$5.00$5.00 # host=`ifconfig eth0 |grep 'inet addr'|cut -d : -f2|cut -d ' ' -f1`# host2=$(ifconfig eth0 |grep 'inet addr'|cut -d : -f2|cut -d ' ' -f1) $(()) :運算子$[] # a=$((1 + 10))# echo $a # a=$[1 + 100]# echo $a • shell的設定檔(軟體+設定檔)• csh• $HOME/.cshrc• 登入時執行$HOME/.login• 登出時執行$HOME/.logout • bash使用者載入shell配置流程:# user01-->login-->bash-->/etc/profile-->$HOME/.bash_profile-->$HOME/.bashrc-->/etc/bashrc 全域設定檔:/etc/profile --bash工作環境的配置(環境變數)/etc/profile.d/*.sh --/etc/profile的擴充設定檔/etc/bashrc --bash的設定檔 針對每個使用者的設定檔:$HOME/.bash_history --存放命令曆史$HOME/.bash_logout --登出/退出shell的時候執行的指令碼$HOME/.bash_profile $HOME/.bashrc 命令的編輯ctrl + u --刪除當前游標至行首內容ctrl + k --刪除當前游標至行尾內容ctrl + c --中斷ctrl + l --清屏ctrl + a --跳到行首HOMEcrtl + e --路到行尾ENDctrl + r --快速搜尋history命令ctrl + z --轉入後台運行 fg bgCtrl + d --退出shell,logout ↑(Ctrl+p) 顯示上一條命令 ↓(Ctrl+n) 顯示下一條命令 alias --查詢系統中所有已經存在的別名alias 別名=‘真名’ unalias --取消系統中的別名unalias 別名unalias -a 刪除所有的別名臨時:alias la='ls -a'固定:可以寫至以下檔案,定義完成需要使用source來重新整理,或者登出重新登入使用者:/etc/profile$HOME/.bash_profile$HOME/.bashrc/etc/bashrc/etc/profile.d/*.sh 命令曆史:HISTSIZE=1000 設定命令曆史的條數history 查詢目前使用者用過的所有命令曆史(記憶體)cat $/HOME/.bash_history | grep xx(硬碟)history -w 同步記憶體中的命令至硬碟($/HOME/.bash_history)自動同步:exit/登出history -cecho "" > $HOME/bash_history--清空命令曆史 # :> $HOME/bash_history 調用命令曆史: !101 通過編號!! 調用最後一條命令曆史!vim 調用離我最近一條以vim開頭的命令曆史!$ 調用最後一條命令曆史中的參數命令字 + [選項] + 參數ls -l /ctrl + r 尋找命令曆史 bash的特殊符號:< << > >> &> | 標準輸入 0 標準正確輸出(螢幕) 1 錯誤輸出 (螢幕) 2# ls -l /dev/std*lrwxrwxrwx. 1 root root 15 Aug 3 09:34 /dev/stderr -> /proc/self/fd/2lrwxrwxrwx. 1 root root 15 Aug 3 09:34 /dev/stdin -> /proc/self/fd/0lrwxrwxrwx. 1 root root 15 Aug 3 09:34 /dev/stdout -> /proc/self/fd/1 <<herestring --非互動模式進行輸入追加重新導向# cat > a3.txt <<END> gfdsjkgfdjgkldf> fdsfdsfds> fdsfdsf> END > --輸出覆蓋重新導向 >> --輸出追加重新導向 2> --錯誤覆蓋輸出重新導向 2>> --錯誤追加輸出重新導向 &> --輸出正確/錯誤重新導向&>> --RHEL6可以實現正確和錯誤追加重新導向。>> --- 2>&1 rhel5# cat /root/a2.txt /root &> a.txt --將正確和錯誤一起覆蓋重新導向至a.txtcat /root/a2.txt /root >> a.txt 2>&1 --將正確和錯誤一起追加重新導向至a.txt[root@i ~]# ls /ttttt /etc/passwd- >1.txt 2>2.txt && &>3.txt | 管道 cat /etc/passwd |grep root |grep ^root --把passwd輸出結果通過管道交給第二個命令去處理,往後的以此類推 • bash shell的基本變數和使用變數的設定引用範圍刪除變數 • 設定變數• VARNAME=VAR_VALUE--變數名中的字母建議大寫--變數名起始字元不能是資料或者特殊符號 變數名 變數值 • readonly VARNAME--設定唯讀變數,不能刪除不能更改 • read --通過斷點設定變數• read -p "請輸入一個值(數字):" a read -t 5 "請輸入一個值:"IP--設定賦值的逾時時間。#H=192.168.0.253 #echo $H192.168.0.253#read -p "Please enter ip address: " H2Please enter ip address: 192.168.0.252#echo $H2192.168.0.252• 引用變數• echo $VARNAME• echo ${VARNAME} 範圍• 全域變數(父子shell)• export• . 或 source 調用• 局部變數• 程式內變數• 函數內變數 刪除變數:• unset VARNAME 使用者自訂變數:host=192.168.0.1ping $host 環境變數 --(使用者工作環境)set --都可以查,但set還可以顯示使用者自訂變數env --查看環境變數 PATH• 使用者命令搜尋路徑 PWD使用者目前的目錄的絕對路徑 HOME• 包含使用者主目錄的絕對路徑 SHELL• 使用者登入shell的絕對路徑 USER或LOGNAME• 使用者名稱,在登入後自動化佈建並不會改變 PS1• 主提示符組態變數 # PS1="[\u@\H \t \w]\$" PS2• 複合命令提示字元組態變數 PS1和PS2提示符變數,用於設定提示符格式PS1是用於設定一級Shell提示符的環境變數,也稱為主提示符字串,即改變: [root @jselab ~]#PS1變數是[\u@\h \W]\$,\u、\h、\W和\$表示了特定含義,\u表示目前使用者名,\h表示表示主機名稱,\W表示目前的目錄名,如果是root使用者,\$表示#號,其他使用者,\$則表示$號PS2是用於設定二級Shell提示符的環境變數 \d 以“周 月 日”格式顯示的日期\H 主機名稱和網域名稱\h 主機名稱\s Shell的類型名稱\T 以12小時制顯示時間,格式為:HH:MM:SS \t 以24小時制顯示時間,格式為:HH:MM:SS \@ 以12小時制顯示時間,格式為:am/pm \u 當前的使用者名稱\v bash Shell的版本號碼\V bash Shell的版本號碼和補丁號\w 當前工作目錄的完整路徑\W 當前工作目錄名字\# 當前命令的序號\$ 如果UID為0,列印#;否則,列印$ 內建bash中變數$#:命令列中位置變數的個數$*:所有位置變數的內容$@: 所有位置參數的內容,與$*的分割任不一樣,建議和所有的位置參數時使用這種方式。$?:上一條命令執行後返回的狀態,當返回狀態值為0時表示執行正常,非0值表示執行異常或出錯$$:當前所在進程的進程號$!:後台啟動並執行最後一個進程號$0:當前執行的進程/程式名# ls &> /dev/null && echo YESYES # fdsfds &> /dev/null && echo YES --無返值 位置變數:• $0~$9,${10} $* $#等使用和迴圈選取#!/bin/bashecho "\$0 = $0 "echo "\$1 = $1 "echo "\$2 = $2 "echo "\$3 = $3 "echo "\$4 = $4 "echo "\$5 = $5 "echo "\$6 = $6 "echo "\$7 = $7 "echo "\$8 = $8 "echo "\$9 = $9 "echo "\$10 = ${10} "echo "\$11 = ${11} "echo "\$* = $* "echo "\$# = $# " • $0~$9 位置參數變數• ${10}~${n} 擴充位置參數變數 #./aa.sh 1 2 3 4 5 6 7 8$0 = ./aa.sh $1 = 1 $2 = 2 $3 = 3 $4 = 4 $5 = 5 $6 = 6 $7 = 7 $8 = 8 $9 = $10 = $11 = $* = 1 2 3 4 5 6 7 8 $# = 8 有類型變數• 預設bash將變數設定為文本值,當使用算數方法時會自動將其轉換為整數值• 內建命令declare可以修改變數屬性• declare參數-a 將變數看成數組-f 只使用函數名-F 顯示未定義的函數名-i 將變數看成整數-r 使變數唯讀-x 標記變數通過環境匯出-r:# h=192.168.0.1# declare -r h等同於:# readonly h -x:# H=192.168.0.100# declare -x H# export --可以查詢所有全域變數 -i• 例子# varA=3 # varB=7# result_out=varA*varB# echo $result_outvarA*varB # declare -i varC=3 varD=7# declare -i declare_result_out# declare_result_out=varC*varD# echo $declare_result_out21• 數組• 數組類似於儲存取值的一個排列排列中每個位置稱為元素每個元素通過數字下標訪問• 數組元素可以包含字串或數字• 數組下標從0開始• 數組可以使用 declare a 來顯示聲明, 數組下標的範圍沒有任何限制 , 同時也不必使用連續的分量。可以通過 ${ array [i]}. 訪問數組中的元素。如果不指定元素,則表示第一個元素。 @ 與 * 相同,但是使用時加引號,並在引號中返回每個參數, *則作為一個整體的字串返回。 (1) name = (value1 ... valuen) 此時下標從 0 開始,也可以: names=([2]=alice [0]=hatter [1]=duchess)。 (2) name[index] = value # A=(a b c def) # echo ${A[@]} a b c def # echo ${A} a echo ${A[*]} a b c def for i in "${A[@]}"; do echo $i done 顯示的結果: a b c def for i in "${A[*]}"; do echo $i done 顯示結果: a b c def // 清除變數 $ unset A$ echo ${A[@]}$ A=B B=C unset $A 事實上所取消的變數是 B 而不是 A // 清空變數 , 即將值變為空白 $ A=$ echo ${A[@]}$ 指令碼執行:1、指令碼無可執行許可權:# /bin/sh /xx/xx.sh--開啟一個新的子shell去執行指令碼,指令碼不需要可執行許可權# /bin/bash /xx/xx.sh # source /xx/xx.sh--強制在當前的shell執行指令碼# . /xx/xx.sh 2、指令碼擁有可執行許可權# chmod +x /xx/xx.sh# /xx/xx.sh