前言
? ? ? ?當我們在終端輸入 ls -l /home 查看目錄詳情,或用 gcc -o hello hello.c 編譯代碼時,或許很少思考:這些空格分隔的 “指令 + 選項 + 路徑” 是如何被程序識別的?為什么 PATH 變量能讓系統找到可執行文件,而 HOME 變量總能指向用戶主目錄?命令行參數與環境變量,作為用戶與程序、程序與系統之間溝通的 “橋梁”,是理解程序運行機制的基礎。
? ? ? ? 本文將從最直觀的使用場景出發,帶你系統梳理這兩大核心概念:先解析命令行參數的結構 —— 以 ls -l、gcc -o 等經典命令為例,講清參數的傳遞邏輯與程序如何接收處理;再深入環境變量的世界,從查看方法(如 echo $PATH)、核心命令(如 export、env),到其 “全局屬性” 的本質,最后通過代碼實例演示如何在程序中獲取環境變量(無論是借助 environ 變量還是系統調用)。
? ? ? ?無論你是剛接觸終端的初學者,還是想搞懂程序啟動時參數與環境如何傳遞的開發者,這篇文章都將幫你打通從 “會用” 到 “理解原理” 的鏈路,讓每一次命令輸入都知其然更知其所以然。
目錄
基本概念
命令行參數
🧱 命令行參數結構
? 示例講解
1. ls -l /home
2. gcc -o hello hello.c
3. rm -rf myfolder/
🔍 如何查看命令的可用參數?
常見環境變量
查看環境變量方法
和環境變量相關的命令
環境變量的組織方式
環境變量獲取方式
通過代碼獲取環境變量
通過第三方變量environ獲取
通過系統調用獲取環境變量
環境變量通常是具有全局屬性的
基本概念
1.環境變量(environment variables)一般是指在操作系統中用來指定操作系統運行環境的一些參數。
例如:我們在編寫C/C++代碼的時候,在鏈接的時候,從來不知道我們的所鏈接的動態靜態庫在哪
里,但是照樣可以鏈接成功,生成可執行程序,原因就是有相關環境變量幫助編譯器進行查找。
2.環境變量通常具有某些特殊用途,還有在系統當中通常具有全局特性。
命令行參數
讓一個程序可以通過選項實現不同的子功能。
main函數的命令行參數,是實現程序不同子功能的方法!!!!———指令選項的實現原理。
main有參數嗎,實際上是有的。
?#include <stdio.h> int main(int argc,char*argv[]){for(int i=0;i<argc;i++){printf("argc[%d]:%s\n",i,argv[i]); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }return 0;}
上述結果bash會把我們的命令拆分成五個部分 ./code 1 2 3 4 ,放到一個argv表中,用來支持選項功能。
在 Linux 中,命令行參數是在終端中運行一個命令時,傳遞給該命令的附加信息。命令行參數通常用于:
-
指定行為(例如:
-l
表示長格式) -
提供文件名或路徑
-
設置選項或標志
🧱 命令行參數結構
?command [options] [arguments]
-
command
:要執行的命令 -
options
(或 flags):修改命令行為,通常以-
或--
開頭,如-l
或--help
-
arguments
:傳遞給命令的數據,比如文件名、路徑等
? 示例講解
1. ls -l /home
-
ls
:列出文件/目錄 -
-l
:使用長格式輸出 -
/home
:指定目錄
輸出:以詳細列表方式顯示 /home
目錄的內容。
2. gcc -o hello hello.c
-
gcc
:GNU C 編譯器 -
-o hello
:輸出文件名為hello
-
hello.c
:輸入的源代碼文件
3. rm -rf myfolder/
-
rm
:刪除文件或目錄 -
-r
:遞歸刪除(包括子目錄) -
-f
:強制刪除(不提示) -
myfolder/
:要刪除的目錄
🔍 如何查看命令的可用參數?
使用 --help
或查看手冊頁:
?command --helpman command
例如:
?ls --helpman rm
常見環境變量
? PATH : 指定命令的搜索路徑
? HOME : 指定用戶的主功能工作目錄(即用戶登陸到Linux系統中時,默認的目錄)
? SHELL : 當前Shell,它的值通常是/bin/bash。
我們要執行一個程序時,首先要找到它的位置,誰找呢?bash來找,通過環境變量來找,系統中存在環境變量,來幫助找到目標二進制文件。
bash會拿到兩張表,一張環境變量表,一張命令行參數表,一起使用。
查看環境變量方法
echo $NAME //NAME:你的環境變量名稱
測試PATH
-
創建hello.c?件
?#include <stdio.h>?int main() {printf("hello world!\n");return 0;}
2.對比
./hello
和hello
執行
-
為什么有些命令可以直接執行,而自己的程序需要帶路徑?
Linux 執行命令時,不會自動在當前目錄查找命令,而是按順序在 PATH
環境變量中定義的目錄里查找。
你可以查看當前的 PATH:
?echo $PATH
輸出類似:
?/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
所以:
-
比如
ls
位于/bin/ls
,由于/bin
在 PATH 中,ls
可以直接運行。 -
而當前目錄
./
不在 PATH 中,所以你的hello
無法直接運行。
-
將當前目錄加入 PATH
例如你當前在 /home/user/test/
目錄下,執行:
?export PATH=$PATH:/home/user/test/
現在再執行:
?hello
? 可以成功運行了!
🔒 注意:這只在當前終端會話中生效,重啟后失效。
2.除了 export PATH,還有哪些辦法讓程序能直接執行?
方法一:移動程序到系統路徑中
將 hello
拷貝到 /usr/local/bin/
或 /usr/bin/
:
?sudo cp hello /usr/local/bin/
然后就可以在任何地方直接運行:
?hello
方法二:在 ~/.bashrc
或 ~/.profile
添加路徑
讓設置永久生效:
?echo 'export PATH=$PATH:/home/user/test/' >> ~/.bashrcsource ~/.bashrc
小結
方法 | 是否需要每次設置 | 是否影響所有用戶 |
---|---|---|
export PATH=... | ? 臨時有效 | 否 |
修改 ~/.bashrc | ? 永久有效(當前用戶) | 否 |
拷貝到 /usr/local/bin | ? 永久有效 | 是(需要 root) |
和環境變量相關的命令
-
echo: 顯示某個環境變量值
-
export: 設置一個新的環境變量
-
env: 顯示所有環境變量
-
unset: 清除環境變量
-
set: 顯示本地定義的shell變量和環境變量
環境變量的組織方式
環境變量獲取方式
通過代碼獲取環境變量
main參數
參數名 | 類型 | 含義 |
---|---|---|
argc | int | 命令行參數數量 |
argv | char* argv[] | 命令行參數字符串數組 |
envp | char* envp[] | 環境變量字符串數組 |
main函數命令行第三個參數
?#include <stdio.h>int main(int argc, char *argv[], char *env[]){int i = 0;for(; env[i]; i++){printf("%s\n", env[i]);}return 0;}
通過第三方變量environ獲取
?#include <stdio.h>int main(int argc, char *argv[]){extern char **environ;int i = 0;for(; environ[i]; i++){printf("%s\n", environ[i]);}return 0;}
libc中定義的全局變量environ指向環境變量表,environ沒有包含在任何頭文件中,所以在使用時要用extern聲明。
通過系統調用獲取環境變量
?#include <stdio.h>#include <stdlib.h>int main(){printf("%s\n", getenv("PATH"));return 0;}
常?getenv函數來訪問特定的環境變量。
環境變量通常是具有全局屬性的
? 環境變量通常具有全局屬性,可以被子進程繼承下去
?#include <stdio.h>#include <stdlib.h>int main(){char *env = getenv("MYENV");if(env){printf("%s\n", env);}return 0;}
當我們直接運行程序什么都沒有輸出,說明該環境變量不存在。只進行 MYENV=“helloworld” ,不調用export導出,也不會有結果。
MYENV
只是 shell 的一個局部變量,不在環境表中。
getenv("MYENV")
無法讀取這個變量,所以程序無輸出。
當export導出環境變量時,放在bash中重新運行就有結果了。
環境變量被加入父 shell 的環境中,因此子進程(你運行的 ./code
)能夠繼承并讀取
?
結束語
? ? ? ? 命令行參數與環境變量,看似是終端操作中最基礎的部分,實則是程序與系統交互的 “底層協議”。命令行參數讓程序得以根據用戶輸入動態調整行為(如 rm -rf 的強制刪除選項),環境變量則為程序提供了全局可見的 “配置上下文”(如 PATH 指引執行路徑、LANG 控制語言環境)。
? ? ? ? 理解它們的結構與原理,不僅能讓你更熟練地使用命令(比如知道如何通過 man 查看參數說明),更能幫你在編程時設計更靈活的程序 —— 無論是讓腳本接收用戶輸入參數,還是在代碼中讀取系統環境變量,這些知識都是必備的基礎。
? ? ? ? 值得注意的是,環境變量的 “全局屬性” 也提醒我們:敏感信息不應隨意存入環境變量,而命令行參數的可見性則要求避免在參數中傳遞密碼等隱私數據。
? ? ? ? 希望本文能讓你對命令行參數與環境變量的認知從 “模糊的工具” 變成 “清晰的邏輯鏈”。下次在終端輸入命令時,不妨多留意參數的含義與環境變量的作用 —— 你會發現,終端交互的每一個細節都藏著系統設計的巧思。如果有相關的實踐問題或心得,歡迎在評論區交流~