零
总结之前学习的所有Linux操作系统知识点
知识点有点杂乱,但花了好长时间
Unix
Unix-->原版正版的"经典配方"
Linux-->按照配方复刻并优化的"开源版本",配方一致
Unix的设计思想 用最简单的规则解决最复杂的问题
类Unix
类Unix(Unix-like)是一个统称,指遵循Unix核心设计思想,拥有和Unix一致的核心特性,用户体验高度兼容Unix的操作系统
eg : Linux macOS BSD(Berkeley Software Distribution,伯克利软件发行版)...
注意 : Windows使用的是Windows NT内核,是非类Unix操作系统
Windows && macOS && Linux
Windows的系统管理命令和Linux完全不一致,无法直接运行Linux命令,根源是内核体系,设计思想完全独立(Windows是NT内核,macOS是类Unix内核)
Linux命令能直接用在macOS上,因为二者都属于类Unix系统 ,均遵循POSIX标准,内核设计思想/终端命令规范/系统调用逻辑高度一致
总之 :
macOS和Linux : 类Unix内核体系-->遵循POSIX标准--->命令通用
Windows和Linux : Windows是NT内核体系(非类Unix),Linux是类Unix--->不遵循POSIX标准--->命令不通用
(Windows NT简称NT[new techology],Windows的内核是Windows NT内核体系)
解释一个Linux名字的混淆
Linux操作系统的全名是GNU/Linux,Linux指的是Linux操作系统的内核
日常所说的Linux其实是 : GNU软件生态+Linux内核的完整组合体
- 内核(Kernel) : 操作系统的核心底层程序,是硬件的软件之间的桥梁
- 完整操作系统 : 以内核为核心,搭配上层软件/工具/生态的完整软件合集
Linux完整操作系统组成 ; 内核 +命令解释器 +基础命令工具 +系统库 +配置工具 +应用支持+...
Shell
Shell(常见的是bash zsh fish...)就是一个命令行解释器,用户和操作系统内核之间的桥梁
macOS中的zsh,bash 和 Linux中的zsh,bash在核心使用上基本一致,底层语法,命令执行逻辑,功能特性一致
CMD/PowerShell/WSL/Git Bash/Windows Terminal
- CMD : Windows原生传统命令行工具
- PowerShell : CMD的升级版
- WSL(Windows System for Linux,Windows系统for Linux) : 能够运行几乎所有的Linux命令,有WSL1版本和WSL2版本
- WSL1 : 在Windows内核上做了一层Linux系统调用层
- WSL2 : 轻量级的虚拟机运行完整的Linux内核
- Git Bash : 安装Git for Windows时附带的轻量级的bash Shell环境
- Windows Terminal : 终端,支持多种命令行工具
date命令
bash
date
# 输出 : Wed Feb 4 17:43:20 CST 2026
# CST(Chinese Standard Time)
# 自定义date输出格式
# 年
%Y 4位完整年份
%y 2位完整年份
# 月
%m 2位月
# 日
%d 2位日
# 时分秒
%H 24小时制小时
%M 分钟
%S 秒
%F 日期简写(%Y-%m-%d) eg : 2006-02-04
%T 时间简写(%H:%M:%S) eg : 16:50:30
bash
eg :
echo "欢迎登录服务器,档期那时间$(date +%Y-%m-%d\ %H:%M:%S)"
echo "欢迎登录服务器,档期那时间$(date +'%Y-%m-%d %H:%M:%S')"
date +"%s" # 输出从1970年到现在一共多少秒
bash
# 解析常规日期字符串,输出标准格式
# -d(date)
date -d "2026-02-05" +"%y-%m-%d %H:%M:%S"
date -d "-1 day" +"%y-%m-%d %H:%M:%S"
date -d "+1 week" +"%y-%m-%d %H:%M:%S"
bash
# 设置系统时间
sudo date -s "时间字符串" # -s(set)
bash
# 秒级时间戳
# 获取当前秒级时间戳
date +%s
date -d @1749332430 +"%Y-%m-%d %H:%M:%S" # 把秒转化为日期时间
$( )命令替换符号
$( )是Linux中的标准命令替换符号,核心作用是 : 把命令的执行结果 转换为普通字符串
Linux中的基础语法
定义普通变量&&调用
bash
# 定义
NAME='lixiang'
PATH_CUDA='/usr/local/cuda/bin'
# 调用
echo "我的名字 : $NAME"
echo "CUDA路径是 : ${PATH_CUDA}/nvcc" # 使用{ }边界区分
定义环境变量
bash
# 定义+导出(一步到位)
export JAVA_HOME=/usr/local/jdk
export PATH=$JAVA_HOME/bin:$PATH
# 先定义,再导出
LD_LIBRARY_PATH=/usr/local/cuda/lib64
export LD_LIBRARY_PATH
系统内置变量
bash
USER 当前登录用户
HOSTNAME 服务器主机名
PWD 当前工作目录
PATH 命令查找路径
?上一条命令的执行结果(0=成功,非0=失败)
变量删除
bash
# 删除已经定义的变量/环境变量
unset NAME # 删除普通变量
unset JAVA_HOME # 删除环境变量
if else语句
bash
if [ 判断条件]; then
执行命令
elif [ 判断条件]; then
执行命令
elif [ 判断条件]; then
执行命令
else
执行命令
fi
- 数值比较
-eq (equal)等于
-ne (not equal)不等于
-gt (greater than)大于
-lt (lower than)小于
-ge (greater equal)大于等于
-le (lower equal)小于等于
bash
if [$? -eq 0]; then
echo "命令执行成功"
fi
- 文件/目录判断
-f (file)是文件
-d (directory)是目录
-e (exit)存在
-s (size)是非空
bash
if [-d ~/dir01]; then # 判断dir01是否为目录
echo "工作目录存在,进入目录"
cd ~/dir01
fi
- 简单数值计算
bash
a=2
b=10
echo "和 : $((a+b))"
echo "余 : $((a%b))"
- 字符串比较
= 等于
!= 不等于
-z (zero length)字符串为空
for循环
bash
# 批量创建3个文件
for i in 01 02 03; do
touch file$i.txt
done
# 遍历当前目录下的所有.sh脚本,赋予执行权限
for sh in *.sh; do
chmod +x $sh
done
通配符
bash
# eg :
ls *.sh # 查看所有.sh脚本
rm -r -f temp* # 删除所有以temp开头的文件/目录
cp file[0-3].txt ~/dir01/ # 复制file0-file3的文件到~/dir01/目录
别名alias
Shell处理命令时,先找到真正命令名,再找可执行文件位置
bash
# 定义别名
alias ll='ls -lh --color=auto'
alias la='ls -alh --color=auto'
# 取消别名
unalias ll
( ) { } [ ]
bash
# $() 命令替换语法,将()中执行的内容转换为字符串
echo "欢迎使用,当前时间$(date +"%Y-%m-%d %H:%M:%S")"
# ${} 界定变量名的边界,避免歧义
NAME="lixiang"
echo "${NAME}_hello world"
# () 子Shell执行(就是单独开一个Shell,圈起来自己玩,哈哈)
(cd ~/dir01 && ls -l -a) # 子进程Shell中切换目录+查看,执行完回到原Shell
(TEST="子Shell变量"; echo $TEST) # 输出 : 子进程
echo $TEST # 无输出,因为当前进程为定义TEST变量
# [] 条件判断
if [-d ~/dir01 ]; then
echo "目录存在"
fi
常用的位置参数
bash
$0 # 执行脚本/命令本身名称
$1~$n # 第1~n个参数
$# # 所有参数的总个数
$* # 所有传入的参数(整体一个字符串)
$@ # 所有传入的参数(逐个独立的字符串)
$? # 上条命令的执行结果(0是成功,非0是失败)
$$ # 当前脚本的执行ID(PID)
visudo
Ubuntu主流版本默认预装vim和nano两款文本编辑器,但是没有校验语法功能
visudo不是编辑器,是专门为/etc/sudoers设计的安全编辑命令.会自动调用系统默认终端编辑器 ,在编辑保存时校验语法
$ : 将命令/程序放在后台执行
Shell中执行命令的默认方式是前台执行,命令执行期间,终端会被占用,无法输入其他命令,只能等待命令执行完毕
在命令末尾加&,会将命令切换到后台执行,不占用当前终端
bash
eg :
命令 > 日志文件.log 2>$1 $
# 将命令的正确输出保存到指定的日志文件
# 将命令的错误文件重定向到同一个日志文件
# 最终实现 : 后台执行的所有输出/报错都存入日志文件,终端保持干净无干扰
后台进程的核心管理命令
将命令放在后台后,需要掌握简单的管理命令,用于查看后台进程,将后台进程调回前台,终止后台进程
jobs
查看当前终端的后台进程列表
bash
jobs
# 典型输出
[1]+ Running Python train.py --epoch 200 > train.log 2>$1 $
fg
fg(foreground) 将后台进程调回前台执行
bash
fg %1
# 将编号为1的后台进程调回前台
# 调回后终端再次被占用,进程执行完成后恢复,也可以Ctrl+Z暂停进程
bg
bg(background) 将暂停的后台进程恢复为后台运行
bash
bg %1
# 若进程被Ctrl+Z暂停,用bg恢复为后台运行,继续执行
# 恢复百年好为1的暂停进程为后台运行
kill
bash
kill %1 # 终止后台进程
kill -9 %1 # 强制终止后台进程
Linux内核的相关信息
| 类Unix操作系统 | 内核体系 | uname的输出 | uname -o的输出 |
|---|---|---|---|
| Linux(Ubuntu/CentOS/WSL2) | Linux内核 | Linux | GNU/Linux |
| macOS/iOS | Darwin内核 | Darwin | Darwin |
| FreeBSD | FreeBSD内核 | FreeBSD | FreeBSD |
| OpenBSD | OpenBSD内核 | OpenBSD | OpenBSD |
注意 : Windows是WindwosNT内核,是非类Unix操作系统
Kernel Name内核名字
Linux输出 : Linux
macOS输出 : Darwin
FreeBSD输出 : FreeBSD
类Unix按照系统的内核不同可以分为Linux,macOS,FreeBSD...
Kernel Release内核发行版
Linux内核的具体版本标识(包含主版本,次版本,修订版,及定制厂商专属后缀)格式为"主版本.次版本.修订版-定制后缀"
Machine Architecture硬件架构
当前系统运行的CPU架构/处理器架构,内核为该架构做了专属适配
目前主流的架构由 x86_64(amd64),aarch64(arm64)
Operating System操作系统名字
当前内核对应的通用操作系统类型
Linux内核输出 : GNU/Linux(这个才是Linux操作系统的全称)
系统发行版本 VS 内核发行版本
系统发行版本 是基于内核封装的完整电脑系统,由发行商维护
内核发行版本 是这个系统的核心发动机版本,由Linux内核社区维护
eg :
针对WSL2-Ubuntu20.04
系统发行版本 : Ubuntu 20.04
内核发行版版本 : 6.6.87.2-microsoft-standard-WSL2
微软使用自己定制的"发动机",装在了Ubuntu社区的"车身"上,组成了你的WSL2的完整系统
查看系统发行版
cat /etc/os-release
查看内核发行版
uname --kernel-release
uname命令
查询当前运行的类Unix系统(Linux,macOS,BSD,WSL)的系统内核,硬件架构等核心标识信息,是类Unix系统中查询操作系统基础信息的基础命令
bash
# 获取操作系统的 内核相关信息 硬件架构信息...
uname # 默认显示内核信息
uname --kernel-name # 显示内核命令(相当于uname)
uname -r(--kernel-release) # 输出内核发行版本号
uname -m(--machine) # 输出硬件架构
uname -o(--operating-system) # 输出操作系统完整名称
uname -a(--all) # 输出所有信息
uname -n(--nodename) # 输出主机名
uname -v(version) # 输出内核编译版本/时间
root权限 && root用户
超级用户管理员
root用户有最高root权限
怎么给普通用户授予root权限
临时提权
给普通用户添加sudo权限,用户执行需要root权限的命令时,在命令前加sudo,输入自身密码即可临时获取root权限
bash
usermod -aG sudo 普通用户名
永久免密提权
bash
# 先将普通用户加入sudo组
# 再编辑sudo配置文件/etc/sudoers (visudo)
visudo /etc/sudoers
# 给单个普通用户免密
普通用户名 ALL=(ALL) NOPASSWD: ALL
# 或者给整个sudo组免密(实现组内用户都免密)
%sudo ALL=(ALL) NOPASSWD: ALL
当前用户默认Shell
每一个用户都有一个默认Shell,系统记录在/etc/passwd中,可以通过echo $SHELL快速查看
默认Shell的作用 : 用户登录/打开终端时,系统会自动启动该Shell,后续终端命令都通过它执行
~/.zshrc
每一个用户在家目录都有一个.Shell名rc命名的用户级配置文件,是Shell启动时的核心初始化文件(是隐藏文件)
eg : lixiang我的默认Shell是zsh,在家用户目录有.zshrc文件,这个是/.zshrc的用户级核心配置文件
eg : lixiang的默认Shell是bash时,家目录有一个.bashrc的文件,这个文件是bash的用户级配置文件
作用 : 是当前用户专属的Zsh启动配置文件----每次打开新的zsh终端,zsh都会自动加载并执行这个文件的所有命令
用户登录时的操作
系统级配置 && 用户级配置
| Shell的配置文件 | 文件配置路径 | 加载场景 | 核心作用 |
|---|---|---|---|
| 系统级登录配置文件 | /etc/.profile | 所有登录时 | CUDA/Anaconda 等全局程序路径、系统级环境变量 |
| 用户级登录配置文件 | ~ /.{Shell名}profile,若没有会使用 ~ /.profile替代 | 仅当前用户登录时 | 所有登录级配置,补充/覆盖系统级登录配置 |
| 用户级个性化配置文件 | ~/.{Shell名}rc | 启动/登录时 | 用户个性化配置,定义该Shell专属行为 |
- 系统级登录配置 文件 : 存放在/etc/目录下,对所有用户 生效,是系统的全局默认配置(eg : /etc/profile)
- 用户级配置 文件 : 存放在家目录下,仅对当前用户
分为两类 :
---用户登录配置 文件 : ~/zprofile(zsh专属,若未创建会自动使用 ~/.profile替代)
---用户个性化配置文件 : ~/.zshrc(登录/非耕录Shell都会启动执行,存放所有个性化设置)
系统级登录配置的案例
系统级配置是登录任意用户都会执行的配置文件--->所有用户通用,全局生效
bash
# 在/etc/profile末尾添加内容,所有用户登录后都能直接使用
# 1.全局环境变量,所有用户都能识别JAVA_HOME
export JAVA_HOME=/usr/local/jdk1.8
export PATH=$JAVA_HOME/bin:$PATH
# 2.全局命令别名,所有用户都能通过ll替代ls -l
alias ll='ls -l --color=auto'
alias la='ls -a --color=auto'
# 3.全局登录登录提示,所有用户打开终端打印一句话
echo "欢迎登录XX服务器,当前时间 : $(date)"
# 总之 :
# 不管是root登录,还是普通用户登录,都能直接执行这些命令
用户级登录配置案例
只有登录当前用户时,才执行登录配置文件
登录配置(~/.zprofile或 ~/.profile),仅当前用户,仅登录时执行一次
bash
# 1.个人专属环境变量
export CUDA_HOME=/usr/local/cuda-12.1
export PATH=$CUDA_HOME/bin:$PATH
# 2.登录专属脚本,仅root登录时,自动检查服务器磁盘使用率
df -h | grep /dev/vda1
# 3.核心联动,必须写,登录时加载个性化配置文件
source ~/.zshrc
用户级个性化配置案例
仅对当前用户,登录/非登录启动zsh都生效
bash
# 1.个人专属别名,仅该用户能用
alias jdir01='cd ~/dir01'
alias sshnode='ssh root@192.168.1.101'
alias pyt='python ~/review'
# 2. zsh插件配置(oh-my-zsh):仅root用的插件
plugins=(git conda autojump syntax-highlighting history-substring-search)
# 3. 自定义zsh提示符:显示用户名、主机名、当前路径、Git分支(算法工程师常用)
PS1='%F{green}%n@%m%f:%F{blue}%~%f %F{yellow}$(git branch 2>/dev/null | grep "*" | cut -d " " -f2)%f %# '
# 4. 历史命令优化:仅root保存10000条历史命令,支持忽略重复命令
HISTSIZE=10000
SAVEHIST=10000
setopt HIST_IGNORE_DUPS
系统级登录配置文件加载顺序(用户登录Shell时,全局生效)
系统启动加载 /etc/environment → 用户登录启动登录Shell → 加载 /etc/profile → /etc/profile 自动执行 /etc/profile.d/ 下所有.sh脚本 → 加载用户级登录配置~/.profile
(后续再加载用户默认个性化配置~/.zshrc)
前置知识
以zsh为例
- 登录Shell标识 : zsh登录模式启动后,执行echo $0会输出-zsh(前缀-是登录Shell的标识,非登录Shell会直接输出zsh)
- 配置文件分配 : 所有zsh配置文件分为系统级 (全局默认)和用户级(个性化定制),执行优先级 : 系统级--->用户级(用户级配置文件会覆盖系统级同名配置)
- 核心配置文件 : zsh登录流程的核心文件为 ~ /.zprofile和 ~ /.zshrc
完整登录流程
- 输入账号密码,验证登录(查/etc)
- 启动zsh进程,读取默认Shell和家目录(/etc/passwd)
- 先加载系统全局配置 : /etc/profile
- 再加载用户登录配置 : ~/.zprofile
- 自动加载zsh核心个性化配置 : ~/.zshrc
- 切到家目录,输出zsh提示符,可操作
非登录,仅启动时,仅执行用户个性化配置文件 ---> .{shell名}rc文件
修改PATH环境变量
永久修改
bash
# 编辑用户级个性化配置文件
vim ~/.zshrc
# 在文件末尾添加export命令
export PATH=新目录:$PATH
# 让终端立即生效
source ~/.zshrc
(PATH环境变量中的多个目录以:分割)
临时修改(仅对当前Shell会话有效,关闭终端就失效)
export PATH=新目录 : $PATH
或者
export PATH= $PATH : 新目录
sudo命令
提权功能
只是提权,不是登录
bash
sudo -u lixiang 命令 # 以lixiang的权限命行命令
sudo 命令 # 默认以root的权限执行命令,但是要求当前使用的用户有root的提权
su命令
su(switch user,切换用户)
核心作用 : 用户登录/切换
有 -
bash
su - lixiang
# 登录lixiang这个用户
su - root
# 登录root这个用户
su -
# 默认登录root这个用户
# 执行用户登录的所有操作
无 -
bash
su lixiang # 仅是切换权限身份
# 不加载任何配置文件
# 不改变原Shell环境
# 仅仅是切换权限
# 相当于 sudo -u lixiang 命令名
bash
su # 默认切换到root权限
总之
有 - 就是登录
无 - 就是提权( 相当于sudo -u {用户名} {命令} )
source命令
在当前Shell进程内执行代码
bash
source 目标文件路径
# 相当于
. 目标文件路径
source执行 与 直接执行 的区别
- 直接执行--->系统会创建独立的子进程执行文件代码
- 直接执行--->子进程内的所有配置仅在子进程中有效,执行完成后子进程销毁,当前Shell环境无任何变化
- source执行--->在当前Shell进程内执行文件代码,执行结果直接作用于当前Shell进程,配置全局生效
变量
Linux中的变量包括 环境变量 和 本地变量(普通变量)
1.环境变量
环境变量 包括 系统级环境变量(全局环境变量) 和 用户级环境变量(用户自定义环境变量/局部变量)
环境变量 : 是全局生效的Shell变量,会被当前Shell进程及所有子进程继承和识别
环境变量都是键值对结构 : 变量名=值
1.1系统全局环境变量
常见的系统全局环境变量 :
| 系统级环境变量 | 用处 | 注意 |
|---|---|---|
| PATH | Shell执行命令时,先确认命令名字,然后在PATH记录的路径中查找环境变量的位置 | which命令查找可执行文件位置也是在PATH记录的路径中查找 |
| HOME | 记录当前用户的家目录位置 | |
| USER | 记录当前用户登录的用户名 | |
| SHELL | 当前用户的默认打开Shell | |
| UID | 当前用户的UID | |
| GID | 当前用户的主组ID | GID一般就是指主组ID,附加组ID叫附加GID |
| LANG | 系统语言/字符编码配置 | |
| HOATNAME | 记录服务器/主机名 | |
| TERM | 终端类型 | |
| PWD | 当前工作目录 | |
| OLDPWD | 上一个工作目录 (cd - 可以切回) |
1.2用户自定义环境变量
bash
export NAME="lixiang"
# NAME是用户自定义环境变量,可以被子进程继承
2.本地变量
仅在当前进程中使用,不能被子进程继承
sudo命令
sudo是Linux提权执行命令
默认以root用户身份执行后续命令
bash
sudo 命令.. # 以root身份执行命令
sudo -u 用户名 # -u(user)以指定用户的身份/权限执行命令,其他不变(使用的Shell不变,基础环境变量不变..)
sudo -u lixiang -i 命令.. # -i(--login)完全模拟目标用户的手动登录流程
#就完全等价于-->先登录lixiang用户,执行命令,再退出lixiang用户
什么是预解析
bash
lixiang的默认使用Shell是bash,root的默认使用Shell是zsh
su -u lixiang echo $SHELL
# 以lixiang的权限执行,输出zsh
su -u lixiang -i echo $SHELL
# 以lixang完整登录执行,应该输出的是bash,但是却是zsh
原因 :
# 在Linux中,当年在终端执行了包含$变量的命令时
# 当前执行命令的Shell会先扫描命令行,将所有$解析为对应的值,再将解析后的完整命令传递给后续程序,而不是传递原始的$变量
模拟执行su -u lixiang -i echo $SHELL的全过程 :
# 1.root的zsh扫描命令,发现$SHELL,立即解析为root自身的Shell路径
# 2.解析后命令变为 : sudo -u lixiang -i echo /usr/bin/zsh
# 3.sudo接收到固定字符串
# 4.登录到lixiang用户,执行echo命令,输出/usr/bin/zsh
阻止预解析的方法 :
bash
'$SHELL' #加引号
\$SHELL #加反斜杠转义$,阻止预解析
# 直接让lixiang的默认Shell(bash)执行命令
# -c(command)让bash执行引号中的命令
sudo -u lixiang -i bash -c 'echo $SHELL'
$SHELL
$SHELL : 存放的是当前用户的默认Shell
/etc/shells
/etc/shells : 记录所有已安装的,可被用户使用的Shell程序路径