Shell 腳本系統學習 · 第5篇:多命令順序執行的三種方式詳解(`;`、``、`||`)

在日常的 Linux 運維與腳本編寫中,我們經常需要依次執行多條命令。本篇將帶你徹底搞懂三種命令順序執行方式:;&&||,并通過實用示例掌握它們的區別與應用場景。


一、為什么要了解多命令執行方式?

在實際運維或腳本編寫中,往往需要連續執行多條命令:

  • 有時希望某條命令出錯也能繼續往下做;
  • 有時希望后續命令僅在前面執行成功后才運行;
  • 也有時要在某條命令失敗時額外做補救。

掌握 ;&&|| 這三種操作符,就能靈活控制“先后順序”與“成功/失敗依賴”,讓腳本更健壯、更易維護。


二、; — 命令分隔符也叫順序執行符

表示:兩個命令是獨立的,無論前一個命令執行結果如何,后一個都會執行

1. 語法格式

命令1 ; 命令2 ; 命令3 ;

解釋:使用分號(;)將多條命令分隔,Shell 會依次執行它們,無論前一條命令是否成功,都會繼續執行下一條。

2. 示例

  • 命令1,whoami 查看當前用戶
  • 命令2,cat file.txt 查看當前目錄file.txt文件(這里file.txt不存在,執行時會報錯,也就是第二條命令執行失敗)
  • 命令3,ls -la 查看當前目錄的所有文件/目錄
#!/bin/bash
whoami;cat file.txt;ls -la

3. 輸出結果

即使第二條寫成了 cet file.txt(寫錯命令),也不會阻止第三條執行(下面我把 cat 改為 cet

#!/bin/bash
whoami;cet file.txt;ls -la

4. 詳細說明

  • 執行順序:從左到右逐條執行。
  • 錯誤忽略:前一條返回非 0 (失敗)也不影響下一條的執行。
  • 適用場景:當你只需保證“一行里列出的命令都會嘗試執行一次”,不在乎它有沒有出錯。例如:批量創建目錄后,按順序設置權限、啟動服務等,即使中間某步出錯,也要繼續嘗試后面操作。

5. 小結

  • 作用:無條件順序執行,多條命令都會執行。
  • 適合場景:不關心某步是否成功,只要“都試一遍”即可。
  • windows CMD中; 對應 Windows 的& 其他兩個都一樣

三、&& —— 邏輯與運算符

表示:如果前面的命令執行成功,再執行后面的命令

1. 語法格式

命令1 && 命令2 && 命令3 &&

解釋:只有當 命令1 返回值為 0(成功)時,才會執行 命令2;同理,命令2 成功后才執行 命令3。一旦某條命令失敗(非 0),后續命令將不再執行。

2. 示例

當前目錄下不存在test目錄,所以執行 cd test 時會提示錯誤

#!/bin/bash
echo "執行第一條命令" && cd test && "執行第三條命令"
cd test && echo "執行第二條命令" && "執行第三條命令"

3. 輸出示例

4. 詳細說明

  • 成功觸發&& 鏈中的一項只有在前一項成功時才執行。
  • 返回值:整個鏈式命令的返回值等于最后一個成功執行的命令返回值;若中途失敗,則返回失敗的那條命令的返回值。
  • 適用場景
    • 多步驟“級聯”操作:如先下載包、再解壓、再安裝,任何一步失敗都要停止后續。
    • 條件判斷:如先檢查網絡連通性,再執行更新;若檢查失敗,后續操作不執行。

5. 小結

  • 作用:僅在前一命令成功時才執行下一命令。
  • 適合場景:多步驟“必須成功才能往下做”的情況。

四、|| —— 邏輯或運算

前命令執行失敗了,才執行后面的命令

1. 語法格式

命令1 || 命令2 || 命令3 ||

解釋:只有當 命令1 返回非 0(失敗)時,才會執行 命令2;若 命令1 成功(返回 0),則跳過 命令2。依次類推:前一條失敗時才會繼續執行下一條。

2. 示例:

當前目錄下不存在 data 目錄

#!/bin/bash
cd data || pwd
pwd || cd /data

3. 輸出結果

  • cd data 進入當前目錄下的 data 目錄
  • 如果 data 目錄不存在(判斷返回非 0),才執行 pwd

Tip:為了邏輯更清晰,shell腳本中通常會寫成 if … else 結構,避免單行邏輯混淆。后續我會出條件判斷文章,一步一步來哦~

4. 小結

  • 作用:僅在前一命令失敗時才執行下一命令。
  • 適合場景:針對“異常/失敗”進行補救、日志記錄、報警通知等。

五、三者結合使用示例

在實際腳本中,常將 ;&&|| 混合使用,實現更靈活的流程控制。下面示例演示:

  1. 部署 Tomcat 9.0.105
  2. 下載地址:https://archive.apache.org/dist/tomcat/tomcat-9/v9.0.100/bin/apache-tomcat-9.0.100.tar.gz
  3. 工作目錄:/data/web-service
  4. 日志路徑:/data/web-service/logs/catalina.out
  5. 當然如果你想下載tomcat 8、10、11只需要替換DOWNLOAD_URL變量中的數字即可
#!/bin/bash
# 定義變量
WORK_DIR="/data/web-service" #定義工作目錄變量
TOMCAT_VERSION="9.0.100"     #定義tomcat小版本變量
TAR_NAME="apache-tomcat-${TOMCAT_VERSION}.tar.gz"  #定義tomcat下載包變量
DOWNLOAD_URL="https://archive.apache.org/dist/tomcat/tomcat-9/v${TOMCAT_VERSION}/bin/${TAR_NAME}"  #定義tomcat下載路徑,以及大版本,如果想下載tomcat8,直接把這里9改成8,然后修改對應的小版本號LOG_DIR="${WORK_DIR}/logs" #定義日志目錄
LOG_FILE="${LOG_DIR}/catalina.out"# 創建工作目錄和日志目錄
mkdir -p "$WORK_DIR" "$LOG_DIR" && echo "【創建目錄】工作目錄和日志目錄已創建" || { echo "【錯誤】無法創建目錄"; exit 1; }
cd "$WORK_DIR" || { echo "【錯誤】無法進入 $WORK_DIR"; exit 1; }
echo "【開始部署】Tomcat ${TOMCAT_VERSION} 部署開始于 $(date '+%F %T')"# 清空舊日志文件
> "$LOG_FILE" && echo "【初始化】日志文件已清空" || echo "【警告】日志文件不存在或無法清空"# 檢查是否已有 Tomcat 目錄,有則刪除
[ -d "apache-tomcat-${TOMCAT_VERSION}" ] && rm -rf "apache-tomcat-${TOMCAT_VERSION}" && echo "【清理】舊版 Tomcat 已刪除" ; echo "【檢查】當前無舊版 Tomcat 或已清理完畢"# 下載 Tomcat(如果不存在)
if [ ! -f "$TAR_NAME" ]; thenecho "【下載】開始下載 Tomcat..."wget -q --show-progress "$DOWNLOAD_URL"if [ $? -eq 0 ]; thenecho "【下載】Tomcat 已下載成功"elseecho "【錯誤】下載失敗,請檢查網絡或 URL"exit 1fi
elseecho "【下載】安裝包已存在,跳過下載..."
fi# 解壓 Tomcat
tar -zxpf "$TAR_NAME" > /dev/null 2>&1 && echo "【解壓】Tomcat 解壓成功" || { echo "【錯誤】解壓失敗,請檢查壓縮包"; exit 1; }# 啟動 Tomcat(后臺運行),輸出重定向到日志文件
./apache-tomcat-${TOMCAT_VERSION}/bin/startup.sh >> "$LOG_FILE" 2>&1 &
if [ $? -eq 0 ]; thenecho "【啟動】Tomcat 已啟動(后臺運行)"
elseecho "【錯誤】啟動失敗,請查看日志文件"exit 1
fi# 等待幾秒確保進程已經啟動
sleep 3# 輸出 Tomcat 進程信息
PID=$(ps -ef | grep java | grep "apache-tomcat-${TOMCAT_VERSION}" | awk '{print $2}')
if [ -n "$PID" ]; thenecho "【狀態】Tomcat 已運行,PID: $PID"
elseecho "【警告】未找到 Tomcat 進程,請檢查日志"
fiecho "【完成】部署流程結束于 $(date '+%F %T')"

要點解析

  • 第1步|| 判斷目錄是否存在,否則創建;再用 && 打印日志。
  • 第2步&& 判斷 cd 成功與否;失敗則用大括號 { … } 打印日志并退出。

六、常見誤區與注意事項

  1. 不加大括號導致邏輯混淆

    cmd1 && cmd2 || cmd3
    
    • 含義:如果 cmd1 成功,才會執行 cmd2;但無論 cmd1cmd2 哪一個失敗,都會執行 cmd3

    • 若想實現“僅當 cmd1 成功且 cmd2 失敗時才 cmd3”,需加大括號:

      cmd1 && { cmd2 || cmd3; }
      
  2. 分號與換行的等價性

    cmd1; cmd2
    

    等同于:

    cmd1
    cmd2
    

    僅是寫法不同。分號適合一行寫多個短命令;若邏輯復雜,推薦換行并加注釋。

  3. 混合使用時要注意優先級

    • Shell 會先解析 &&||,最后處理 ;
    • 當同時出現 &&||; 時,建議適當用“換行 + 大括號”來讓邏輯更清晰,避免歧義。

七、小白友好的命令對照表

操作符含義示例適用場景
;無條件順序執行echo A ; echo B ; echo C不關心命令是否成功,只要全部都執行一次
&&成功則繼續執行mkdir /tmp/dir && echo "創建成功"僅在前一步成功時才做后續操作
||失敗則繼續執行cp A B || echo “復制失敗”用于失敗補救、日志記錄、報警通知

八、運維示例腳本:一鍵日志輪轉與備份

下面附上一個可直接拿來使用的運維腳本,通過 ;&&|| 三種方式,實現對指定服務日志的輪轉、壓縮、備份,并保留最近 7 天的歷史。適用于 CentOS/Ubuntu 等常見 Linux 發行版。

腳本功能概覽

  1. 停止目標服務
  2. 將日志文件按日期重命名并壓縮備份到指定目錄
  3. 刪除 7 天前的舊備份
  4. 啟動目標服務
  5. 將執行結果寫入操作日
    腳本下載方式,關注公眾號【安全日記Pro】,進入發送消息,點擊shell菜單,獲取腳本

📝 腳本使用說明

  1. 保存腳本
    將以上內容保存為 log_rotate_backup.sh,并賦予可執行權限:

    chmod +x log_rotate_backup.sh
    
  2. 執行腳本示例

    sudo sh log_rotate_backup.sh \tomcat "/var/log/tomcat/access.log" \"/backup/logs/tomcat" "/var/log/tomcat/rotate.log"
    
    • 腳本會對 /var/log/tomcat/access.log 進行輪轉備份,
    • 備份文件存放在 /backup/logs/tomcat/2025-06/ 目錄下,
    • 并將操作記錄寫入 /var/log/tomcat/rotate.log

  1. 定時執行(Crontab 可選)
    可將腳本加入 crontab,實現每日自動輪轉。例如每天凌晨 1 點執行:

    #腳本路徑根據你實際情況填寫
    0 1 * * * /usr/local/bin/log_rotate_backup.sh \tomcat "/var/log/tomcat/access.log" \"/backup/logs/tomcat" "/var/log/tomcat/rotate.log"
    

九、結語與小白學習建議

  1. 多練、多試

    • 親手在終端嘗試不同的 ;&&|| 組合,觀察 $? 的返回值和后續命令的執行情況,體驗它們的執行邏輯。
  2. 使用 set -e(可選)

    • 在腳本開頭添加 set -e,可以讓腳本在任意一步出現非 0 返回值時立即退出。但要注意與 ||&& 的混用可能導致流程不如預期,初學者可先不加,待熟悉后再靈活運用。
  3. 日志與錯誤處理很關鍵

    • 像示例腳本一樣,將執行結果寫到日志文件,并在失敗時發送報警或退出腳本,是做好運維腳本的關鍵。
  4. 牢記返回值判斷

    • 在 Shell 中,返回值 0 = 成功,非 0 = 失敗。掌握這一點,就能自然而然地運用 &&|| 進行流程控制。

本篇小結

  • ;:無條件順序執行,所有命令都會嘗試執行。
  • &&:前一步成功時才執行下一步,適合級聯式操作。
  • ||:前一步失敗時才執行下一步,適合“失敗補救”或“日志/報警”。
  • 混合使用時要加大括號或換行,避免邏輯歧義。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/91301.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/91301.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/91301.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

K8s存儲系統(通俗易懂版)

Kubernetes中存儲中有四個重要的概念:Volume、PersistentVolume PV、PersistentVolumeClaim PVC、StorageClass一、存儲系統核心概念Volume(卷)定義:Kubernetes 中最基礎的存儲單元,用于將外部存儲掛載到 Pod 中的容器…

小白學Python,標準庫篇——隨機庫、正則表達式庫

一、隨機庫1.隨機生成數值在random庫中可以隨機生成數值的方法有uniform()、random()、randint()、randrange()等。(1)uniform()方法uniform(參數1, 參數2)方法用于生成參數1到參數2之間的隨機小數,其中參數的類型都為數值類型。示例代碼&…

Qt窗口:菜單欄

目錄 一、窗口預覽 二、菜單欄 快捷鍵 子菜單 分割線 圖標 內存泄露 一、窗口預覽 在前面幾篇文章中,或者說,Qt初學階段,接觸到的都是QWidget,QWidget指控件,往往作為一個窗口的一部分出現。所謂的窗口&#x…

STM32裸機開發(中斷,輪詢,狀態機)與freeRTOS

裸機:沒有操作系統,程序是單流程的(比如一個大循環里依次執行各個功能,或者用中斷嵌套處理事件)。優點是資源占用極少(幾乎不占 RAM/Flash)、執行流程直觀;但復雜項目里,…

電腦上如何查看WiFi密碼

打開控制面板>點擊網絡和Internet在查看網絡和共享中心找到網絡狀態和任務點擊進去點擊連接的WLAN在WLAN狀態中點擊無線屬性在無線網絡屬性中點擊安全,點擊顯示字符(H)就可以顯示密碼了

文心一言4.5企業級部署實戰:多模態能力與Docker容器化測評

隨著大語言模型在企業服務中的應用日益廣泛,如何選擇一款既能滿足多模態創作需求,又具備良好企業級適配性的AI模型成為了關鍵問題。文心一言4.5作為百度最新開源的大模型,不僅在傳統的文本處理上表現出色,更是在多模態理解和企業級…

VUE Promise基礎語法

目錄 異步和同步 異步的問題 new Promise語法 promise的狀態 promise.then() Promise.resolve() Promise.reject() Promise.all() Promise.race() Promise.catch() Promise.finally() 異步和同步 同步模式下,代碼按順序執行,前一條執行完畢后…

用TensorFlow進行邏輯回歸(六)

import tensorflow as tfimport numpy as npfrom tensorflow.keras.datasets import mnistimport time# MNIST數據集參數num_classes 10 # 數字0到9, 10類num_features 784 # 28*28# 訓練參數learning_rate 0.01training_steps 1000batch_size 256display_step 50# 預處…

【HTTP版本演變】

在瀏覽器中輸入URL并按回車之后會發生什么1. 輸入URL并解析輸入URL后,瀏覽器會解析出協議、主機、端口、路徑等信息,并構造一個HTTP請求(瀏覽器會根據請求頭判斷是否又HTTP緩存,并根據是否有緩存決定從服務器獲取資源還是使用緩存…

Android 16系統源碼_窗口動畫(一)窗口過渡動畫層級圖分析

一 窗口過渡動畫 1.1 案例效果圖1.2 案例源碼 1.2.1 添加權限 (AndroidManifest.xml) <!-- 系統懸浮窗權限&#xff08;Android 6.0需動態請求&#xff09; --> <uses-permission android:name"android.permission.SYSTEM_ALERT_WINDOW" />1.2.2 窗口顯示…

騰訊云WAF域名分級防護實戰筆記

基于業務風險等級、合規要求及騰訊云最佳實踐&#xff0c;提供可直接落地的配置方案&#xff0c;供學習借鑒&#xff1a;一、域名分級與防護原則1. ?域名分級清單&#xff08;核心資產&#xff09;???主域名??業務類型??風險等級??合規要求??防護等級?example.com…

1. 請說出你知道的水平垂直居中的方法

總結 容器 flex 布局&#xff0c;jsutify-content: center; align-items: center;容器 flex 布局&#xff0c;子項 margin: auto;容器 relative 布局&#xff0c;子項 absolute 布局&#xff0c;left: 50%; top: 50%; transform: translate(-50%, -50%);子項 absolute 布局&…

VS Code `launch.json` 完整配置指南:參數詳解 + 配置實例

文章目錄&#x1f4e6; 一、基本結構&#x1f50d; 二、單個配置項詳解示例配置&#xff1a;&#x1f9e9; 三、字段說明與可選值&#x1f4c1; 四、常用變量&#xff08;宏替換&#xff09;&#x1f6e0;? 五、常見配置實例1?? 調試當前打開的 .py 文件2?? 調試 Jupyter …

使用瀏覽器inspect調試wx小程序

edge://inspect/#devices調試wx小程序 背景&#xff1a; 在開發混合項目的過程中&#xff0c;常常需要在app環境排查問題&#xff0c;接口可以使用fiddler等工具來抓包&#xff0c;但是js錯誤就不好抓包了&#xff0c;這里介紹一種調試工具-瀏覽器。 調試過程 首先電腦打開edg…

【論文閱讀】-《Simple Black-box Adversarial Attacks》

簡單黑盒對抗攻擊 Chuan Guo Jacob R. Gardner Yurong You Andrew Gordon Wilson Kilian Q. Weinberger 摘要 我們提出了一種在黑盒&#xff08;black-box&#xff09;場景下構建對抗樣本&#xff08;adversarial images&#xff09;的極其簡單的方法。與白盒&#xff08;…

基于ASP.NET+SQL Server實現(Web)企業進銷存管理系統

企業進銷存管理系統的設計和實現一、摘要進銷存管理是現代企業生產經營中的重要環節&#xff0c;是完成企業資源配置的重要管理工作&#xff0c;對企業生產經營效率的最大化發揮著重要作用。本文以我國中小企業的進銷存管理為研究對象&#xff0c;描述了企業進銷存管理系統從需…

(LeetCode 面試經典 150 題 ) 15. 三數之和 (排序+雙指針)

題目&#xff1a;15. 三數之和 思路&#xff1a;排序雙指針&#xff0c;時間復雜度0(n^2nlogn)。 先將數組nums升序排序&#xff0c;方便去重和使用雙指針。第一層for循環來枚舉第一位數&#xff0c;后面使用雙指針來找到第二個、第三個數即可&#xff0c;細節看注釋。 C版本…

easy-springdoc

介紹 簡化springdoc的使用&#xff08;可以搭配knife4j-openapi3-jakarta-spring-boot-starter一起使用&#xff09; maven引用 <dependency><groupId>io.github.xiaoyudeguang</groupId><artifactId>easy-springdoc</artifactId><version>…

配置nodejs,若依

1.配置node.js環境 Node.js — Download Node.js 1.下載好一路下一步&#xff0c;可以安裝到d盤 裝完之后執行 npm -v 顯示版本號即安裝成功 2.安裝好后新建兩個文件夾&#xff0c;node_cache和node_global 3.配置環境變量 新建變量 在path里編輯變量 4.配置用戶變量 5.…

Python學習之路(十二)-開發和優化處理大數據量接口

文章目錄一、接口設計原則二、性能優化策略1. 數據庫優化2. 緩存機制3. 并發模型三、內存管理技巧1. 內存優化實踐2. 避免內存泄漏四、接口測試與監控1. 性能測試2. 日志與監控3. 錯誤處理與限流五、代碼示例&#xff08;Flask 流式處理&#xff09;六、部署建議一、接口設計原…