Shell編程-01-Shell腳本初步入門

来源:https://www.cnblogs.com/surpassme/archive/2018/11/05/9911671.html
-Advertisement-
Play Games

什麼是Shell     簡單來說Shell其實就是一個 命令解釋器 ,而它的作用就是解釋並執行用戶輸入的命令及程式。用戶每輸入一條命令,Shell就解釋執行一次。這種方式很容易讓大家想起在Windows環境中使用的command命令,我們在cmd視窗輸入一條命令,按下Enter ...


什麼是Shell

    簡單來說Shell其實就是一個命令解釋器,而它的作用就是解釋並執行用戶輸入的命令及程式。用戶每輸入一條命令,Shell就解釋執行一次。這種方式很容易讓大家想起在Windows環境中使用的command命令,我們在cmd視窗輸入一條命令,按下Enter鍵,則執行相應的命令和結果。
    Shell位於操作系統的最外層,對外提供與用戶互動式的對話並返回相應的執行結果,對內則是將用戶輸入的命令解釋給操作系統。Shell在操作系統中所處的位置如下圖所示:
3-1 Shell在操作系統的位置.jpg

Shell在英文中的意思就是外殼、貝殼等,從圖中也可以看出,Shell就像殼一樣包住了系統的核心(Kernel)

Shell命令與Command命令對比
3-2 Shell命令與Command命令_c2i.jpg

什麼是Shell腳本

    在理解了Shell之後,我們再來看看Shell腳本。當命令或程式語句不是在命令行中執行時,而是通過程式文件來執行時,該程式就稱之為Shell腳本,我依然拿Windows來做比例。當我們需要執行比較少的命令時,我們可以一個一個命令的進行手動輸入,如果需要執行成百上千的命令時,你會怎麼辦?聰明的你肯定會脫口而出,用批處理(擴展名一般為bat或cmd)。其實Shell腳本就類似於批處理,通過在腳本中定義變數、執行命令、調用函數和邏輯判斷、迴圈等形成一個有機的整體,便形成一個功能強大、自動化程度較高的腳本。

  • 在Windows通過批處理獲取系統信息保存為txt文件,而後自動打開該文件,代碼如下:
@echo off
set date=%date:~0,4%-%date:~5,2%-%date:~8,2%
echo "當前時間為:"%date%
cd /d "D:\"
mkdir SystemInfo
cd /d "SystemInfo"
systeminfo>systeminfo%date%.txt
start systeminfo%date%.txt
pause
  • Shell腳本判斷當前登錄用戶是否為root
# !/bin/bash
currentName=`whoami`
echo $currentName
if [ "$currentName" = "root" ]
  then
    echo "Current Login User is root"
else
  echo "Current Login User is :"$currentName
fi

Shell腳本語言的種類

    Shell 腳本語言是弱類型語言,即無須定義變數類型即可使用。在UNIX/Linux中主要有兩大類Shell:Bourne ShellC Shell

Bourne Shell

    Bourne Shell包括Bourne Shell(sh)、Korn Shell(ksh)、Bourne Again Shell(bash)三種類型。

  • Bourne Shell
      由AT&T的Steve Bourne開發,是標準的UNIX Shell,很多UNIX系統都配有sh。

  • Korn Shell(ksh)
      由David Korn開發,是Bournd Shell(sh)的超集合併且添加了csh引入的新功能,是目前很多UNIX系統標配的Shell,這些系統上的/bin/sh往往指向/bin/ksh的符號鏈接

  • Bourne Again Shell(bash)
      由GNU項目組開發,主要目標是與POSIX標準操持一致,同時相容sh。bash從csh和ksh借鑒了很多功能,是各種Linux發行版本預設配置的Shell。Linux系統上的/bin/sh往往是指向/bin/bash的符號鏈接。但bash和sh還是有很多不同之處,雖然bash擴展了一些命令和參數,但bash並不完全相容sh,兩者之間有些行為並不一致。在大多數情況下區別不太大,有時還可以使用bash替代sh。

C Shell

    C Shell包括csh和tcsh兩種。csh由Berkeley大學開發,隨之BSD UNIX發佈,它的流程式控制制語句很像C語言,支持很多Bourne Shell所不支持的功能,如作業控制、別名、系統算術、命令歷史、命令行編輯等。tcsh是csh的增強版,加入了命令補全等功能,在FreeBSD、Mac OS X等系統上代替了csh。
    以上介紹的這些Shell中,較為通用的是標準的Bourne Shell(sh)和C Shell(csh),而其中Bourne Shell(sh)已經被Bourne Again Shell(bash)所取代。可通過以下命令查看CentOS 7.3系統Shell的支持情況。

[admin@CentOS7 tmp]$ cat /etc/shells
/bin/sh             #Linux常用的Shell,指向/bin/bash
/bin/bash           #Linux常用的Shell,也是預設使用的Shell
/sbin/nologin       #Linux常用的Shell,用於禁止用戶登錄
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
/bin/tcsh
/bin/csh

Linux系統中主流的Shell是bash,而bash是由Bourne Shell(sh)發展而來,同時bash還包含了csh和ksh的特色。因此大多數腳本都可以不做修改即可在sh運行,如果使用sh後結果與預期有差異,可以嘗試用bash代替sh.

常用操作系統預設Shell

    在常用的操作系統中,Linux中預設的Shell是Bourne Again Shell(bash),Solaris和FreeBSD下預設的是Bourne Shell(sh),AIX下預設的是Korn Shell(ksh)。那麼問題來了,我們該如何查看所使用系統的Shell?以CentOS為例查看系統預設的Shell:

  • 方法一:
[admin@CentOS7 tmp]$ echo $SHELL
/bin/bash
  • 方法二:
[admin@CentOS7 tmp]$ grep root /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

root用戶結尾的/bin/bash就是用戶登錄後的Shell解釋器。後續文章中重點講解的是Bourne Again Shell(bash)

Shell 腳本的建立和執行

Shell腳本的建立

    在Linux系統中,Shell腳本通常是在編輯器vi/vim中進行編寫。可由UNIX/Linux命令、bash shell命令、程式結構控制語句、註釋等組成,推薦使用vim。

  • Shell腳本開頭(第一行)
      一個規範標準的Shell腳本會在第一行指出由哪個解釋器來執行腳本中的內容,一般如下所示:
#!/bin/bash
或
#!/bin/sh

註意事項:

1、第一行一般要求小於255個字元。
2、#!/bin/bash不是註釋,在執行腳本時,內核會根據#!後的解釋器確定使用哪個解釋器來執行腳本的內容。
3、這一行必須位於每個腳本頂端的第一行,如果不是第一行則是代表註釋

#!/bin/bash
echo "bash test"
#!/bin/bash #代表該行是註釋
#!/bin/sh   #代表該行是註釋
  • bash和sh的區別
      早期的bash與sh稍有不同,bash包含csh和ksh的特色,但大多數的腳本都可以直接在sh上運行。
    3-3 bash和sh區別.jpg

從上圖可以看到sh為bash的軟鏈接,大多數情況下,腳本開頭使用#!/bin/bash和#!/bin/sh是沒有區別的。但還是建議採用#!/bin/bash

  一般情況下,安裝完Linux系統之後會自動安裝好bash軟體,查看bash版本如下所示:

[admin@CentOS7 etc]$ cat /etc/redhat-release
CentOS Linux release 7.3.1611 (Core) #當前系統版本
[admin@CentOS7 etc]$ bash --version
GNU bash, version 4.2.46(1)-release (x86_64-redhat-linux-gnu) # bash 版本,後續省略自由軟體提示信息

如果想體驗更高版本的bash,升級方法如下所示:

yum -y update bash #線上升級
rpm -qa bash  #查看bash安裝包
bash-4.2.46-20.el7_2.x86_64

  以下是常用腳本開頭的寫法,不同語言的腳本在開頭一般都要加上如下標識內容:

#!/bin/sh
#!/bin/bash
#!/usr/bin/awk
#!/bin/sed
#!/usr/bin/tcsh
#!/usr/bin/perl

    CentOS中預設的Shell均為bash。因此即在腳本中未加#!/bin/bash,它也會使用bash去解釋。如果不希望使用系統預設的Shell解釋器,就需要自行指定解釋器。建議大家一開始就養成好習慣,遵循Shell編程規範,在開頭第一行指定所使用的解釋器
    如果在開頭未指定解釋器,要使用對應的解釋器來執行腳本時,可以使用如下方法:

Shell腳本: bash test.sh或sh test.sh
Python腳本:python test.py
  • 腳本註釋

    在很多編程語言中,都會支持單行和多行註釋,方便閱讀和維護,在Shell中,使用#對所在行進行註釋,註釋的內容並不會當作命令執行。註釋可單獨一行也可以緊跟在命令後面。建議在寫腳本添加必要的註釋,方便自己也方便後續維護者或使用者。

註釋中儘量不要使用中文,腳本中也儘量不要使用中文

Shell腳本的執行

  • Shell腳本的執行流程
        當腳本運行時,它會先查找系統環境變數ENV,該變數指定了環境文件(載入順序通常是/etc/profile、~/.bash_profile、~/.bashrc、/etc/bashrc等),在載入了上述環境變數文件後,Shell開始執行Shell腳本中的內容。
        Shell腳本執行的順序是從上到下,從左到右依次執行每一行的命令及語句。如果Shell中存在腳本嵌套(子腳本)時,就會執行嵌套腳本的內容,完成後再返回父腳本繼續執行父腳本內後續的命令和語句。通常情況下,執行Shell腳本時,會向系統內核啟動一個新的進程,以便在該進程中執行腳本的命令和子腳本,其流程圖如下所示:
    3-4 Shell腳本執行基本流程圖_c2i.jpg

  • Shell腳本的執行方式

【1】bash script-name或sh script-name
    這種方式是當腳本文件本身沒有可執行許可權(即文件屬性沒有x占位符)時常使用的方式或腳本文件沒有指定解釋器時常用的方法。
3-5 Shell執行方式-1.jpg

【2】path/script-name或./script-name
    這種方式是指在當前路徑下執行腳本,前提是腳本必須有可執行許可權,具體方法為chmod +x script-name。然後通過相對路徑或絕對路徑執行腳本。
3-6 Shell執行方式-2.jpg

【3】source script-name或. script-name
    這種方法通常使用source或" . "讀入或載入指定的Shell腳本,如son.sh,然後依次執行指定的Shell腳本文件son.sh中的所有語句。這些語句將在當前父Shell腳本father.sh中運行(其他幾種模式都會啟動新的進程執行子腳本)。

使用source或" . "可以將son.sh自身腳本中的變數值或函數等的返回值傳遞到當前父Shell腳本father.sh中使用,這是和其他兩種方法最大的區別,因此需要特別註意。

3-7 Shell執行方式-3_c2i.jpg

【4】sh<script-name或cat script-name | sh
    這種方法同樣適用於bash,這種方法並不常見,瞭解知道即可。其原理就是利用了管道技術。

3-8 Shell執行方式-4.jpg

  • 示例

大家可以看看以下腳本的正確答案是哪一個?

3-9 Shell執行示例-1.jpg

參考的答案選項如下所示:

  • [ ] 當前用戶
  • [ ] admin
  • [ ] 無內容輸入

正確答案是無內容輸入。原因可查看Shell腳本的幾種執行方式。

通過這個示例我們可以得出如下結論:

  • 子Shell腳本會直接繼承父Shell的變數、函數等,如兒子繼承父親基因。
  • 如果希望父Shell繼承子Shell的變數,就要使用source或" . "

3-10 Shell執行示例-2.jpg

腳本規範

    每種語言都有自己的開發規範,雖然不是強制遵守,但有規範的代碼不便方便閱讀、維護、多人協同開發,同時也能減少出現Bug的概率。主要的規範如下所示:

  • 【1】Shell腳本的第一行指定腳本解釋器
#!/bin/bash
或
#!/bin/sh
  • 【2】Shell腳本的開關添加版本、版權、作者等
#Date:2017-11-29 22:50
#Author:Surpassme
#Description:This is sample shell scripts
#Version:1.5
  • 【3】Shell腳本中儘量不要使用中文
      雖說Linux也能相容中文,但還是存在切換系統環境後中文出現亂碼的問題。如果非要用中文,可對系統進行字元集調整。如export LANG="zh_CN.UTF-8",併在腳本中重新定義字元集設置和系統保持一致。

  • 【4】Shell腳本儘量添加擴展名.sh

  • 【5】養成良好的腳本書寫習慣
1、成對的符號儘量一次性寫全,防止遺漏
2、中括弧([])兩端至少要保留一個空格。
3、流程式控制制語句,應一次性將格式寫完,再添加內容
4、良好的代碼縮進,方便閱讀
5、腳本的各個符號必須為英文狀態下的符號
6、常規變數的字元串定義時應加雙引號("")並且等號前後均不能有空格,需要強引用(指所見即所得的字元串引用),則使用單引號(''),如果是命令引用,則用反引號(``)

本文同步在微信訂閱號上發佈,如各位小伙伴們喜歡我的文章,也可以關註我的微信訂閱號:woaitest,或掃描下麵的二維碼添加關註:
MyQRCode.jpg


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 原則的誕生:面向對象:封裝、繼承、多態三大支柱蘊含了用抽象來封裝變化,降低耦合,實現復用的精髓; 封裝:隱藏內部的實現,保護內部信息; 繼承:實現復用,歸納共性; 多態:改寫對象行為,實現更高級別的繼承 要實現這些目的,就必須遵守一些原則:封裝變化、對介面編程、少繼承多聚合 實現系統的可擴展、可復用 ...
  • FormsAuthentication.SetAuthCookie(UserFlag, createPersistentCookie); createPersistentCookie是否永久保存cookie https://www.cnblogs.com/joeylee/p/3521131.html ...
  • 一、線程開銷 操作系統創建線程是有代價的,其主要開銷在下麵列舉出來了。 記憶體開銷 1. 線程內核對象 擁有線程描述屬性與線程上下文,線程上下文占用的記憶體空間為 x86 架構 占用 700 位元組、x64 架構 1240 位元組 、ARM 架構 350 位元組。 2. 線程環境塊(TEB) TEB 消耗一個 ...
  • 一、什麼是運行時序列化 序列化的作用就是將對象圖(特定時間點的對象連接圖)轉換為位元組流,這樣這些對象圖就可以在文件系統/網路進行傳輸。 二、序列化/反序列化快速入門 一般來說我們通過 FCL 提供的 對象就可以將一個對象序列化為位元組流進行存儲,或者通過該 Formatter 將一個位元組流反序列化為一 ...
  • 在上一篇緒中,已經介紹了整個項目的情況下了,接下來就是開始一步步做起來了。 首先:先整個我們的Job任務表,以及Job執行日誌表。SQL如下: 1 drop table if exists job_info; 2 create table job_info 3 ( 4 id int not null ...
  • more命令,功能類似 cat ,cat命令是整個文件的內容從上到下顯示在屏幕上。 more會以一頁一頁的顯示方便使用者逐頁閱讀,而最基本的指令就是按空白鍵(space)就往下一頁顯示,按 b 鍵就會往回(back)一頁顯示,而且還有搜尋字串的功能 。more命令從前向後讀取文件,因此在啟動時就載入 ...
  • findfs 查找指定捲標或者UUID的文件系統對應的設備文件。findfs將搜索系統中的磁碟,尋找具有標簽匹配標簽或與UUID相等的文件系統。如果找到文件系統,文件系統的設備名稱將列印在stdout上。 此命令的適用範圍:RedHat、RHEL、Ubuntu、CentOS、SUSE、openSUS ...
  • 昨晚更新了一下內核,今晚開機就無法進系統了...提示如下圖: 解決方案:開機啟動時按Esc,然後選擇下麵的舊版本的內核啟動即可。 (成功進入系統後,你可以選擇改變開機預設選擇的內核)。 uname -r 查看當前內核版本 rpm -qa|grep kernel 查看系統已安裝的內核 vim /boo ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...