bash腳本編程基礎及配置文件

shell腳本編程

         編程語言的分類:根據運行方式

                   編譯運行:源代碼----->編譯器(編譯)---->程序文件

                            C語言:

                   解釋運行:源代碼--->運行時啓動解釋器,由解釋器邊解釋邊運行;

 

         根據其編程過程中功能的實現是調用庫還是調用外部的程序文件:

                   shell腳本編程:

                            利用系統上的命令及編程組件進行編程;

                   完成編程:

                            利用庫或編程組件運行編程

 

         編程模型:

                   過程式編程語言,面向對象的編程語言

         程序=指令+數據

                   過程式:以指令爲中心來組織代碼,數據是服務於代碼;

                            順序執行

                            選擇執行

                            循環執行

                            C語言,bash腳本語言)

                   對象式:以數據爲中心來組織代碼,圍繞數據來組織指令;

                            類(class):實例化對象,method

                            JAVAC++Python

 

shell腳本編程:(特性)

         1)過程式編程

         2)解釋運行

         3)依賴於外部程序文件

 

如何寫shell腳本:

         腳本文件的第一行,頂格寫,給出shebang,解釋器路徑,用於指明解釋執行當前腳本的解釋器程序文件

                   常見的解釋器:

                            #!/bin/bash

                            #!/usr/bin/python

                            #!/usr/bin/perl

 

文本編輯器:nano

         行編輯器:sed

         全屏幕編輯器:nano,vim,vi

使用namo命令:

         ctrl+G:求助   ctrl+O:寫入   ctrl+R:讀檔   ctrl+Y:上頁   ctrl+V:下頁 

         ctrl+K:剪切文字    ctrl+U:還原剪切   ctrl+C:遊標位置    ctrl+T:拼寫檢查

         ctrl+X:離開    ctrl+J:對齊

一般而言shell腳本都以“.sh”結尾。

 

shell腳本是什麼?

         命令的堆積;

         但是很多命令不具有冪等性,需要用程序邏輯來判斷運行條件是否滿足,以避免其運行         中發生錯誤;

 

編寫第一個shell腳本:

 

         nanomyshell.sh

腳本內容爲:

         #!/bin/bash

         useradduser3

         echo"user3" | passwd --stdin user3

         mktemp-d /tmp/test.XXX

最後腳本寫完後,直接按“ctrl+X”保存退出

要想執行腳本,先看一下這個腳本的權限

                   [root@centos6~]# ls -l myshell.sh

                   -rw-r--r--.1 root root 86 Oct 26 22:51 myshell.sh

再看當前用戶是以什麼身份登入的:

                   [root@centos6~]# whoami

                   root

給用戶加執行權限:

                   [root@centos6~]# chmod +x myshell.sh

                   [root@centos6~]# ls -l myshell.sh

                   -rwxr-xr-x.1 root root 86 Oct 26 22:51 myshell.sh

                   [root@centos6~]#

最後執行腳本:

[root@centos6 ~]# ./myshell.sh    

Changing password for user user3.

passwd: all authentication tokens updatedsuccessfully.

/tmp/test.noG

[root@centos6 ~]#

 

注意當我們再次運行上面的腳本時,我們的腳本還會執行,只是第一個創建用戶的命令創建失敗了,下面的兩條命令執行成功了。

 

這說明,在shell腳本中並不是所有的命令失敗,都會導致腳本終止的,而是命令執行失敗,如果產生嚴重的錯誤,這種嚴重的錯誤比如會“exit”,一般而言任何腳本遇到“exit”都會終止或者我們使用某種判斷機制將其強行終止。或者我們的腳本運行中出現了語法錯誤。腳本纔有可能終止。

 

所以我我們可以將上面的腳本創建用戶時,加一個判斷,用戶在就不創建,不在就創建,那麼就是將第一個命令改爲id user3||useradd user3”這樣再次執行腳本就不會報錯了

運行腳本:

         1)賦予執行權限,並執行運行此程序文件;

                            chmod  +x /PATH/TO/SCRIPT_FILE      //一加x所有的用戶都有了執行權限

                            ./SCRIPT_FILE       //相對路徑

                            /PATH/TO/SCRIPT_FILE     //絕對路徑

         2)直接運行解釋器,將腳本以命令行參數傳遞給解釋器程序

                            bash /PATH/TO/SCRIPT_FILE

(解釋:

                   使用解釋器運行腳本,本質上其實就是利用了linux內核有一個特性,他可以通過文本的前n個字節,來判定這是一個什麼格式的文件,尤其是看到文件前兩個字節是“#!”就知道後面是shell腳本程序文件,我們不需要直接運行這個文件,而是先運行“#!”後面的解釋器程序,然後由這個解釋器程序來解釋運行這個文件中的程序代碼。)

 

演示:

[root@centos6 ~]# ll myshell.sh

-rw-r--r--. 1 root root 98 Oct 26 23:12myshell.sh

[root@centos6 ~]# bash myshell.sh

uid=502(user3) gid=502(user3)groups=502(user3)

Changing password for user user3.

passwd: all authentication tokens updatedsuccessfully.

/tmp/test.BkL

[root@centos6 ~]#

 

這也說明了,shell是嚴重依賴命令的,不然怎麼說shell腳本是命令的堆積呢

 

 

練習1:寫一個腳本,實現如下功能:

         1)顯示/etc/目錄下所有以大寫P或小寫p開頭的文件或目錄本身;

         2)顯示/var目錄下的所有文件或目錄本身,並將顯示結果中的小寫字母轉換爲大寫後顯示:

         3)創建臨時文件/tmp/myfile.XXXX

 

         解:

                            #!/bin/bash

                            ls  -d /etc/[Pp]*

                            ls   -d  /var/* |  tr  [:lower:] [:upper:]

                  

                            ls   -d /var/*  |  tr 'a-z'  'A-Z'

                            mktemp  /tmp/myfile.XXXX

 

(拓展:

         上面的腳本我們還可以進行優化:

                   上面的腳本執行過程中沒有執行後的反饋,我們可以進一步的進行完善:

                   如下:

         #!/bin/bash

         echo  "Show some  under  /etc"      //echo的內容都是直接顯示在屏幕上

         ls  -d /etc/[Pp]*

         echo  "Traslate  lower to  upper"

         ls  -d /var/*  |  tr  'a-z'  'A-Z'

         echo  "Create a  temp  file"

         mktemp  /tmp/myfile.XXXX

 

注意:

         1)腳本中的空白行直接被忽略,所以不會輸出空白行

         2)腳本中,除了shebang,餘下所有以#開頭的行,都會被視作註釋行而被忽略;此           即爲註釋行

         3)如果想從腳本中輸出一個空白行,則在腳本中加上一行,並且這行中只寫一個echo

         4shell腳本的運行是通過運行一個子shell進程實現的;

 

 

bash的配置文件:定義別名

         (我們之前講的,在shell進程中定義的別名,當我們的系統重啓以後,當我們的shell登出再登錄以後,我們在shell下定義的特性,包括變量,他的生命週期僅是當前shell進程,如果想突破這樣的生命週期,我們應該在他的配置文件中定義)

        

         bash程序有兩大類的配置文件:

                   profile

                   bashrc

 

                   profile類:爲交互式登錄的shell進程提供配置

                   bashrc類:爲非交互式登錄的shell進程提供配置

 

         登錄類型:

                   交互式登錄shell進程;

                            直接通過某終端輸入賬號和密碼後登錄打開的shell進程;

                            使用su命令:su -USERNAME,或者使用 su -l USERNAME執行的登錄切換;

 

                   非交互式登錄shell進程:

                            suUSERNAME執行的登錄切換;

                            圖形界面下打開的終端;

                            運行腳本時

 

         profile類:

                   全局:對所有用戶都生效;

                            /etc/profile

                            /etc/profile.d/*.sh

                   用戶個人:僅對當前用戶有效;

                            ~/.bashrc_profile

                  功能:

                            1)用於定義環境變量;

                            2)運行命令或腳本;

 

         bashrc類:

                   全局:

                            /etc/bashrc

                   用戶個人:

                            ~/.bashrc

                   功用:

                            1)定義本地變量;

                            2)定義命令別名;

注意:

         1)定義命令別名時,定義在全局文件“/etc/profile”或“/etc/bashrc”還是定義在用戶個人文件“~/.bashrc_profile”或“~/.bashrc”文件中,要看我們自己的需要,如果是想要定義對所有的用戶有效的命令別名,則就定義在文件“/etc/profile”或“/etc/bashrc”中,如果是隻想對特定用戶有效,那麼就將命令別名定義在用戶本身的家目錄文件“~/.bashrc_profile”或“~/.bashrc”中。

         2)只用管理員用戶纔有權限定義全局的,普通用戶是沒有權限進行編輯的。

         3)當我們真正登錄一個shell時,shell有這麼多的配置文件,那麼我們的shell應該先讀取哪一個,後讀取哪一個文件?

         舉例:我們在全局文件中,定義“name=jerry”,在個人配置文件中定義“name=tom”,那麼這個變量name,到底等於誰?是先讀取的生效,還是後讀取的生效?

         解:

                   後讀的纔是最終生效,因此配置文件的讀取的次序纔是至關重要。

                  

 

配置文件的讀取次序:

         交互式登錄shell進程:

                   /etc/profile------->/etc/profile.d/*------->~/.bash_profile------>~/.bashrc----->/etc/bashrc

         非交互式登錄shell進程:

                   ~/.bashrc------>/etc/bashrc------->/etc/profile.d/*

 

(所以我們自己編輯的腳本在運行時,他的環境是取決於“~/.bashrc---->/etc/bashrc---->/etc/pprofile.d/*”這三個文件的,如果是登錄系統是,則就取決於“/etc/profile---->/etc/profile.d/*----->~/.bashrc_profile------>~/.bashrc------>/etc/bashrc”這五個文件的。此前我們也知道,在命令行中定義的,不會永久有效,但是在change文件中定義的他不會立即有效,在配置文件中定義的,只對下次新登錄的shell進程有效,對以往的老shell進程是無效的,)

 

         命令行中定義的特性,例如變量和別名作用於當前的shell進程的生命週期,即立即生效

         配置文件中定義的特性,只對隨後新啓動的shell進程有效;

讓通過配置文件定義的特性立即生效:

         1)通過命令行重複定義一次;

         2)讓shell進程重讀配置文件;

                            重讀配置文件,執行下面的命令:(點號就相當於source

                                              ~]#source  /PATH/FROM/CONF_FILE

                                    

                                               ~]#.  /PATH/FROM/CONF_FILE(配置文件的路徑)

 

注意:定義別名,主要是定義在/etc/bashrc~/.bashrc文件中。

 

 

需求:

 

         如果我們希望每次用戶登錄成功以後,都會echo一下,顯示說“歡迎登錄系統,你已經進入監控區域,你的所有行爲都將被記錄,請注意您的言行”那麼應該怎麼實現呢?

         分析:

         要想讓用戶登錄以後,能執行命令,應該在bashrc的配置文件中定義還是在profile文件中定義?我們知道,profile命令的兩個功能:(1)用於定義環境變量;(2)運行命令或腳本;那麼我們應該在全局中寫還是在個人的家目錄中寫?如果要想讓所有的用戶登陸後都能顯示,那就全局寫,否則就在個人目錄下寫。

         假設我們在全局下寫,我們應該寫在那呢?

                   profile類的文件有兩大類,(1/etc/profile2/etc/profile.d/*,那麼我們要是在/etc/profile.d/目錄下自己建立一個目錄,以後管理也好管理,不用的時候直接刪除就行。

         因此在“/etc/profile.d/”下創建一個文件名隨便起,但是要以“.sh”結尾的文件例如:

該文件叫“welcome.sh

         編輯的內容爲:

                            echo  "welcome aboard....."

然後當我們再次登錄一個shell進程時,就會在shell剛開始前面出現我們編寫內容:

wKioL1gys9nzppaQAAAzRng3jNY808.png

 

所以,如果我們想在用戶登錄時給一些提示信息,那麼我們就可以在“/etc/profile.d/”目錄下定義一個“.sh”結尾的文件,或者在“/etc/profile”文件中定義。

 

有些配置不會立即生效,但是對後來的新登錄的窗口有效。

我們還可以在這樣的配置文件中定義一些環境變量的。

         舉例:

                   輸出當前系統下的JAVA環境所在,我們通常輸出一個環境變量叫JAVA_HOME

創建一個文件,vim  /etc/profile.d/java.sh,(因爲輸出環境變量使用“export”或“declare  -x”)然後在寫的文件內容爲:“export  JAVA_HOME=/usr這樣就定義了一個環境變量“JAVA_HOME”,但是這麼文件不會立即有效,需要重讀這個配置爲文件,使用命令點“.”或“source重讀文件java.sh,然後執行一下命令“export”或“declare  -x”即可顯示新定義的環境變量。

 

 

問題:

         1)如何定義對所有用戶都生效的命令別名,例如  lftps='lftp 10.1.0.1/pub'

         2)如何實現centos用戶登錄時,提示其已經登錄,並顯示當前系統時間(提示顯示當前系統時間,可以通過命令引用來實現,也可以直接寫在文件中)

         3)如何實現root用戶的PATH環境查詢多幾個查詢路徑

 

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章