天天看點

Day01 Shell腳本程式設計一、shell環境及特性二、Shell腳本設計三、寫腳本四、變量五、單引号&雙引号&反引号

解釋器:負責向核心翻譯及傳達使用者/程式指令

解釋器 車

shell 汽車

bash 寶馬、奔馳、法拉利

檔案裡面的内容就是系統已安裝的解釋器

修改老使用者的預設解釋器

建立新使用者時指定預設解釋器

ctrl+l清屏

ctrl+c終止目前運作的程式

ctrl+a移動光标到行首

ctrl+e移動光标到行尾

ctrl+w删除目前光标前面的一個單詞

esc+d删除目前光标後面的一個單詞

ctrl+u删除目前光标到行首的所有内容

ctrl+k删除目前光标到行尾的所有内容

ctrl+f向前移動一個字元

ctrl+b向後移動一個字元

alt+b 向前移動一個單詞

alt+f 向後移動一個單詞

RHEL7.2才支援補齊選項,老版本可通過bash-completion包提供選項補齊的功能

grep HISTSIZE /etc/profile#檢視曆史指令預設儲存條數

history | wc -l#檢視目前使用了多少條指令

!100#執行第100條指令

!cat#從後到前,查找最近執行的cat指令

history -c#清除曆史指令

~/.bash_history

alias

unalias

/etc/bashrc

~/.bashrc

标準輸出&1

錯誤輸出&2

标準輸入&0

對腳本來說,重定向非常重要,相當于給執行腳本做了個日志記錄

1>正确輸出 1>>正确追加輸出

2>錯誤輸出 2>>錯誤追加輸出

&>将正常輸出、錯誤輸出重定向同一個檔案

/dev/null 2>&1 相當于1>/dev/null 2>/dev/null。是将标準出錯重定向到标準輸出,最後一個&表示取标準裝置。 echo 'error' >&2 把echo出來的結果 重定向到 錯誤輸出. <重定向輸入 在linux裡面管道非常重要!!! 把前一個指令的輸出作為給後面的指令的輸入 因為linux指令設計的原則是3S(simple、small、speed),軟體越大啟動越慢、漏洞越多。管道具體使用上就是用來組合多個指令,來實作複雜的功能 yum list|grep abc|wc -l echo "content" | mail -s "title" receipt 缺點是郵件内容不能寫太多,優點是不用另外建立檔案 mail -s "title" receipt < mail.txt 缺點是需要先建立檔案,優點是可以寫很多内容 擴充名是.sh 頂格第一行必須是#!/bin/bash,表示該腳本指定由bash作為腳本解釋器 #為注釋符,注釋可以寫時間、版本、功能、聯系人 chmod +x 腳本名 ./腳本名#相對路徑 /root/腳本名#絕對路徑 bash 腳本名#指定解釋器,即使腳本沒有執行權限,也同樣能執行腳本 上面的執行方式都會開啟子程序 但是注意!source 腳本名是不會開啟子程序的。 在特例中,比如腳本中隻有一行exit,執行腳本後會退出目前bash

$PATH 指令搜尋路徑

#!/bin/bash

echo "hello the word"

if [ -d /etc/yum.repos.d ];then

rm -fr /etc/yum.repos.d/*

echo '[dvd]

name=rhel

gpgcheck=0' >/etc/yum.repos.d/dvd.repo

else

mkdir -p /etc/yum.repos.d/

fi

yum clean all >/dev/null

yum -y install vsftpd 2>/var/log/ins_vsftpd_err.log >/dev/null

systemctl restart vsftpd && systemctl enable vsftpd >/dev/null

read -p "請輸入使用者名:" name

#關閉回顯

stty -echo

read -p "請輸入密碼:" pass

#打開回顯

stty echo

useradd $name

echo $pass | passwd --stdin $name

echo '03 03 5 tar -czf /root/log-$(date+%F).tar.gz /var/log' >>/var/spool/cron/root

思路:如何檢測登入使用者數量?如何判斷大于2?如何發郵件?

#判斷本機登入的使用者數是否大于2,如果大于2,則發郵件給root

num=<code>who|wc -l</code>

[ $num -gt 2 ] &amp;&amp; mail -s Error root &lt;/root/mail.txt

#mail.txt是要發的郵件内容

[ -d /root/cd ] &amp;&amp; mount /ISO/rhel7.iso /cd || mkdir /cd;mount /ISO/rhel7.iso /cd

[ -d /root/cd ] || mkdir /cd &amp;&amp; mount /ISO/rhel7.iso /cd

[ ! -d /root/cd ] &amp;&amp; mkdir /cd;mount /ISO/rhel7.iso /cd

思路:隻關心最後得出的和。如何輸出1..100?輸出的值存入另一個變量?另一個變量存儲最後得出的和

j=0

for i in {1..100}

do

let j+=i

done

echo $j

思路:如何顯示每個檔案?如何打包并儲存?

for n in <code>ls /var/log</code>

tar -zcf /tmp/$n.tar.gz /var/log/$n &amp;&gt;/dev/null

思路:讀取鍵盤輸入?求和并存在另一個變量内?如果輸入0則結束循環并輸出和

RESULT=0

while :

read -p "請輸入一個數[0結束]:" NUM

[ $NUM -eq 0 ] &amp;&amp; break

let RESULT+=$NUM

echo $RESULT

實際螢幕輸出:

11=1

21=2 22=4

31=3 32=6 33=9

......

91=9 92=18 93=27 94=36 95=45 96=54 97=63 98=72 9*9=81 

思路:i={1..9} j={?} 要打出三角形,核心是i&lt;=j

腳本:

for j in {1..9}

for i in {1..9}

echo -en "$i$j=$[ij]\t"

[ $i -eq $j ] &amp;&amp; break

echo

for i in <code>seq $j</code>

思路:棋盤的格式是黑白相間

for n in {1..4}

for i in {1..4}

echo -en "\033[44m \033[0m"

echo -en "\033[45m \033[0m"

for j in {1..4}

更優秀的代碼:

color(){

echo -en "\033[4$1m \033[0m"

echo -en "\033[4$2m \033[0m"

}

for i in {1..8}

y=$[i%2]

[ $y -eq 1 ] &amp;&amp; color 7 0 || color 0 7

思路:前一天的數量y等于今天的數量(x+1)2

x=1

x=$[(x+1)2]

思路:如何計算1+...x的和?不輸入值該如何處理?

sum=0

read -p "請輸入一個數:" num

num=${num:-100}

for i in <code>seq $num</code>

do 

let sum+=i 

done 

echo "從1到${num}的求和值為:$sum"

exit

思路:num1存最小值,num2存中間,num3存最大值,tmp作為中間變量。有多少種可能呢?

num1&gt;num2&gt;num3

num1&lt; num2&lt; num3

num2 &lt; num3

num2

首先if判斷num1和num2比大小。如果num1大,則把num1和num2交換,保證num1存放的是小值;如果num2大,則不做操作,結束這個判斷

然後再來個if判斷num1和num3比大小。如果num1大,則把num1和num3交換,保證num1存放的是最小值;如果num3大,則不做操作,結束這個判斷

最後的if判斷num2和num3比大小。如果num2大,則把num2和num3交換,保證num3存放的是最大值;如果num3大,則不做操作,結束這個判斷。

從小到大輸出$num1 $num2 $num3

#num1存最小值,num2存中間,num3存最大值

num1=$RANDOM

num2=$RANDOM

num3=$RANDOM

tmp=0

if [ $num1 -gt $num2 ];then

tmp=$num2;num2=$num1;num1=$tmp

if [ $num1 -gt $num3 ];then

tmp=$num1;num1=$num3;num3=$tmp

if [ $num2 -gt $num3 ];then

tmp=$num3;num3=$num2;num2=$tmp

echo $num1 $num2 $num3

以固定名稱來存放可能會變化的值

若指定的變量名存在,則相當于給變量指派

等号兩邊不能有空格

隻能用數字、字母和下劃線組成

不能以數字開頭

變量名=變量值

FROM=/etc/

read -p "提示" 變量名#隻定義變量名,不指派。由使用該指令的人來指派

使用位置變量$1、$2等

通過管道|把前面指令的輸出作為現在指令的輸入

$FROM

echo $FROM

echo ${FROM}

配置檔案:/etc/profile、~/.bashrc

PATH

HOME

USER

UID

HOSTNAME

PS1 一級提示符

PS2 二級提示符

$0:腳本自身的名字

$1:位置變量1

$2:位置變量2

$:所有變量

$ @ :所有變量。

$和$@都表示傳遞給函數或腳本的所有參數,不被雙引号(" ")包含時,都以"$1" "$2" … "$n" 的形式輸出所有參數。 

但是當它們被雙引号(" ")包含時,"$*" 會将所有的參數作為一個整體,以"$1 $2 … $n"的形式輸出所有參數;"$@" 會将各個參數分開,以"$1" "$2" … "$n" 的形式輸出所有參數。

$#:所有變量的數量

$$:腳本運作後的PID

$!:顯示最後一個被放到背景的程序PID

$?:上一條指令執行狀态,值等于0為正确,值非0就是錯誤

自定義變量預設就是局部變量

存在于腳本函數(function)中的變量也是局部變量。

要以 local 變量名方式進行聲明,使之隻在本函數作用域内有效,防止變量在函數中的命名與變量外部程式中變量重名造成程式異常。

局部變量預設隻在目前shell環境中有效,無法在子shell環境中使用

可以通過export指令将局部變量聲明為全局變量

系統變量預設就是全局變量

全局變量在目前shell環境及子、孫等shell環境中有效

/etc/profile

export 變量名#将局部變量聲明為全局變量

export -n 變量名#取消聲明

雙引号可以界定一個完整的字元串

echo a b

echo "a b"

單引号可以界定一個完整的字元串,而且可以屏蔽特殊符号($\ ),原封不動輸出。

<code>指令</code> 僅可以放指令,提取的是指令的結果

$(指令) 僅可以放指令,提取的是指令的結果

本文轉自 goldwinner 51CTO部落格,原文連結:http://blog.51cto.com/355665/2068827,如需轉載請自行聯系原作者