shell腳本編程

bash的配置文件

用戶登錄系統(tǒng)后,會(huì)啟動(dòng)一個(gè)接口程序,也稱shell程序,一般默認(rèn)是bash,而這個(gè)程序的啟動(dòng),需要讀取配置文件,完成環(huán)境的配置,以便用戶在該接口程序下方便的執(zhí)行一系列操作

配置文件的種類:

根據(jù)配置文件中定義的內(nèi)容,將配置文件分為兩大類

profile類:為交互式登錄的shell進(jìn)程提供配置

用于定義環(huán)境變量,啟動(dòng)需要執(zhí)行的命令或者腳本

  • /etc/profile: 全局設(shè)置

  • /etc/profile.d/*.sh

  • ~/.bash_profile: 個(gè)人設(shè)置(僅對(duì)當(dāng)前用戶有效)

bashrc類:為非交互式登錄的shell進(jìn)程提供配置

用于定義命令別名或本地變量

  • /etc/bashrc:全局設(shè)置
  • ~/.bashrc:個(gè)人設(shè)置

配置文件的加載順序

交互式登錄

直接通過某終端輸入賬號(hào)和密碼后登錄打開的shell進(jìn)程;
使用su命令:su - USERNAME, 或者使用 su -l USERNAME執(zhí)行的登錄切換;

順序:/etc/profile-->/etc/profile.d/*.sh-->/.bash_profile-->~/.bashrc-->/etc/bashrc

非交互式登錄

su USERNAME執(zhí)行的登錄切換;
圖形界面下打開的終端;
運(yùn)行腳本

順序:~/.bashrc-->/etc/bashrc-->/etc/profile.d/*.sh

  • 命令行中定義的特性,例如變量和別名作用域?yàn)楫?dāng)前shell進(jìn)程的生命周期;
  • 配置文件定義的特性,只對(duì)隨后新啟動(dòng)的shell進(jìn)程有效;

讓通過配置文件定義的特性立即生效:
(1) 通過命令行重復(fù)定義一次;
(2) 讓shell進(jìn)程重讀配置文件;

~]# source /PATH/FROM/CONF_FILE
~]# . /PATH/FROM/CONF_FILE


shell腳本編程

過程式編程,解釋運(yùn)行,依賴于外部程序文件運(yùn)行

編程語言的分類:根據(jù)運(yùn)行方式

  • 編譯運(yùn)行:源代碼 --> 編譯器 (編譯)--> 程序文件;
  • 解釋運(yùn)行:源代碼 --> 運(yùn)行時(shí)啟動(dòng)解釋器,由解釋器邊解釋邊運(yùn)行;

根據(jù)其編程過程中功能的實(shí)現(xiàn)是調(diào)用庫還是調(diào)用外部的程序文件:

編程模型:過程式編程語言,面向?qū)ο蟮木幊陶Z言

過程式:以指令為中心來組織代碼,數(shù)據(jù)是服務(wù)于代碼;

  • 順序執(zhí)行
  • 選擇執(zhí)行
  • 循環(huán)執(zhí)行
    代表:C,bash

對(duì)象式:以數(shù)據(jù)為中心來組織代碼,圍繞數(shù)據(jù)來組織指令;
類(class):實(shí)例化對(duì)象,method;
代表:Java, C++, Python

數(shù)據(jù)類型:字符型,數(shù)值型
弱類型:字符型

shell腳本格式:

腳本文件的第一行,頂格:給出shebang(解釋器路徑),用于指明解釋執(zhí)行當(dāng)前腳本的解釋器程序文件

常見的解釋器:
#!/bin/bash
#!/usr/bin/python
#!/usr/bin/perl

注意:代碼需要加注釋,如空白行,縮進(jìn),所有#開頭的為注釋行

文本編程器:nano
行編輯器:sed
全屏幕編程器:nano, vi, vim

shell腳本是命令的堆積,但很多命令不具有冪等性,需要用程序邏輯來判斷運(yùn)行條件是否滿足,以避免其運(yùn)行中發(fā)生錯(cuò)誤;

運(yùn)行腳本:

  • 賦予執(zhí)行權(quán)限,并直接運(yùn)行此程序文件;
    chmod +x /PATH/TO/SCRIPT_FILE
    /PATH/TO/SCRIPT_FILE

  • 直接運(yùn)行解釋器,將腳本以命令行參數(shù)傳遞給解釋器程序;
    bash /PATH/TO/SCRIPT_FILE

注意:腳本中的空白行會(huì)被解釋器忽略;
腳本中,除了shebang,余下所有以#開頭的行,都會(huì)被視作注釋行而被忽略;此即為注釋行;
shell腳本的運(yùn)行是通過運(yùn)行一個(gè)子shell進(jìn)程實(shí)現(xiàn)的;

練習(xí)1:寫一個(gè)腳本,實(shí)現(xiàn)如下功能;
(1) 顯示/etc目錄下所有以大寫p或小寫p開頭的文件或目錄本身
(2) 顯示/var目錄下的所有文件或目錄本身,并將顯示結(jié)果中的小寫字母轉(zhuǎn)換為大寫后顯示
(3) 創(chuàng)建臨時(shí)文件/tmp/myfile.XXXX

#!/bin/bash
ls -d /rtc/[pP]*
ls -d /var/* | 'a-z' 'A-Z'
mktemp /tmp/myfile.XXXX

ctrl+o:保存
ctrl+x:退出

腳本的狀態(tài)返回值:

默認(rèn)是腳本中執(zhí)行的最后一條件命令的狀態(tài)返回值

[root@centos7 ~]# id usr3 &> /dev/null && exit 0 || useradd usr3
logout
There are stopped jobs.
useradd: user 'usr3' already exists

自定義狀態(tài)退出狀態(tài)碼:
exit [n]:n為自己指定的狀態(tài)碼;
注意:shell進(jìn)程遇到exit時(shí),即會(huì)終止,因此,整個(gè)腳本執(zhí)行即為結(jié)束;

shell腳本的參數(shù)傳遞

位置參數(shù)變量

執(zhí)行腳本和執(zhí)行命令一樣,在腳本后加上多個(gè)參數(shù),用空格隔開即可,例如myscript.sh argu1 argu2

引用方式:

\$1, \$2, ..., \${10}, ${11}, ...

例如:

~]#vim sum.sh
#!/bin/bash
#
echo $[$1+$2]
輪替:

shift [n]:位置參數(shù)輪替;

~]#vim shift.sh
#!/bin/bash
#
echo "First pos argu: $1"
shift
echo "Second pos argu: $1"
~]# bash shift.sh one two


~]#vim shift.sh
#!/bin/bash
#
echo "First and second pos argu: $1, $2"
shift 2
echo "Third pos argu: $1"
~]# bash shift.sh one two three              

練習(xí):寫一腳本,通過命令傳遞兩個(gè)文本文件路徑給腳本,計(jì)算其空白行數(shù)之和

~]# vim lines.sh
   #!/bin/bash
   #
   file1_lines=$(grep "^$" $1 | wc -l)
   file2_lines=$(grep "^$" $2 | wc -l)

   echo "Total blank lines: $[$file1_lines+$file2_lines]"    
~]# bash lines.sh /etc.fstab /etc/issue

特殊變量

符號(hào) 含義
$0 腳本文件路徑本身
$# 腳本參數(shù)的個(gè)數(shù)
$* 所有參數(shù)
$@ 所有參數(shù)

shell腳本的用戶交互

用戶交互:通過鍵盤輸入數(shù)據(jù),從而完成變量賦值操作;
read[option] [name...]
-p“提示字符”
-t # 限定輸入時(shí)間

#!/bin/bash
#
read -p "Enter a username: " name
[ -z "$name" ] && echo "a username is needed." && exit 2

read -p "Enter password for $name, [password]: " password
[ -z "$password" ] && password="password"

if id $name &> /dev/null; then
   echo "$name exists."
else
   useradd $name
   echo "$password" | passwd --stdin $name &> /dev/null
   echo "Add user $name finished."
fi            

shell腳本的語法檢測(cè)

  • bash -n FILE,智能檢測(cè)出語法錯(cuò)誤,不能檢測(cè)出邏輯錯(cuò)誤
  • bash -x FILE 調(diào)試執(zhí)行

bash腳本編程之算術(shù)運(yùn)算: +,-,*,/, **, %

算術(shù)運(yùn)算格式:

  • let VAR=算術(shù)運(yùn)算表達(dá)式
  • VAR=$[算術(shù)運(yùn)算表達(dá)式]
  • VAR=$((算術(shù)運(yùn)算表達(dá)式))
  • VAR=$(expr $ARG1 $OP $ARG2)

注意:乘法符號(hào)在有些場(chǎng)景中需要使用轉(zhuǎn)義符;

變量賦值
增強(qiáng)型賦值:

變量做某種算術(shù)運(yùn)算后回存至此變量中;
let i=$i+#
let i+=#

如:+=,-=,*=, /=, %=

自增:
VAR=$[$VAR+1]
let  VAR+=1
let  VAR++
自減:
VAR=$[$VAR-1]
let  VAR-=1
let  VAR--

練習(xí):
1、寫一個(gè)腳本
計(jì)算/etc/passwd文件中的第10個(gè)用戶和第20個(gè)用戶的id號(hào)之和;

id1=$(head -10  /etc/passwd | tail -1  | cut  -d:  -f3)
id2=$(head -20   /etc/passwd | tail -1  | cut  -d:  -f3)

2、寫一個(gè)腳本
計(jì)算/etc/rc.d/init.d/functions和/etc/inittab文件的空白行數(shù)之和;

grep "^[[:space:]]*$"   /etc/rc.d/init.d/functions | wc -l

3、編寫腳本,實(shí)現(xiàn)自動(dòng)添加三個(gè)用戶,并計(jì)算三個(gè)用戶的UID之和

#!/bin/bash
#
id_sum=0
[ $# -lt 3 ] && echo "請(qǐng)輸入三個(gè)用戶:" && exit 1
for i in $* ;do
useradd $i && echo "${i}創(chuàng)建成功"
id_num=$(id -u $i)
id_sum=$[${id_sum}+${id_num}]
done
echo "三個(gè)用戶uid之和為: ${id_sum}"

[root@centos7 ~]# bash useradd.sh 1 2 3
useradd: invalid user name '1'
useradd: invalid user name '2'
useradd: invalid user name '3'
三個(gè)用戶uid之和為: 6

常用測(cè)試條件及控制語句

條件測(cè)試語句

判斷某需求是否滿足,需要由測(cè)試機(jī)制來實(shí)現(xiàn)

如何編寫測(cè)試表達(dá)式以實(shí)現(xiàn)所需的測(cè)試:

  • 執(zhí)行命令,并利用命令狀態(tài)返回值來判斷;

    0:成功
    1-255:失敗

  • 測(cè)試表達(dá)式

    test EXPRESSION
    [ EXPRESSION ]
    [[ EXPRESSION ]]

注意:EXPRESSION兩端必須有空白字符,否則為語法錯(cuò)誤;

bash的測(cè)試類型

數(shù)值測(cè)試:
符號(hào) 含義
-eq 是否等于
-ne 是否不等于
-gt 是否大于
-ge 是否大于等于
-lt 是否小于
-le 是否小于等于
字符串測(cè)試
符號(hào) 含義
== 是否等于
> 是否大于
< 是否小于
!= 是否不等于
=~ 左側(cè)的字符串是否被右側(cè)的patter所匹配
-z “string” 判斷指定的字符創(chuàng)是否為空
-n “string” 判斷指定的字符串是否不空

注意

  1. 字符創(chuàng)比較盡量定義在雙括號(hào)中
  2. 比較對(duì)象是變量時(shí),最好加雙引號(hào)(變量為空時(shí),該測(cè)試會(huì)出現(xiàn)問題)
文件測(cè)試:
  • 存在性測(cè)試
  • -a FILE
  • -e FILE

文件存在性測(cè)試
存在則為真,否則則為假

符號(hào) 含義
-b FILE 文件是否存在,且為塊設(shè)備文件
-c FILE 文件是否存在,且為字符設(shè)備
-d FILE 文件是否存在,且為目錄文件
-f FILE 文件是否存在,且為普通文件
-h FILE 是否存在,且為符號(hào)鏈接
-p FILE 是否存在,且為命名管道文件
-S FILE 是否存在,且為套接字文件

文件權(quán)限測(cè)試

符號(hào) 含義
-r FILE 是否存在,且對(duì)當(dāng)前用戶可讀
-w FILE 是否存在,且對(duì)當(dāng)前用戶可寫
-x FILE 是否存在,且對(duì)當(dāng)前用戶可執(zhí)行

特殊權(quán)限測(cè)試

符號(hào) 含義
-g FILE 是否存在,且擁有sgid權(quán)限
-u FILE 是否存在,且擁有suid權(quán)限
-k FILE 是否存在,且擁有sticky權(quán)限
雙目測(cè)試
符號(hào) 含義
FILE1 -ef FILE2 file1與file2是否為指向同一個(gè)文件系統(tǒng)的相同inode的硬鏈接
FILE1 -ne FILE2 file1是否新于file2
FILE1 -ot FILE2 file1是否舊于file2
文件是否有內(nèi)容:

-s FILE:是否有內(nèi)容;
時(shí)間戳:
-N FILE:文件自從上一次讀操作后是否被修改過;

從屬關(guān)系測(cè)試:
符號(hào) 含義
-O FILE 當(dāng)前用戶是否為文件的屬主
-G FILE 當(dāng)前用戶是否屬于文件的屬組
組合測(cè)試條件

邏輯運(yùn)算

  • 命令的邏輯運(yùn)算

    COMMAND1 && COMMAND2

    COMMAND1 || COMMAND2

    !COMMAND

  • 表達(dá)式的邏輯運(yùn)算

    EXPRESSION1 -a EXPRESSION2

    EXPRESSION1 -o EXPRESSION2

    !EXPRESSION

練習(xí):將當(dāng)前主機(jī)名稱保存至hostName變量中;主機(jī)名如果為空,或者為localhost.localdomain,則將其設(shè)置為www.magedu.com

hostName=$(hostname)

[ -z "$hostName" -o "$hostName" == "localhost.localdomain" -o "$hostName" == "localhost" ] && 
hostname [www.magedu.com](http://www.magedu.com/)

控制語句

if選擇執(zhí)行語句
  • 單分支
if  測(cè)試條件; then
    代碼分支
fi

例如:測(cè)試/tmp目錄下是否有test文件,如果有則告知用戶,已存在

source-shell
if [[ -a /tmp/test ]];then
    echo "test is existing"
fi
  • 雙分支
if  測(cè)試條件; then
       條件為真時(shí)執(zhí)行的分
else
       條件為假時(shí)執(zhí)行的分支
fi

例如:檢查/tmp目錄下是否有名為test的普通文件,沒有則創(chuàng)建

  source-shell
if [[ -f /tmp/test ]];then
        echo "test is existing"
        else
            touch /tmp/test
fi
  • 多分支
 if  測(cè)試條件1;then
       條件1為真時(shí)執(zhí)行的分支
elif  測(cè)試條件2;then
       條件2為真時(shí)執(zhí)行的分支
......
else
       上述條件都不滿足時(shí)的執(zhí)行分支
fi

注意:即便多個(gè)條件可能同時(shí)都能滿足,分支只會(huì)執(zhí)行中其中一個(gè),首先測(cè)試為“真”

示例:腳本參數(shù)傳遞一個(gè)文件路徑給腳本,判斷此文件的類型;

#!/bin/bash
#
if [ $# -lt 1 ]; then
     echo "At least on path."
     exit 1
fi

if ! [ -e $1 ]; then
     echo "No such file."
     exit 2
fi

if [ -f $1 ]; then
      echo "Common file."
elif [ -d $1 ]; then
      echo "Directory."
elif [ -L $1 ]; then
      echo "Symbolic link."
elif [ -b $1 ]; then
      echo "block special file."
elif [ -c $1 ]; then
      echo "character special file."
elif [ -S $1 ]; then
      echo "Socket file."
else
      echo "Unkown."
fi    

注意:if語句可嵌套;

練習(xí)1:通過命令行參數(shù)給定一個(gè)用戶名,判斷其ID號(hào)是偶數(shù)還是奇數(shù)

#!/bin.bash
if [ $# -lt 1 ];then
echo "Must give a username."
fi
num=$(id -u $1)
let num2=$num%2
#echo "num is $num"
#echo "num2 is $num2"
if [ $num2 -eq 1 ];then
echo "the uid is "odd number
else
echo "the uid is even number"
fi

練習(xí)2:寫一個(gè)腳本
(1) 傳遞一個(gè)參數(shù)給腳本,此參數(shù)為用戶名;
(2) 根據(jù)其ID號(hào)來判斷用戶類型:
0: 管理員
1-999:系統(tǒng)用戶
1000+:登錄用戶

#!/bin/bash
#
[ $# -lt 1 ] && echo "At least on user name." && exit 1

! id $1 &> /dev/null && echo "No such user." && exit 2

userid=$(id -u $1)

if [ $userid -eq 0 ]; then
     echo "root"
elif [ $userid -ge 1000 ]; then
     echo "login user."
else
     echo "System user."
fi                                        

練習(xí)3:寫一個(gè)腳本
(1) 列出如下菜單給用戶:
disk: show disks info;
mem: show memory info;
cpu: show cpu info;
( * ) quit;
(2) (2) 正確的選擇則給出相應(yīng)的信息;否則,則提示重新選擇正確的選項(xiàng);

#!/bin/bash
#
cat << EOF
(disk) show disks info
(mem) show memory info
(cpu) show cpu info
(*) QUIT
EOF

read -p "Your choice: " option

while [ "$option" != "cpu" -a "$option" != "mem" -a "$option" != "disk" -a "$option" != "quit" ]; do
                    echo "cpu, mem, disk, quit"
                    read -p "Enter your option again: " option
done

if [[ "$option" == "disk" ]]; then
      fdisk -l /dev/[sh]d[a-z]
elif [[ "$option" == "mem" ]]; then
      free -m
elif [[ "$option" == "cpu" ]];then
      lscpu
else
      echo "Unkown option."
      exit 3
fi
case語句
case  $VARAIBLE(變量引用)  in  
PAT1)
     分支1
      ;;
PAT2)
     分支2
      ;;
...
*)
     分支n
      ;;
esac

case支持glob風(fēng)格的通配符:

*:任意長度的任意字符;
?:任意單個(gè)字符;
[]:范圍內(nèi)任意單個(gè)字符;
a|b:a或b;

示例:寫一個(gè)服務(wù)框架腳本
$lockfile, 值/var/lock/subsys/SCRIPT_NAME

(1) 此腳本可接受start, stop, restart, status四個(gè)參數(shù)之一;
(2) 如果參數(shù)非此四者,則提示使用幫助后退出;
(3) start,則創(chuàng)建lockfile,并顯示啟動(dòng);stop,則刪除lockfile,并顯示停止;restart,則先刪除此文件再創(chuàng)建此文件,而后顯示重啟完成;status,如果lockfile存在,則顯示running,否則,則顯示為stopped.

#!/bin/bash
#
# chkconfig: - 50 50
# description: test service script
#
prog=$(basename $0)
lockfile=/var/lock/subsys/$prog

case $1  in
start)
      if [ -f $lockfile ]; then
          echo "$prog is running yet."
      else
         touch $lockfile
         [ $? -eq 0 ] && echo "start $prog finshed."
      fi
      ;;
stop)
      if [ -f $lockfile ]; then
           rm -f $lockfile
           [ $? -eq 0 ] && echo "stop $prog finished."
      else
         echo "$prog is not running."
      fi
      ;;
restart)
      if [ -f $lockfile ]; then
           rm -f $lockfile
           touch $lockfile
           echo "restart $prog finished."
     else
           touch -f $lockfile
           echo "start $prog finished."
      fi
      ;;
status)
      if [ -f $lockfile ]; then
         echo "$prog is running"
     else
         echo "$prog is stopped."
      fi
      ;;
*)
     echo "Usage: $prog {start|stop|restart|status}"
     exit 1
esac

循環(huán)執(zhí)行: 將一段代碼重復(fù)執(zhí)行0、1或多次;

進(jìn)入條件:

for:列表元素非空;
while:條件測(cè)試結(jié)果為“真”
unitl:條件測(cè)試結(jié)果為“假”

退出條件:每個(gè)循環(huán)都應(yīng)該有退出條件,以有機(jī)會(huì)退出循環(huán);

for:列表元素遍歷完成;
while:條件測(cè)試結(jié)果為“假”
until:條件測(cè)試結(jié)果為“真

for循環(huán):

兩種格式:

  • 遍歷列表
  • 控制變量

遍歷列表:

for  VARAIBLE  in  LIST; do
     循環(huán)體
done

進(jìn)入條件:只要列表有元素,即可進(jìn)入循環(huán);
退出條件:列表中的元素遍歷完成;

示例:

#!/bin/bash
#
for username in user21 user22 user23; do
    if id $username &> /dev/null; then
        echo "$username exists."
    else
        useradd $username && echo "Add user $username finished."
    fi
done

LISTT的生成方式:

(1) 直接給出;
(2) 整數(shù)列表
(a) {start..end}
(b) seq [start [incremtal]] last
(3) 返回列表的命令
(4) glob
(5) 變量引用
@,*
...

示例:求100以內(nèi)所有正整數(shù)之和;

#!/bin/bash
#
declare -i sum=0

for i in {1..100}; do
            echo "\$sum is $sum, \$i is $i"
            sum=$[$sum+$i]
done

echo $sum

示例:判斷/var/log目錄下的每一個(gè)文件的內(nèi)容類型

#!/bin/bash
#
for filename in /var/log/*; do
     if [ -f $filename ]; then
        echo "Common file."
elif [ -d $filename ]; then
        echo "Directory."
elif [ -L $filename ]; then
        echo "Symbolic link."
elif [ -b $filename ]; then
        echo "block special file."
elif [ -c $filename ]; then
        echo "character special file."
elif [ -S $filename ]; then
        echo "Socket file."
else
        echo "Unkown."
     fi                    
done
for循環(huán)的特殊用法:
for  ((控制變量初始化;條件判斷表達(dá)式;控制變量的修正語句)); do
                循環(huán)體
            done

控制變量初始化:僅在循環(huán)代碼開始運(yùn)行時(shí)執(zhí)行一次;
控制變量的修正語句:每輪循環(huán)結(jié)束會(huì)先進(jìn)行控制變量修正運(yùn)算,而后再做條件判斷;

示例:求100以內(nèi)所有正整數(shù)之和

#!/bin/bash
#
declare -i sum=0

for ((i=1;i<=100;i++)); do
    let sum+=$i
done

echo "Sum: $sum."

示例:用for循環(huán)檢測(cè)10.0.0.1/24網(wǎng)段存活的IP地址

#!/bin/bash
#
declare -i a=0
for a in {1..255};do
if ping -w 2 -c 2 10.0.0.$a &>/dev/null;then
echo "10.0.0.$a is up"
else
echo "10.0.0.$a is down"
fi
done
while循環(huán):
while  CONDITION; do
     循環(huán)體
     循環(huán)控制變量修正表達(dá)式
done

進(jìn)入條件:CONDITION測(cè)試為”真“
退出條件:CONDITION測(cè)試為”假“

示例:求100以內(nèi)所有正整數(shù)之和

#!/bin/bash
#
declare -i sum=0
declare -i i=1

while [ $i -le 100 ]; do
     let sum+=$i
     let i++
done

echo $sum
循環(huán)控制語句:

continue:提前結(jié)束本輪循環(huán),而直接進(jìn)入下一輪循環(huán)判斷

while  CONDITION1; do
          CMD1
                    ...
      if  CONDITION2; then
          continue
      fi
          CMDn
         ...
done

示例:求100以內(nèi)所有偶數(shù)之和

#
declare -i evensum=0
declare -i i=0

while [ $i -le 100 ]; do
    let i++
    if [ $[$i%2] -eq 1 ]; then
            continue
    fi
    let evensum+=$i
done

echo "Even sum: $evensum"   

break:提前跳出循環(huán)

while  CONDITION1; do
          CMD1
          ..
     if  CONDITION2; then
          break
     fi
done

創(chuàng)建死循環(huán):

while true; do
          循環(huán)體
done

退出方式:
某個(gè)測(cè)試條件滿足時(shí),讓循環(huán)體執(zhí)行break命令;

示例:求100以內(nèi)所奇數(shù)之和

#!/bin/bash
#
declare -i oddsum=0
declare -i i=1

while true; do
     let oddsum+=$i
     let i+=2
     if [ $i -gt 100 ]; then
           break
    fi

done
sleep命令:

delay for a specified amount of time
sleep NUMBER

練習(xí):每隔3秒鐘到系統(tǒng)上獲取已經(jīng)登錄用戶的用戶的信息;其中,如果logstash用戶登錄了系統(tǒng),則記錄于日志中,并退出;

#!/bin/bash
#
while true; do
      if who | grep "^logstash\>" &> /dev/null; then
          break
      fi
          sleep 3
done

echo "$(date +"%F %T") logstash logged on" >> /tmp/users.log    
#!/bin/bash
#
until who | grep "^logstash\>" &> /dev/null; do
         sleep 3
         done

echo "$(date +"%F %T") logstash logged on" >> /tmp/users.log   
while循環(huán)的特殊用法(遍歷文件的行):
while  read  VARIABLE; do
          循環(huán)體;
done  <  /PATH/FROM/SOMEFILE

依次讀取/PATH/FROM/SOMEFILE文件中的每一行,且將基賦值給VARIABLE變量;

示例:找出ID號(hào)為偶數(shù)的用戶,顯示其用戶名、ID及默認(rèn)shell

#!/bin/bash
#
while read line; do
    userid=$(echo $line | cut -d: -f3)
    username=$(echo $line | cut -d: -f1)
    usershell=$(echo $line | cut -d: -f7)

    if [ $[$userid%2] -eq 0 ]; then
          echo "$username, $userid, $usershell."
    fi
done < /etc/passwd        

示例:用while循環(huán)檢測(cè)10.0.0.1/24網(wǎng)段存活的IP地址

#!/bin/bash
#
declare -i a=0
declare -i b=0
declare -i c=0

while [ $a -le 255 ];do
if ping -w 2 -c 2 10.0.0.$a &>/dev/null;then
echo "10.0.0.$a is up"
else
echo "10.0.0.$a is down"
fi
let a++
done
until循環(huán):
until  CONDITION; do
     循環(huán)體
     循環(huán)控制變量修正表達(dá)式
done

進(jìn)入條件:CONDITION測(cè)試為”假“
退出條件:CONDITION測(cè)試為”真“

示例:求100以內(nèi)所有正整數(shù)之和

#!/bin/bash
#
declare -i sum=0
declare -i i=1

until [ $i -gt 100 ]; do
     let sum+=$i
     let i++
done

echo $sum            

練習(xí):打印九九乘法表
1X1=1
1X2=2 2X2=4
1X3=3 2X3=6 3X3=9
外循環(huán)控制乘數(shù),內(nèi)循環(huán)控制被乘數(shù);

#!/bin/bash
#
for j in {1..9}; do
      for i in $(seq 1 $j); do
            echo -n -e "${i}X${j}=$[${i}*${j}]\t"
      done
      echo
done    
#!/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              

寫一個(gè)腳本:
ping命令去查看172.16.1.1-172.16.67.1范圍內(nèi)的所有主機(jī)是否在線;在線的顯示為up, 不在線的顯示down,分別統(tǒng)計(jì)在線主機(jī),及不在線主機(jī)數(shù);
分別使用for, while循環(huán)實(shí)現(xiàn)。

#!/bin/bash
#
declare -i uphosts=0
declare -i downhosts=0

for i in {1..67}; do
     if ping -W 1 -c 1 172.16.$i.1 &> /dev/null; then
             echo "172.16.$i.1 is up."
             let uphosts+=1
     else
             echo "172.16.$i.1 is down."
             let downhosts+=1
      fi
done

echo "Up hosts: $uphosts, Down hosts: $downhosts."        
#!/bin/bash
#
declare -i uphosts=0
declare -i downhosts=0
declare -i i=1

hostping() {
          if ping -W 1 -c 1 $1 &> /dev/null; then
                   echo "$1 is up."
                   return 0
          else
                   echo "$1 is down."
                   return 1
          fi
}
          while [ $i -le 67 ]; do
                hostping 172.16.$i.1
                [ $? -eq 0 ] && let uphosts++ || let downhosts++
                let i++
done

echo "Up hosts: $uphosts, Down hosts: $downhosts."                    

寫一個(gè)腳本,實(shí)現(xiàn):
能探測(cè)C類、B類或A類網(wǎng)絡(luò)中的所有主機(jī)是否在線;

#!/bin/bash
#
cping() {
        local i=1
        while [ $i -le 254 ]; do
                if ping -W 1 -c 1 $1.$i &> /dev/null; then
                        echo "$1.$i is up"
                else
                        echo "$1.$i is down."
                fi
                let i++
done
}
bping() {
        local j=0
        while [ $j -le 255 ]; do
                cping $1.$j
                let j++
done
}
aping() {
        local x=0
        while [ $x -le 255 ]; do
                bping $1.$x
                let x++
done
}

函數(shù):function

過程式編程:代碼重用

  • 模塊化編程
  • 結(jié)構(gòu)化編程

把一段獨(dú)立功能的代碼當(dāng)作一個(gè)整體,并為之一個(gè)名字;命名的代碼段,此即為函數(shù);

注意:定義函數(shù)的代碼段不會(huì)自動(dòng)執(zhí)行,在調(diào)用時(shí)執(zhí)行;所謂調(diào)用函數(shù),在代碼中給定函數(shù)名即可;
函數(shù)名出現(xiàn)的任何位置,在代碼執(zhí)行時(shí),都會(huì)被自動(dòng)替換為函數(shù)代碼;

語法風(fēng)格一:

function  f_name  {
         ...函數(shù)體...
}

語法風(fēng)格二:

f_name()  {
         ...函數(shù)體...
}

函數(shù)的生命周期:每次被調(diào)用時(shí)創(chuàng)建,返回時(shí)終止;
其狀態(tài)返回結(jié)果為函數(shù)體中運(yùn)行的最后一條命令的狀態(tài)結(jié)果;

自定義狀態(tài)返回值,需要使用:return
return [0-255]
0: 成功
1-255: 失敗

示例:給定一個(gè)用戶名,取得用戶的id號(hào)和默認(rèn)shell

#!/bin/bash
#
userinfo() {
       if id "$username" &> /dev/null; then
             grep "^$username\>" /etc/passwd | cut -d: -f3,7
       else
             echo "No such user."
       fi
}

username=$1
userinfo

username=$2
userinfo        

示例2:服務(wù)腳本框架(函數(shù)形式)

#!/bin/bash
#
# chkconfig: - 50 50
# description: test service script
#
prog=$(basename $0)
lockfile=/var/lock/subsys/$prog

start() {
        if [ -f $lockfile ]; then
               echo "$prog is running yet."
        else
               touch $lockfile
               [ $? -eq 0 ] && echo "start $prog finshed."
        fi
}

stop() {
        if [ -f $lockfile ]; then
               rm -f $lockfile
               [ $? -eq 0 ] && echo "stop $prog finished."
        else
               echo "$prog is not running."
        fi
}
status() {
        if [ -f $lockfile ]; then
               echo "$prog is running"
        else
               echo "$prog is stopped."
        fi
}

usage() {
               echo "Usage: $prog {start|stop|restart|status}"
}

case $1 in
start)
        start ;;
stop)
        stop ;;
restart)
        stop
        start ;;
status)
        status ;;
*)
        usage
        exit 1 ;;
esac
函數(shù)返回值:

函數(shù)的執(zhí)行結(jié)果返回值:
(1) 使用echo或printf命令進(jìn)行輸出;
(2) 函數(shù)體中調(diào)用的命令的執(zhí)行結(jié)果;

函數(shù)的退出狀態(tài)碼:
(1) 默認(rèn)取決于函數(shù)體中執(zhí)行的最后一條命令的退出狀態(tài)碼;
(2) 自定義:return

函數(shù)可以接受參數(shù):

傳遞參數(shù)給函數(shù):
在函數(shù)體中當(dāng)中,可以使用$1,$2, ...引用傳遞給函數(shù)的參數(shù);還可以函數(shù)中使用$*或$@引用所有參數(shù),$#引用傳遞的參數(shù)的個(gè)數(shù);
在調(diào)用函數(shù)時(shí),在函數(shù)名后面以空白符分隔給定參數(shù)列表即可,例如,testfunc arg1 arg2 arg3 ...

示例:添加10個(gè)用戶,添加用戶的功能使用函數(shù)實(shí)現(xiàn),用戶名做為參數(shù)傳遞給函數(shù)

#!/bin/bash
#
# 5: user exists

addusers() {
         if id $1 &> /dev/null; then
                return 5
         else
                useradd $1
                retval=$?
                return $retval
         fi
}

     for i in {1..10}; do
                addusers ${1}${i}
                retval=$?
          if [ $retval -eq 0 ]; then
                echo "Add user ${1}${i} finished."
          elif [ $retval -eq 5 ]; then
                echo "user ${1}${i} exists."
          else
                echo "Unkown Error."
          fi
done
變量作用域:

局部變量:作用域是函數(shù)的生命周期;在函數(shù)結(jié)束時(shí)被自動(dòng)銷毀;
定義局部變量的方法:local VARIABLE=VALUE
本地變量:作用域是運(yùn)行腳本的shell進(jìn)程的生命周期;因此,其作用范圍為當(dāng)前shell腳本程序文件;

示例程序:

#!/bin/bash
#
name=tom

setname() {
       local name=jerry
       echo "Function: $name"
}

setname
echo "Shell: $name"
函數(shù)遞歸:

函數(shù)直接或間接調(diào)用自身

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 $1                    
斐波那契數(shù)列:1,1,2,3,5,8,13,21,...
#!/bin/bash
#
fab() {
      if [ $1 -eq 1 ]; then
              echo -n "1 "
      elif [ $1 -eq 2 ]; then
              echo -n "1 "
      else
              echo -n "$[$(fab $[$1-1])+$(fab $[$1-2])] "
       fi
}

       for i in $(seq 1 $1); do
              fab $i
      done
 echo

數(shù)組:

程序=指令+數(shù)據(jù)
數(shù)據(jù):變量、文件

變量:存儲(chǔ)單個(gè)元素的內(nèi)存空間

數(shù)組:存儲(chǔ)多個(gè)元素的連續(xù)的內(nèi)存空間
數(shù)組名:整個(gè)數(shù)組只有一個(gè)名字;
數(shù)組索引:編號(hào)從0開始;
數(shù)組名[索引]
${ARRAY_NAME[INDEX]}

注意:bash-4及之后的版本,支持自定義索引格式,而不僅僅是0,1,2,...數(shù)字格式;
此類數(shù)組稱之為“關(guān)聯(lián)數(shù)組”

[root@promote ~]# world[us]="america"
[root@promote ~]# echo ${world[us]}
america
[root@promote ~]# world[uk]="united kingdom"
[root@promote ~]# echo ${world[uk]}
united kingdom
聲明數(shù)組:
  • declare -a NAME:聲明索引數(shù)組
  • declare -A NAME:聲明關(guān)聯(lián)數(shù)組
數(shù)組中元素的賦值方式:

(1) 一次只賦值一個(gè)元素
ARRAY_NAME[INDEX]=value

[root@promote ~]# animal[0]=pig
[root@promote ~]# animal[1]=dog
[root@promote ~]# echo $animal
pig
[root@promote ~]# echo ${animal[0]}
pig
[root@promote ~]# echo ${animal[1]}
dog

(2) 一次賦值全部元素
ARRAY_NAME=("VAL1" "VAL2" "VAL3" ...)

[root@promote ~]# weekday=("Monday" "Tuesday" "Wednesday")
[root@promote ~]# echo ${weekday[1]}
Tuesday

(3) 只賦值特定元素;
ARRAY_NAME=([0]="VAL1" [3]="VAL4" ...)
注意:bash支持稀疏格式的數(shù)組

[root@promote ~]# sword=([0]="Yitianjian" [3]="Longquan")
[root@promote ~]# echo ${sword[3]}
Longquan

(4) read -a ARRAY_NAME

[root@promote ~]# read -a Jiangsu
ljiawen wangchenlu lalala
[root@promote ~]# echo ${Jiangsu[2]}
lalala

引用數(shù)組中的元素:${ARRAY_NAME[INDEX]}
注意:引用時(shí),只給數(shù)組名,表示引用下標(biāo)為0的元素;

數(shù)組的長度(數(shù)組中元素的個(gè)數(shù)):

${#ARRAY_NAME[*]}
${#ARRAY_NAME[@]}

[root@promote ~]# echo ${#Jiangsu[*]}
3
[root@promote ~]# echo ${#animal[@]}
2

示例:生成10個(gè)隨機(jī)數(shù),并找出其中的最大值

#!/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"            

練習(xí):寫一個(gè)腳本
定義一個(gè)數(shù)組,數(shù)組中的元素是/var/log目錄下所有以.log結(jié)尾的文件;統(tǒng)計(jì)其下標(biāo)為偶數(shù)的文件中的行數(shù)之和

#!/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."
引用數(shù)組中的所有元素:

${ARRAY_NAME[*]}
${ARRAY_NAME[@]}

數(shù)組元素切片:

${ARRAY_NAME[@]:offset:number}
offset:要路過的元素個(gè)數(shù);
number:要取出的元素個(gè)數(shù);省略number時(shí),表示取偏移量之后的所有元素;

[root@promote ~]# files=(/etc/[Pp]*)
[root@promote ~]# echo ${files[*]}
/etc/pam.d /etc/passwd /etc/passwd- /etc/pkcs11 /etc/pki /etc/plymouth /etc/pm /etc/polkit-1 /etc/popt.d /etc/postfix /etc/ppp /etc/prelink.conf.d /etc/printcap /etc/profile /etc/profile.d /etc/protocols /etc/python
[root@promote ~]# echo ${files[@]:2:3}
/etc/passwd- /etc/pkcs11 /etc/pki

向非稀疏格式數(shù)組中追加元素:
ARRAY_NAME[${#ARRAY_NAME[*]}]=

刪除數(shù)組中的某元素:
unset ARRAY[INDEX]

關(guān)聯(lián)數(shù)組:
declare -A ARRAY_NAME
ARRAY_NAME=([index_name1]="value1" [index_name2]="value2" ...)

bash的內(nèi)置字符串處理工具:

字符串切片:

${var:offset:number}取字符串的子串;
取字符趾的最右側(cè)的幾個(gè)字符:${var: -length}

注意:冒號(hào)后必須有一個(gè)空白字符

[root@promote ~]# name=jerry
[root@promote ~]# echo ${name: 2: 2}
rr
[root@promote ~]# echo ${name: 2}
rry
[root@promote ~]# echo ${name: -4}
erry

基于模式取子串:

${var#*word}:其中word是指定的分隔符;
功能:自左而右,查找var變量所存儲(chǔ)的字符串中,第一次出現(xiàn)的word分隔符,刪除字符串開頭至此分隔符之間的所有字符;

[root@promote ~]# mypath="/etc/init.d/functions"
[root@promote ~]# echo ${mypath#*/}
etc/init.d/functions

${var##*word}:其中word是指定的分隔符;
功能:自左而右,查找var變量所存儲(chǔ)的字符串中,最后一次出現(xiàn)的word分隔符,刪除字符串開頭至此分隔符之間的所有字符;

[root@promote ~]# mypath="/etc/init.d/functions"
[root@promote ~]# echo ${mypath##*/}
functions

${var%word*}:其中word是指定的分隔符;
功能:自右而左,查找var變量所存儲(chǔ)的字符串中,第一次出現(xiàn)的word分隔符,刪除此分隔符至字符串尾部之間的所有字符;

[root@promote ~]# mypath="/etc/init.d/functions"
[root@promote ~]# echo ${mypath%/*}
/etc/init.d

${var%%word*}:其中word是指定的分隔符;
功能:自右而左,查找var變量所存儲(chǔ)的字符串中,最后一次出現(xiàn)的word分隔符,刪除此分隔符至字符串尾部之間的所有字符;

[root@promote ~]# mypath="/etc/init.d/functions"
[root@promote ~]# echo ${mypath%%/*}
[root@promote ~]# mypath="etc/init.d/functions"
[root@promote ~]# echo ${mypath%%/*}
etc

示例:

[root@promote ~]# url=http://www.magedu.com:80
[root@promote ~]# echo ${url##*:}
80
[root@promote ~]# echo ${url%%:*}
http

查找替換:

${var/PATTERN/SUBSTI}:查找var所表示的字符串中,第一次被PATTERN所匹配到的字符串,將其替換為SUBSTI所表示的字符串;

${var//PATTERN/SUBSTI}:查找var所表示的字符串中,所有被PATTERN所匹配到的字符串,并將其全部替換為SUBSTI所表示的字符串;

[root@promote ~]# userinfo="root:x:0:0:root admin:/root:/bin/chroot"
[root@promote ~]# echo ${userinfo/root/ROOT}
ROOT:x:0:0:root admin:/root:/bin/chroot
[root@promote ~]# echo ${userinfo//root/ROOT}
ROOT:x:0:0:ROOT admin:/ROOT:/bin/chROOT

${var/#PATTERN/SUBSTI}:查找var所表示的字符串中,行首被PATTERN所匹配到的字符串,將其替換為SUBSTI所表示的字符串;

${var/%PATTERN/SUBSTI}:查找var所表示的字符串中,行尾被PATTERN所匹配到的字符串,將其替換為SUBSTI所表示的字符串;

注意:PATTERN中使用glob風(fēng)格和通配符;

[root@promote ~]# userinfo="root:x:0:0:root admin:/root:/bin/chroot"
[root@promote ~]# echo ${userinfo/%r??t/ROOT}
root:x:0:0:root admin:/root:/bin/chROOT

查找刪除:

${var/PATTERN}:以PATTERN為模式查找var字符串中第一次的匹配,并刪除
${var//PATERN}:以PATTERN為模式查找var字符串中所有的匹配,并刪除
${var/#PATTERN:以PATTERN為模式查找var字符串中所有被行首匹配的,并刪除
${var/%PATTERN}:以PATTERN為模式查找var字符串中所有被行尾匹配的,并刪除

字符大小寫轉(zhuǎn)換:

${var^^}:把var中的所有小寫字符轉(zhuǎn)換為大寫
${var,,}:把var中的所有大寫字符轉(zhuǎn)換為小寫

[root@promote ~]# url=http://www.magedu.com:80
[root@promote ~]# echo ${url^^}
HTTP://WWW.MAGEDU.COM:80
[root@promote ~]# myurl=${url^^}
[root@promote ~]# echo $myurl
HTTP://WWW.MAGEDU.COM:80
[root@promote ~]# echo ${myurl,,}
http://www.magedu.com:80

變量賦值:

${var:-VALUE}:如果var變量為空,或未設(shè)置,那么返回VALUE;否則,則返回var變量的值;

[root@promote ~]# echo hi
hi
[root@promote ~]# echo $hi

[root@promote ~]# echo ${hi:-world}
world
[root@promote ~]# hi="america"
[root@promote ~]# echo ${hi:-world}
america

${var:=VALUE}:如果var變量為空,或未設(shè)置,那么返回VALUE,并將VALUE賦值給var變量;否則,則返回var變量的值;

[root@promote ~]# hi="america"
[root@promote ~]# echo ${hi:=world}
america
[root@promote ~]# unset hi
[root@promote ~]# echo ${hi:=world}
world
[root@promote ~]# echo $hi
world

${var:+VALUE}:如果var變量不空,則返回VALUE;
${var:?ERROR_INFO}:如果var為空,或未設(shè)置,那么返回ERROR_INFO為錯(cuò)誤提示;否則,返回var值;

信號(hào)捕捉:

trap命令
格式:trap 'COMMAND' SIGNALS

列出信號(hào):
trap -l
kill -l

[root@promote ~]# trap -l
 1) SIGHUP   2) SIGINT   3) SIGQUIT  4) SIGILL   5) SIGTRAP
 6) SIGABRT  7) SIGBUS   8) SIGFPE   9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG  24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF 28) SIGWINCH    29) SIGIO   30) SIGPWR
31) SIGSYS  34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX    

man 7 signal
解釋每個(gè)信號(hào)的功用

??梢赃M(jìn)行捕捉的信號(hào):

HUP, INT

示例:

#!/bin/bash
#
declare -a hosttmpfiles
trap  'mytrap'  INT

mytrap()  {
         echo "Quit"
         rm -f ${hosttmpfiles[@]}
         exit 1
}

for i in {1..50}; do
        tmpfile=$(mktemp /tmp/ping.XXXXXX)
        if ping -W 1 -c 1 172.16.$i.1 &> /dev/null; then
              echo "172.16.$i.1 is up" | tee $tmpfile
        else
              echo "172.16.$i.1 is down" | tee $tmpfile
        fi
        hosttmpfiles[${#hosttmpfiles[*]}]=$tmpfile
        done

rm -f ${hosttmpfiles[@]}
SIGHUP、SIGQUIT、SIGTERM、SIGINTERRUPT的區(qū)別
  • SIGHUP: 無需關(guān)閉進(jìn)程而讓其重讀配置
  • SIGQUIT: 終止進(jìn)程,由QUIT字符(通常是Ctrl-)來控制,進(jìn)程在因收到SIGQUIT退出時(shí)會(huì)產(chǎn)生core文件
  • SIGTERM: 程序結(jié)束(terminate)信號(hào),該信號(hào)可以被阻塞和處理。通常用來要求程序自己正常退出
  • SIGNTERRUPT: 允許信號(hào)中斷系統(tǒng)調(diào)用

在bash中使用ACSII顏色

\033[31m hello \033[0m

##m:
左側(cè)#:
3:前景色
4:背景色
右側(cè)#:顏色種類
1, 2, 3, 4, 5, 6, 7

#m:
加粗、閃爍等功能;

多種控制符,可組合使用,彼此間用分號(hào)隔開

示例:

dialog命令:可實(shí)現(xiàn)窗口化編程

各窗體控件使用方式

[root@promote ~]# dialog --msgbox hello 17 30

如何獲取用戶選擇或鍵入的內(nèi)容?
默認(rèn),其輸出信息被定向到了錯(cuò)誤輸出流;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 官網(wǎng) 中文版本 好的網(wǎng)站 Content-type: text/htmlBASH Section: User ...
    不排版閱讀 4,709評(píng)論 0 5
  • 一.編程基本概念 編程邏輯處理方式: 順序執(zhí)行 循環(huán)執(zhí)行 選擇執(zhí)行 ?shell編程:過程式、解釋執(zhí)行編程語言的基...
    楠人幫閱讀 1,437評(píng)論 0 1
  • 什么是Shell腳本 示例 看個(gè)例子吧: !/bin/sh cd ~ mkdir shell_tut cd she...
    碼農(nóng)朱同學(xué)閱讀 2,535評(píng)論 0 5
  • 一、什么是Shell腳本 示例 看個(gè)例子吧: 示例解釋 第1行:指定腳本解釋器,這里是用/bin/sh做解釋器的 ...
    Rick617閱讀 886評(píng)論 0 1
  • 第二章節(jié)一草一木,皆是北方 請(qǐng)回答我的一九九三 可憐的姑娘失去了母親,因?yàn)槟承┰虿荒苷f話,有語言障礙。 世事艱難...
    妍兮兮閱讀 1,320評(píng)論 8 53

友情鏈接更多精彩內(nèi)容