12.Shell腳本修煉手冊--函數的基礎認知與實戰演練(fock炸彈!!)

Shell 函數的知識與實踐

文章目錄

    • Shell 函數的知識與實踐
      • Shell 函數介紹
      • Shell 函數的語法
      • Shell 函數的執行
        • 1. 不帶參數的函數執行
        • 2. 帶參數的函數執行
      • Shell 函數的基礎實踐
        • 示例 1:簡單的 hello 函數(驗證 “先定義后調用”)
        • 示例 2:調用外部文件中的函數
        • 示例 3:帶參數的函數(根據輸入輸出彩色文字)
        • 示例 4:函數參數與腳本參數的關系
      • 企業級 URL 檢測腳本
      • 函數的遞歸調用(函數調用自身)
        • 示例 1:遞歸求 1+2+...+n 的和
        • 示例 2:遞歸求 n 的階乘(1*2*...*n)
        • 示例 3:fork 炸彈(危險!僅作原理了解)
      • 總結

Shell 函數介紹

在學習 Shell 函數之前,我們先回憶一下 Linux 中的 alias(別名)功能。比如我們常用 ll 代替 ls -l --color=auto,就是通過別名實現的:

# 直接執行詳細列表命令,顯示/home目錄內容(--color=auto自動為文件著色)
[bq@controller shell 14:15:42]$ ls -l --color=auto /home
總用量 0
drwx------. 5 bq bq 124 823 14:15 bq# 創建別名:用ll代替ls -l --color=auto
[bq@shell ~]$ alias ll='ls -l --color=auto'# 用別名執行,效果和原命令完全一致
[bq@controller shell 14:25:23]$ ll /home/
總用量 0
drwx------. 5 bq bq 124 823 14:15 bq

Shell 函數和別名類似,都能簡化操作,但功能更強大。簡單來說,函數就是把一段重復使用的代碼 “打包”,起一個名字。之后想使用這段代碼時,直接調用這個名字就行。如果需要修改這段代碼,只改 “打包” 好的那一份,所有調用的地方都會同步更新。我們也可以把函數存到單獨的文件里,需要時再加載使用。

使用 Shell 函數的好處:

  • 減少重復代碼:一段代碼多次用,定義成函數后不用反復寫,提高開發效率。
  • 增強可讀性:用有意義的函數名代替一堆命令,代碼更易懂、易維護。
  • 實現模塊化:把功能拆分成函數,讓腳本更通用,方便移植到其他場景。

小貼士:Linux 系統中的近 2000 個命令,其實都可以理解為 Shell 的 “內置函數”,可見函數在 Shell 中的重要性。

Shell 函數的語法

Shell 函數有多種定義方式,核心都是 “函數名 + 代碼塊”,以下是常見格式:

標準寫法

function 函數名 () {指令...  # 函數要執行的代碼return n  # 可選,返回一個狀態值(0-255,0表示成功)
}

簡化寫法 1:省略小括號 ()

function 函數名 {  # 去掉了函數名后的(),其他和標準寫法一致指令...return n
}

簡化寫法 2:省略 function 關鍵字

函數名 () {  # 去掉了function,保留()和代碼塊指令...return n
}

三種寫法功能完全一樣,實際使用中可以根據習慣選擇。

Shell 函數的執行

Shell 函數分為 “不帶參數” 和 “帶參數” 兩種,執行方式略有不同,下面詳細說明:

1. 不帶參數的函數執行

直接輸入函數名即可(注意:函數名后不要加小括號),格式:

函數名  # 直接調用函數

重要說明(必看)

  • 調用函數時,不要加 function 關鍵字,也不要加小括號(比如定義了 hello(),調用時直接寫 hello)。
  • 函數必須 “先定義,后調用”:如果在調用之后才定義函數,Shell 會提示 “命令未找到”。
  • 執行優先級:Shell 執行程序的順序是「系統別名 → 函數 → 系統命令 → 可執行文件」。比如如果有一個別名 ll、一個函數 ll 和系統命令 ll,執行 ll 時會先執行別名。
  • 變量共享:函數和調用它的腳本會共用變量,但可以用 local 定義 “局部變量”(僅在函數內有效,函數結束后消失)。
  • returnexit 的區別:return 是退出函數,返回一個狀態值給調用者;exit 是直接退出整個腳本,返回狀態值給當前 Shell。
  • 外部函數加載:如果函數存放在單獨的文件中,需要用 source 文件名. 文件名 加載后才能調用(source. 作用相同)。
2. 帶參數的函數執行

調用時在函數名后直接跟參數,格式:

函數名 參數1 參數2  # 參數之間用空格分隔

參數說明

  • 函數內部用 “位置參數” 接收參數:$1 表示第 1 個參數,$2 表示第 2 個參數,$# 表示參數總數,$*$@ 表示所有參數,$? 表示上一條命令的返回值。
  • 臨時覆蓋父腳本參數:函數執行時,父腳本的參數會被函數參數臨時 “掩蓋”,函數執行完后,父腳本參數恢復正常。
  • $0 特殊:始終表示父腳本的文件名,不會被函數參數影響。

Shell 函數的基礎實踐

示例 1:簡單的 hello 函數(驗證 “先定義后調用”)

實驗流程

  1. 編寫腳本,先定義 hello 函數(輸出 “Hello World !”),再調用函數,觀察執行結果。
  2. 編寫另一個腳本,先調用 hello 函數,再定義函數,觀察錯誤結果。

詳細步驟

# 腳本1:先定義函數,再調用
[bq@shell ~]$ cat fun1.sh 
#!/bin/bash
# 定義hello函數:輸出Hello World !
function hello () {echo "Hello World !"
}
# 調用hello函數(直接寫函數名)
hello# 執行腳本,成功輸出結果
[bq@shell ~]$ bash fun1.sh 
Hello World !# 腳本2:先調用函數,再定義(錯誤示范)
[bq@shell ~]$ cat fun2.sh 
#!/bin/bash
# 先調用hello函數(此時函數還未定義)
hello
# 后定義hello函數
function hello () {echo "Hello World !"
}# 執行腳本,提示“hello: 命令未找到”(因為調用時函數還不存在)
[bq@shell ~]$ bash fun2.sh
fun2.sh: line 2: hello: command not found

結論:函數必須先定義,后調用,否則會報錯。

示例 2:調用外部文件中的函數

實驗流程

  1. 創建一個存放函數的文件 mylib(定義 hello 函數)。
  2. 編寫腳本 fun3.sh,通過 source 加載 mylib 中的函數,然后調用。
  3. 執行腳本,驗證能否成功調用外部函數。

詳細步驟

# 1. 創建存放函數的文件mylib
[bq@shell ~]$ cat >> mylib << 'EOF'  # 用here document寫入內容,'EOF'表示內容中的變量不解析
function hello () {echo "Hello World !"  # 函數功能:輸出Hello World !
}
EOF# 2. 編寫調用腳本fun3.sh
[bq@shell ~]$ cat fun3.sh 
#!/bin/bash
# 檢查mylib文件是否存在且可讀(-r選項:判斷文件存在且可讀)
if [ -r mylib ];thensource mylib  # 加載mylib文件中的函數(source等同于. mylib)
elseecho "mylib文件不存在或不可讀"  # 如果文件不存在,提示錯誤exit 1  # 退出腳本,返回狀態碼1(表示執行失敗)
fi
hello  # 調用加載的hello函數# 3. 執行腳本,成功調用外部函數
[bq@shell ~]$ bash fun3.sh 
Hello World !

結論:通過 source 可以加載外部文件中的函數,實現代碼復用。

示例 3:帶參數的函數(根據輸入輸出彩色文字)

實驗流程

  1. 定義 print 函數,接收參數 PASS/FAIL/DONE,分別輸出綠色、紅色、紫色文字;其他參數提示用法。
  2. 腳本中通過 read 命令獲取用戶輸入,傳給 print 函數。
  3. 測試不同輸入(PASS/FAIL/DONE/ 其他文字),觀察輸出結果。

詳細步驟

# 編寫腳本fun4.sh
[bq@shell ~]$ cat fun4.sh 
#!/bin/bash
# 定義print函數:根據參數輸出彩色文字
function print () {# 判斷參數是否為PASS:輸出綠色文字(\033[1;32m是綠色高亮,\033[0;39m恢復默認顏色)if [ "$1" == "PASS" ];thenecho -e '\033[1;32mPASS\033[0;39m'  # -e選項:解析轉義字符(如顏色控制符)# 判斷參數是否為FAIL:輸出紅色文字elif [ "$1" == "FAIL" ];thenecho -e '\033[1;31mFAIL\033[0;39m'# 判斷參數是否為DONE:輸出紫色文字elif [ "$1" == "DONE" ];thenecho -e '\033[1;35mDONE\033[0;39m'# 其他參數:提示用法elseecho "Usage: print PASS|FAIL|DONE"fi
}
# 交互式讀取用戶輸入,-p選項:顯示提示文字
read -p "請輸入你想要打印的內容:" str
# 調用print函數,傳入用戶輸入的參數
print $str# 測試1:輸入PASS(輸出綠色PASS)
[bq@shell ~]$ bash fun4.sh 
請輸入你想要打印的內容:PASS
PASS  # 實際顯示為綠色高亮# 測試2:輸入FAIL(輸出紅色FAIL)
[bq@shell ~]$ bash fun4.sh 
請輸入你想要打印的內容:FAIL
FAIL  # 實際顯示為紅色高亮# 測試3:輸入DONE(輸出紫色DONE)
[bq@shell ~]$ bash fun4.sh 
請輸入你想要打印的內容:DONE
DONE  # 實際顯示為紫色高亮# 測試4:輸入其他文字(提示用法)
[bq@shell ~]$ bash fun4.sh 
請輸入你想要打印的內容:hello
Usage: print PASS|FAIL|DONE

補充說明

  • read -p "提示信息" 變量名:用于交互式獲取用戶輸入,-p 顯示提示文字。
  • 顏色控制符:\033[1;32m 中,1 表示高亮,32 表示綠色(31 = 紅,35 = 紫),\033[0;39m 用于恢復默認顏色,避免后續文字也變色。
示例 4:函數參數與腳本參數的關系

實驗流程

  1. 編寫腳本 fun5.sh,定義 print 函數(邏輯同示例 3),腳本中通過 $2 獲取第二個參數傳給函數。
  2. 測試腳本傳入不同參數,觀察函數是否使用腳本的參數,以及 $0 的值(腳本名還是函數名)。

詳細步驟

# 編寫腳本fun5.sh
[bq@shell ~]$ cat fun5.sh 
#!/bin/bash
function print () {if [ "$1" == "PASS" ];thenecho -e '\033[1;32mPASS\033[0;39m'elif [ "$1" == "FAIL" ];thenecho -e '\033[1;31mFAIL\033[0;39m'elif [ "$1" == "DONE" ];thenecho -e '\033[1;35mDONE\033[0;39m'else# $0始終表示腳本名(而非函數名)echo "Usage: $0 PASS|FAIL|DONE"fi
}
str=$2  # 腳本的第二個參數賦值給變量str
print $str  # 函數使用腳本的第二個參數# 測試1:腳本傳入兩個參數(PASS和FAIL)
[bq@shell ~]$ bash fun5.sh PASS FAIL
FAIL  # 函數接收的是腳本的第二個參數(FAIL),輸出紅色FAIL# 測試2:腳本不傳入參數(觸發else分支)
[bq@shell ~]$ bash fun5.sh 
Usage: fun5.sh PASS|FAIL|DONE  # $0顯示為腳本名fun5.sh,而非函數名print

結論

  • 函數參數需要顯式從腳本參數中傳遞(如腳本的 $2 傳給函數的 $1)。
  • $0 始終表示當前腳本的文件名,和函數名無關。

企業級 URL 檢測腳本

實驗流程

  1. 定義 usage 函數:提示腳本用法(如參數錯誤時調用)。
  2. 定義 check_url 函數:用 wget 檢測 URL 是否可訪問。
  3. 定義 main 函數:檢查參數數量,調用 check_url 函數。
  4. 執行腳本,測試有效 URL(如百度)和無效 URL,觀察結果。

詳細步驟

# 編寫檢測腳本check_url.sh
[bq@shell ~]$ cat check_url.sh 
#!/bin/bash
# 用法提示函數:當參數錯誤時調用
function usage () {echo "usage: $0 url"  # 提示正確用法:腳本名 + URLexit 1  # 退出腳本,狀態碼1表示錯誤
}# URL檢測函數:接收URL參數,判斷是否可訪問
function check_url () {# wget選項說明:# --spider:模擬爬蟲(只檢查URL是否存在,不下載內容)# -q:安靜模式(不輸出日志)# -o /dev/null:將日志輸出到“黑洞”(徹底不顯示)# --tries=1:嘗試1次(失敗不重試)# -T 5:超時時間5秒wget --spider -q -o /dev/null --tries=1 -T 5 $1# 判斷上一條命令的返回值($?):0表示成功,非0表示失敗[ $? -eq 0 ] && echo "$1 is accessable" || echo "$1 is not accessable"
}# 主函數:處理參數,調用檢測函數
function main () {[ $# -ne 1 ] && usage  # 如果參數數量不是1,調用usage函數提示用法check_url $1  # 調用檢測函數,傳入URL參數
}# 執行主函數,$*表示所有參數(傳給main函數)
main $*# 測試1:檢測有效URL(百度)
[bq@shell ~]$ bash check_url.sh www.baidu.com
www.baidu.com is accessable  # 可訪問# 測試2:檢測無效URL(不存在的域名)
[bq@shell ~]$ bash check_url.sh www.bq.com
www.bq.com is not accessable  # 不可訪問# 測試3:參數錯誤(不傳參數)
[bq@shell ~]$ bash check_url.sh 
usage: check_url.sh url  # 調用usage函數提示用法

實戰價值:可批量檢測網站可用性,結合定時任務(crontab)實現自動監控。

函數的遞歸調用(函數調用自身)

遞歸是指函數自己調用自己,適用于有明確終止條件的問題(如求和、階乘)。

示例 1:遞歸求 1+2+…+n 的和

實驗流程

  1. 定義 sum_out 函數:如果 n=1,返回 1;否則返回 n + sum_out(n-1)(自身調用)。
  2. 腳本接收用戶輸入的整數 n,調用函數計算和并輸出。
  3. 測試輸入 10(預期結果 55),驗證正確性。

詳細步驟

# 編寫求和腳本sum.sh
[bq@shell ~]$ cat sum.sh 
#!/bin/bash
# 遞歸求和函數:計算1+2+...+$1的和
function sum_out() {# 終止條件:當參數為1時,和為1if [ $1 -eq 1 ];thensum=1else# 遞歸調用:n的和 = n + (n-1)的和(通過$(sum_out $[ $1 - 1 ])獲取n-1的和)sum=$[ $1 + $(sum_out $[ $1 - 1 ]) ]fiecho $sum  # 輸出計算結果
}
# 讀取用戶輸入的整數
read -p "輸入一個你想計算和的整數:" num
# 調用遞歸函數,傳入用戶輸入的數字
sum_out $num# 測試:輸入10(1+2+...+10=55)
[bq@shell ~]$ bash sum.sh 
輸入一個你想計算和的整數:10
55  # 結果正確
示例 2:遞歸求 n 的階乘(12…*n)

實驗流程

  1. 定義 fact_out 函數:如果 n=1,返回 1;否則返回 n * fact_out(n-1)
  2. 腳本接收用戶輸入的整數 n,調用函數計算階乘并輸出。
  3. 測試輸入 10(預期結果 3628800),驗證正確性。

詳細步驟

# 編寫階乘腳本fact.sh
[bq@shell ~]$ cat fact.sh 
#!/bin/bash
# 遞歸階乘函數:計算1*2*...*$1的積
function fact_out() {# 終止條件:當參數為1時,階乘為1if [ $1 -eq 1 ];thensum=1else# 遞歸調用:n的階乘 = n * (n-1)的階乘sum=$[ $1 * $(fact_out $[ $1 - 1 ]) ]fiecho $sum  # 輸出計算結果
}
# 讀取用戶輸入的整數
read -p "輸入一個你想計算階乘的整數:" num
# 調用遞歸函數,傳入用戶輸入的數字
fact_out $num# 測試:輸入10(10! = 3628800)
[bq@shell ~]$ bash fact.sh 
輸入一個你想計算階乘的整數:10
3628800  # 結果正確
示例 3:fork 炸彈(危險!僅作原理了解)

fork 炸彈是一種通過遞歸創建大量進程耗盡系統資源的惡意代碼,原理是函數不斷自我復制并后臺運行。

代碼解析

:(){ :|:& };:  # fork炸彈核心代碼

逐部分解釋:

  • :():定義一個函數,函數名是 :(冒號)。

  • { :|:& }
    

    :函數體內容:

    • ::調用函數自身(遞歸)。
    • |:管道符,將左邊的輸出作為右邊的輸入,同時觸發兩次函數調用。
    • &:將進程放入后臺運行,允許同時創建更多子進程。
  • ;:結束函數定義。

  • ::調用函數,觸發 “爆炸”。

危害:函數會無限制創建子進程,很快耗盡 CPU、內存等資源,導致系統卡死。

防御措施:限制用戶可創建的最大進程數(臨時生效):

# 限制當前用戶最多創建100個進程(ulimit -u 限制用戶最大進程數)
[bq@shell ~]$ ulimit -u 100

警告:切勿在生產環境中執行 fork 炸彈代碼!

總結

Shell 函數通過 “封裝重復代碼” 提升了腳本的簡潔性和可維護性,掌握函數的定義、參數傳遞、遞歸調用等技巧,能大幅提高 Shell 腳本開發效率。實際使用中,建議將通用函數整理到單獨的文件中,通過 source 加載復用,形成自己的 “函數庫”。

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

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

相關文章

微信小程序設計的請求封裝方案(request.js)

以下是為微信小程序設計的請求封裝方案&#xff0c;包含代碼示例和最佳實踐建議&#xff1a; 基礎請求封裝&#xff08;request.js&#xff09; // 基礎配置 const BASE_URL https://api.yourdomain.com; const TIMEOUT 10000;// 請求封裝函數 const request (options) >…

【Linux系統】進程信號:信號的處理

上一篇文章在介紹完信號的產生和保存后&#xff0c;我們現在對信號有了一個基本的認識&#xff0c;信號由鍵盤、系統調用、硬件異常、軟件條件等方式產生&#xff0c;然后被保存在三張表中&#xff0c;再將信號遞達&#xff0c;操作系統有三種處理方式&#xff1a;默認處理、忽…

權限管理模塊

登錄相關權限管理模塊(基礎版)模塊設計與實現優化點&#xff1a;前后端用戶驗證實現方式常見的攻擊手段及防御手段權限管理模塊(基礎版) RBAC(Role-Base Access Control&#xff0c;基于角色的訪問控制)&#xff1a;是權限管理的常用方案。 核心&#xff1a;通過用戶 - 角色 -…

征服與守護:從拉里·埃里森看八號人格的職場王者之道

真正的強者&#xff0c;從不遵守別人的規則2010年&#xff0c;加利福尼亞州的圣何塞機場迎來了一架不速之客——一架意大利產的馬基戰斗機以一種極其霸道的姿態降落在跑道上。艙蓋打開&#xff0c;走下來的不是空軍飛行員&#xff0c;而是一位身穿飛行員服、戴著墨鏡的企業家&a…

【Linux系統】命名管道與共享內存

前言&#xff1a; 上文我們講到了匿名管道【Linux系統】匿名管道以及進程池的簡單實現-CSDN博客 本文我們來講一講命名管道與共享內存 命名管道 上面我們講到&#xff0c;匿名管道只能用于有血緣關系&#xff08;尤其父子&#xff09;的進程進行通信&#xff01;但如果…

搜索體驗優化:ABP vNext 的查詢改寫(Query Rewrite)與同義詞治理

&#x1f50e; 搜索體驗優化&#xff1a;ABP vNext 的查詢改寫&#xff08;Query Rewrite&#xff09;與同義詞治理 &#x1f4da; 目錄&#x1f50e; 搜索體驗優化&#xff1a;ABP vNext 的查詢改寫&#xff08;Query Rewrite&#xff09;與同義詞治理1. 背景與問題界定 &…

Text2API與Text2SQL深度對比:自然語言驅動的數據交互革命

在數字化浪潮中&#xff0c;如何讓人機交互更加自然流暢&#xff1f;Text2API與Text2SQL技術應運而生&#xff0c;它們如同魔法般將自然語言轉化為機器可執行的指令&#xff0c;讓數據交互不再高不可攀。本文將深入剖析這兩項技術的原理、優劣勢及應用場景&#xff0c;帶您領略…

數據可視化與分析平臺設計與實現案例

數據可視化與分析平臺設計與實現案例(python) 下面分享一個完整的 Flask 數據可視化與分析平臺代碼,包含所有必要的組件和功能。這個平臺允許用戶上傳數據文件、進行基本的數據清洗、生成各種可視化圖表以及查看基礎統計分析結果。 產品設計 核心功能 數據上傳與管理(支…

Kotlin-基礎語法練習二

接上一篇博客 每個 Kotlin 程序都是由兩種部分組成的&#xff1a; 1、表達式&#xff08;Expressions&#xff09;&#xff1a;用于計算值的部分&#xff0c;比如 2 3、函數調用、變量賦值等&#xff0c;它們通常會返回一個結果。2、語句&#xff08;Statements&#xff09;…

與Deepseek對話了解單片機基礎知識

keil5里的c語言編程的程序燒錄到單片機里具體過程是啥&#xff1f;如何能把機器語言轉換為電路控制&#xff1f; 步驟 所在位置 核心工具 輸入->輸出 比喻 1. 編譯 Keil5 (PC) 編譯…

利用背景圖片定位套打檔案封面

某些表單設計起來比較復雜&#xff0c;或只有表單的空白圖片資料。Nhdeep檔案目錄套打工具&#xff08;nhdeep官網www.nhdeep.com&#xff09;支持將已有的表單圖片作為模版背景圖片&#xff0c;然后使用文本框進行精準的位置定位&#xff0c;再進行文本替換。 背景圖片定位套…

微信HOOK 實現自動下載視頻

1、前言 在收發消息的接口中&#xff0c;圖片和文件這類接口是相對容易自動下載&#xff0c;但是視頻的下載是需要手動點擊的&#xff0c;并且只有這一種下載方式&#xff0c;實現自動化也比較困難&#xff0c;一些項目的開發中&#xff0c;需要自動下載收到的視頻并保存&#…

【GPT入門】第57課 詳解 LLamaFactory 與 XTuner 實現大模型多卡分布式訓練的方案與實踐

【GPT入門】第57課 大模型多卡計算1. 理論2.LLamaFacotory實踐3. xtuner3.1 介紹3.1 安裝3.2 xtuner訓練3.4 訓練后格式轉換3.5 合并基礎模型與lora模型3.6 參數說明3.7 訓練過程主觀檢驗1. 理論 deepspeed的三種訓練方式 zero-1&#xff0c;優化器狀態分片。的優勢體現在多卡…

部隊多媒體信息發布系統:賦能 IPTV 與電教化,加速軍營信息化變革

在科技飛速發展的當下&#xff0c;部隊的信息化建設也在不斷推進。多媒體信息發布系統作為一種創新的技術手段&#xff0c;正逐步融入部隊的各個領域&#xff0c;為部隊的現代化建設注入強大動力。?在部隊 IPTV 方面&#xff0c;多媒體信息發布系統展現出卓越的性能。它打破了…

FTP/TCP上傳下載文件

封裝C風格地ftplib為ftp.c和ftp.h文件&#xff1a;cftplient類&#xff08;主要成員變量&#xff1a;文件大小、文件修改時間、主要成員函數&#xff1a;get函數&#xff08;遠程文件名、本地文件名、核對文件時間&#xff09;、put函數&#xff08;本地文件名、服務端文件名、…

DeepSeek V3.1深度解析:一個模型兩種思維,邁向Agent時代的第一步!

名人說&#xff1a;博觀而約取&#xff0c;厚積而薄發。——蘇軾《稼說送張琥》 創作者&#xff1a;Code_流蘇(CSDN)&#xff08;一個喜歡古詩詞和編程的Coder&#x1f60a;&#xff09; 目錄一、什么是DeepSeek V3.1&#xff1f;為什么這么火&#x1f680;1. 發布時間線回顧2.…

VsCode 便攜版(綠色版)下載及配置

下載 VsCode 便攜版&#xff0c;并確保所有配置和擴展都保存在一起&#xff0c;實現真正的“綠色版”效果 核心步驟概覽 核心原理是在 VSCode 的主程序目錄下創建一個名為 data 的文件夾&#xff0c;VSCode 啟動時如果檢測到這個文件夾&#xff0c;就會自動切換到便攜模式&am…

使用VLLM部署大模型embedding/chat 的API

模型下載&#xff1a;一般通過modelscope提供的方式進行下載&#xff0c;速度更快&#xff0c;huggingface下模型即便開啟了魔法也還是很慢&#xff0c;對于9B以上的模型都是至少15G的。 比如需要下載qwen3-embedding-8b的模型&#xff0c;可以通過提供的一段代碼自動進行下載到…

Blender模型動畫導入到UE5

UE5支持直接導入FBX文件&#xff0c;但在實際應用中筆者發現&#xff1a;剛開始使用的是UE5.3&#xff0c;在UE5.3中直接將.fbx文件拖入UE中導入后是一個個的零件&#xff0c;后來使用了datasmith插件等其他辦法&#xff0c;怎么都沒有達到想要的效果。后面升級UE5.4以后&#…