Linux环境变量与shell变量实战指南:PATH、export与故障排查

📅 2026/6/22 0:43:55
Linux环境变量与shell变量实战指南:PATH、export与故障排查
1. 项目概述为什么搞懂环境变量和 shell 变量是 Linux 生存的第一课在 Linux 系统里你敲下ls能列出文件输入python3就能启动解释器执行git commit就能提交代码——这些看似理所当然的操作背后全靠一组看不见、摸不着却无处不在的“隐形指挥官”在调度。它们就是环境变量Environment Variables和シェル変数Shell Variables。这不是教科书里的概念游戏而是你每天打开终端后真实发生的底层逻辑PATH决定命令在哪找HOME告诉系统你的家在哪PS1控制你看到的命令提示符长什么样LANG影响中文能不能正常显示……漏掉一个就可能遇到“command not found”、“No such file or directory”、“乱码输出”这类高频故障。我刚带新人时有位同事折腾了三小时配不好 Node.js 全局模块路径最后发现只是PATH里少加了/usr/local/bin这一行还有人改完.bashrc死活不生效反复 source 十几次结果问题出在把export写成了export——这种细节在图形界面里根本不会暴露但一进终端就原形毕露。所以别被“变量”二字骗了它不是编程课里的抽象符号而是 Linux 系统的呼吸节奏、权限边界和行为习惯的总开关。本文不讲理论推导只聚焦实操怎么读、怎么设、怎么传、怎么查、怎么防坑。无论你是刚装好 Ubuntu 的新手还是在 WSL2 里跑 Docker 的开发者或是维护国产 Linux 发行版如统信 UOS、麒麟 Kylin的运维人员只要用终端就必须吃透这套机制。下面所有操作均在标准 Bash Shell 下验证兼容 Kali Linux、CentOS Stream、Debian、Ubuntu 及主流国产发行版无需额外安装工具。2. 核心机制拆解环境变量与 shell 变量的本质区别与协作逻辑2.1 一张图看懂变量的“血缘关系”与作用域边界很多人混淆环境变量和 shell 变量本质是没看清它们的“出生地”和“活动范围”。打个比方shell 变量是你家客厅里的遥控器只能控制本屋电视环境变量则是小区物业广播系统所有住户子进程都能听到通知。具体来说Shell 变量仅存在于当前 shell 进程内部不自动传递给任何子进程。定义方式为VARNAMEvalue无空格、无$例如mynamezhangsan。它就像临时记事本关掉这个终端窗口内容就清空。环境变量是 shell 变量的“升级版”必须通过export VARNAME或export VARNAMEvalue显式声明才能将变量“提升”为环境变量。一旦 export该变量就会写入进程的环境块environment block所有后续启动的子进程如vim、curl、python3都能继承并读取它。PATH、HOME、USER都是典型环境变量。提示export不是“赋值命令”而是“提升作用域”的动作。VARvalue是赋值export VAR是授权传播。两者可合并写为export VARvalue但逻辑上仍是两步。2.2 变量生命周期的四重门从定义到消亡的完整链路变量不是静态存在而是一条动态流水线。理解其生命周期是避免“设了不生效”“改了没反应”的关键定义阶段在当前 shell 中执行VARvalue。此时变量仅在内存中存在echo $VAR可见但env | grep VAR查不到。导出阶段执行export VAR。系统将该变量复制一份到环境块env | grep VAR开始显示且新启动的子进程能继承。继承阶段当你运行ls、grep或启动新 shell如bash子进程会自动拷贝父进程的环境块因此能读取PATH、HOME等已导出变量。销毁阶段当前 shell 退出关闭终端或执行exit所有 shell 变量和未被子进程保留的环境变量全部释放。注意子进程修改自己的环境变量如在脚本里export PATH/new/bin:$PATH不影响父进程。这个链条解释了为什么.bashrc里写的export JAVA_HOME/opt/java在新开终端才生效——因为.bashrc是在新 shell 启动时被 source 的变量在那一刻才被定义并导出。2.3 为什么 PATH 是最常出问题的变量深度解析其搜索机制PATH是环境变量中的“顶流”也是故障高发区。它的值是一串由冒号:分隔的目录路径例如/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin。当输入gcc时系统按顺序扫描每个目录找到第一个gcc可执行文件即执行不再继续查找。这就带来三个经典陷阱顺序错误若把/home/user/bin放在PATH末尾而系统自带的/usr/bin/gcc已存在则自定义版本永远不生效。正确做法是前置export PATH/home/user/bin:$PATH。路径不存在export PATH/wrong/path:$PATH会导致每次命令查找都多扫一个无效目录虽不报错但拖慢响应。可用ls -d /wrong/path验证路径真实性。重复添加多次 source 配置文件可能导致PATH出现重复项如/usr/bin:/usr/bin:/bin。虽不影响功能但冗余且难维护。解决方法是先去重再拼接Bash 4.0 可用typeset -U PATH老版本则需手动处理。我在线上服务器踩过一次坑某次更新 Python 后pip命令突然报command not found。排查发现PATH里/usr/local/bin被误删而新版 pip 安装在此目录。修复只需一行export PATH/usr/local/bin:$PATH但定位花了 40 分钟——这就是理解PATH搜索逻辑的价值。3. 实操全流程从临时设置到永久生效的七种方法与适用场景3.1 临时设置仅对当前终端会话有效适合调试与快速验证这是最轻量、最安全的起步方式所有操作都在当前 shell 内存中完成关掉终端即还原毫无风险。# 1. 定义 shell 变量不导出 $ myproject/data/myapp $ echo $myproject /data/myapp $ env | grep myproject # 无输出证明未进入环境块 # 2. 导出为环境变量 $ export myproject $ env | grep myproject myproject/data/myapp # 3. 一步到位定义并导出 $ export EDITORvim # 4. 验证是否生效检查环境变量列表 $ printenv EDITOR vim # 或使用更通用的 env 命令 $ env | grep EDITOR # 5. 删除变量临时清除 $ unset EDITOR $ echo $EDITOR # 输出为空注意printenv和env都只显示环境变量不显示纯 shell 变量而set命令会同时列出所有变量含函数输出极长一般不用来查单个变量。实操心得我习惯在调试脚本前先用export DEBUG1打开调试开关脚本里用[ $DEBUG 1 ]判断是否输出详细日志。测试完直接unset DEBUG干净利落。这种“开关式”临时变量是开发中最常用的模式。3.2 用户级永久设置影响当前用户所有新终端推荐日常使用要让变量在每次打开新终端时自动加载必须写入用户专属的 shell 初始化文件。Bash 默认读取顺序为~/.bash_profile→~/.bash_login→~/.profile按存在优先级但绝大多数发行版包括 Ubuntu、Kali、国产 UOS实际使用~/.bashrc。原因在于图形界面终端GNOME Terminal、Konsole默认以“交互式非登录 shell”方式启动只读~/.bashrc而 SSH 登录或su -则是“登录 shell”读~/.bash_profile。为求统一标准做法是在~/.bash_profile末尾添加source ~/.bashrc。操作步骤以 Ubuntu/Kali/统信 UOS 为例# 1. 编辑 ~/.bashrc用 nano、vim 或你喜欢的编辑器 $ nano ~/.bashrc # 2. 在文件末尾添加你的变量务必用 export # 示例1添加自定义脚本目录 export PATH/home/$USER/bin:$PATH # 示例2设置 Java 环境 export JAVA_HOME/usr/lib/jvm/java-11-openjdk-amd64 export PATH$JAVA_HOME/bin:$PATH # 示例3配置代理注意生产环境慎用此处仅为演示 # export http_proxyhttp://127.0.0.1:8080 # export https_proxyhttp://127.0.0.1:8080 # 3. 保存并退出然后立即生效无需重启终端 $ source ~/.bashrc # 或简写 $ . ~/.bashrc # 4. 验证 $ echo $JAVA_HOME /usr/lib/jvm/java-11-openjdk-amd64 $ echo $PATH | tr : \n | head -5 # 查看 PATH 前5个路径 /home/yourname/bin /usr/lib/jvm/java-11-openjdk-amd64/bin /usr/local/bin /usr/bin /bin提示source命令是关键它让当前 shell 重新执行脚本内容相当于“热加载”。不执行这步修改只是文本不会影响当前会话。避坑指南不要在~/.bashrc里写export PATH...覆盖整个 PATH这会清空系统默认路径导致ls、cd等基础命令失效。永远用export PATHnew:$PATH追加。变量名区分大小写PATH和path是两个不同变量。系统只认大写的PATH。引号使用原则值中含空格时必须加双引号如export PS1\u\h:\w\$ 纯字母数字可不加但加了更规范。3.3 系统级永久设置影响所有用户需 root 权限谨慎操作当需要为所有用户包括新创建用户统一配置时需修改系统级文件。主要文件有/etc/environment纯键值对格式不支持变量展开、不支持export、不执行 shell 语法。格式为KEYVALUE每行一个。适用于绝对静态的全局变量如LANGen_US.UTF-8。/etc/profile所有用户登录 shell 的初始化脚本支持完整 shell 语法。适合需要逻辑判断的配置如根据架构设置不同路径。/etc/profile.d/*.sh推荐方式将配置拆分为独立.sh文件如/etc/profile.d/java.sh便于管理、启用/禁用。系统启动时会自动 source 所有.sh文件。实操为所有用户配置 JDK以 OpenJDK 17 为例# 1. 创建专用配置文件需 root $ sudo nano /etc/profile.d/java.sh # 2. 写入内容注意这里用 $() 执行命令获取动态路径 export JAVA_HOME$(dirname $(dirname $(readlink -f $(which java)))) export PATH$JAVA_HOME/bin:$PATH export JRE_HOME$JAVA_HOME/jre # 3. 赋予执行权限profile.d 下文件需可读 $ sudo chmod r /etc/profile.d/java.sh # 4. 让当前会话立即生效新用户登录时自动加载 $ source /etc/profile.d/java.sh # 5. 验证切换到其他用户测试 $ su - otheruser $ echo $JAVA_HOME /usr/lib/jvm/java-17-openjdk-amd64注意/etc/environment的特殊性。它由 PAMPluggable Authentication Modules模块pam_env.so解析不经过 shell因此不能写PATH/usr/local/bin:$PATH$PATH不会被展开。它只接受静态字符串适合LANG、TZ这类不变量。3.4 针对特定程序的变量设置精准控制避免全局污染有时你只想让某个命令如git使用特定变量而不影响其他程序。这时用env命令前缀是最优雅的方案。# 1. 临时为单次 git 命令设置代理 $ env http_proxyhttp://10.0.0.1:8080 git clone https://github.com/user/repo.git # 2. 为整个子 shell 设置括号内所有命令共享变量 $ (export PYTHONPATH/home/user/mylib; python3 -c import mymodule; print(mymodule.__file__)) # 3. 创建别名alias封装常用组合 $ alias mygitenv GIT_AUTHOR_NAMEMy Name GIT_AUTHOR_EMAILmedomain.com git $ mygit commit -m fix: update config高级技巧用 systemd 用户服务设置 GUI 应用变量在 GNOME/KDE 桌面环境下.bashrc对图形程序如 VS Code、Chrome无效因为它们不是从终端启动的。解决方案是配置 systemd 用户会话# 1. 创建用户级环境配置 $ mkdir -p ~/.config/environment.d $ nano ~/.config/environment.d/myapp.conf # 2. 写入变量格式同 /etc/environment JAVA_HOME/usr/lib/jvm/java-17-openjdk-amd64 PATH/usr/lib/jvm/java-17-openjdk-amd64/bin:/usr/local/bin:/usr/bin:/bin # 3. 重启用户会话或注销重登 $ systemctl --user restart dbus此方法被现代 Linux 发行版Fedora 34、Ubuntu 22.04、统信 UOS V20广泛采用是桌面环境变量管理的未来标准。4. 深度诊断与排查五类高频故障的现场还原与根因分析4.1 故障一“变量设了但命令找不到” —— PATH 检查清单这是新手最高频问题。假设你安装了kubectl到/opt/bin/kubectl并执行了export PATH/opt/bin:$PATH但终端仍报kubectl: command not found。排查流程按顺序执行步骤命令预期输出异常含义1. 确认 PATH 是否包含目标路径echo $PATH | tr : \n | grep opt/opt/bin若无说明 export 未生效或写错路径2. 确认目标路径下文件存在且可执行ls -l /opt/bin/kubectl-rwxr-xr-x 1 root root ... /opt/bin/kubectl若无文件或权限不足如-rw-r--r--需sudo chmod x /opt/bin/kubectl3. 确认文件是可执行二进制或脚本file /opt/bin/kubectl/opt/bin/kubectl: ELF 64-bit LSB pie executable, x86-64若显示cannot open或text但无 shebang可能是损坏或纯文本4. 检查是否被 alias 覆盖type kubectlkubectl is /opt/bin/kubectl若显示kubectl is aliased to ...说明 alias 优先级更高需unalias kubectl真实案例某次在 WSL2 中安装docker-compose下载的是docker-compose-Linux-x86_64二进制但忘记重命名为docker-compose。PATH里有/usr/local/binls /usr/local/bin/docker*显示docker-compose-Linux-x86_64自然找不到docker-compose命令。修复只需sudo mv /usr/local/bin/docker-compose-Linux-x86_64 /usr/local/bin/docker-compose。4.2 故障二“改了配置文件新终端不生效” —— 初始化文件加载链路验证你确认~/.bashrc末尾写了export MYVAR1也执行了source ~/.bashrc但新开终端echo $MYVAR仍是空。根因分析与验证确认终端类型右键终端标题栏 → “Preferences” → 查看是否勾选 “Run command as login shell”。若勾选则读~/.bash_profile否则读~/.bashrc。大多数 GUI 终端默认不勾选。检查~/.bash_profile是否覆盖了~/.bashrc$ grep -n bashrc\|source ~/.bash_profile # 应看到类似if [ -f ~/.bashrc ]; then . ~/.bashrc; fi # 若没有手动添加验证文件是否被读取在~/.bashrc开头加一行echo Loading .bashrc新开终端看是否有输出。无输出则证明未加载。检查语法错误~/.bashrc中任意一行语法错误如export PATH$PATH:/new/path少了引号路径含空格时会导致后续所有行不执行。用bash -n ~/.bashrc检查语法。提示在国产 Linux 系统如麒麟 Kylin中部分定制终端可能使用zsh作为默认 shell。执行echo $SHELL确认若为/bin/zsh则需修改~/.zshrc而非~/.bashrc。4.3 故障三“中文显示乱码” —— LANG/LC_* 变量全解析在 Kali Linux 或最小化安装的 CentOS 上ls列出中文文件名显示为??.txtvim编辑中文文档一片方块。核心变量与优先级LANG全局默认语言环境格式zh_CN.UTF-8。LC_*系列如LC_CTYPE,LC_MESSAGES针对特定功能的 locale优先级高于LANG。LC_ALL最高优先级会覆盖所有LC_*和LANG。生产环境严禁设置LC_ALL因为它会强制所有 locale 一致可能破坏系统消息本地化。诊断与修复# 1. 查看当前 locale 设置 $ locale # 2. 检查系统是否安装了中文 locale $ locale -a | grep zh_CN.utf8\|zh_CN.UTF-8 # 若无输出需生成Ubuntu/Debian $ sudo locale-gen zh_CN.UTF-8 $ sudo update-locale LANGzh_CN.UTF-8 # 3. 临时修复测试用 $ export LANGzh_CN.UTF-8 $ export LC_CTYPEzh_CN.UTF-8 # 4. 永久修复写入 ~/.bashrc echo export LANGzh_CN.UTF-8 ~/.bashrc echo export LC_CTYPEzh_CN.UTF-8 ~/.bashrc source ~/.bashrc关键点UTF-8必须大写zh_CN.utf8小写在某些旧系统上不识别。国产发行版如 UOS通常预装zh_CN.UTF-8但最小化安装可能缺失。4.4 故障四“子进程读不到变量” —— export 漏洞现场抓包你写了一个脚本deploy.sh里面echo $MYVAR是空的但你在终端里echo $MYVAR能打印出值。原因脚本运行在一个新的子 shell 中它只继承已导出的环境变量。如果你只执行了MYVAR1而没export MYVAR子进程就看不到。验证与修复# 1. 在终端设置未导出 $ MYVAR1 $ echo $MYVAR 1 $ ./deploy.sh # deploy.sh 内容echo In script: $MYVAR # 输出In script: # 2. 导出后重试 $ export MYVAR $ ./deploy.sh # 输出In script: 1 # 3. 更严谨的写法在脚本开头显式导入防御性编程 #!/bin/bash # deploy.sh : ${MYVAR:?Error: MYVAR is not set. Please export it first.} echo In script: $MYVAR注意:是 Bash 内置空命令${VAR:?msg}是参数扩展语法当VAR为空或未设置时打印错误信息并退出。这是脚本健壮性的黄金实践。4.5 故障五“变量值含空格或特殊字符脚本崩溃” —— 引号与转义的生死线定义export MYDIR/home/user/my project但在脚本中cd $MYDIR报错cd: /home/user/my: No such file or directory。根源Bash 在展开$MYDIR时会按空格分割成多个单词cd只收到第一个/home/user/my。正确解法三选一双引号包裹变量推荐cd $MYDIR # 正确保持整体为一个参数 cp $MYDIR/file.txt /tmp/使用数组存储多值路径高级mypaths(/home/user/my project /opt/app data) for dir in ${mypaths[]}; do echo Processing: $dir done避免空格用下划线或连字符治本export MYDIR/home/user/my_project # 从源头规避特殊字符处理表字符问题安全写法说明空格参数分割$VAR必须双引号$变量展开\$VAR或$VAR单引号禁止展开\$转义命令替换date反引号内命令会被执行*文件通配$VAR双引号内*失效保持字面量我曾因export BACKUP_DIR/backup/$(date %Y%m%d)在脚本中未加引号导致tar -cf backup.tar $BACKUP_DIR展开成tar -cf backup.tar /backup/20231001正确 vstar -cf backup.tar /backup/20231001/*错误*被通配。加引号是成本最低的防御。5. 进阶实战结合真实工作流的变量管理策略与自动化技巧5.1 开发者工作流用变量隔离多环境dev/staging/prod在微服务开发中频繁切换数据库地址、API 端口、密钥路径。硬编码在代码里是灾难用配置文件又分散。最佳实践是用环境变量分层管理。目录结构设计~/myproject/ ├── .env.dev # 开发环境变量 ├── .env.staging # 预发布环境变量 ├── .env.prod # 生产环境变量 └── start.sh # 启动脚本.env.dev内容export DB_HOSTlocalhost export DB_PORT5432 export API_URLhttp://localhost:3000 export SECRET_KEY_PATH/home/dev/keys/dev.keystart.sh脚本支持一键切换#!/bin/bash # start.sh ENV${1:-dev} # 默认 dev可传参./start.sh staging if [ ! -f .env.$ENV ]; then echo Error: .env.$ENV not found! exit 1 fi # 安全加载只允许 export 行过滤注释和空行 set -o allexport source .env.$ENV 2/dev/null set o allexport # 启动应用此处为示意 echo Starting in $ENV mode... echo DB_HOST: $DB_HOST # python3 app.py执行$ chmod x start.sh $ ./start.sh dev # 加载 .env.dev $ ./start.sh prod # 加载 .env.prodset -o allexport是 Bash 4.0 特性开启后所有后续变量定义自动export避免逐个写export。2/dev/null屏蔽 source 时的无关警告。5.2 运维自动化用 Ansible 动态注入变量到远程主机在批量部署国产 Linux 服务器如麒麟 Kylin时需统一配置 JDK、Python 路径。Ansible 是最佳选择。Ansible Playbook (setup-env.yml)--- - name: Configure Java Environment hosts: linux_servers become: yes vars: java_home: /usr/lib/jvm/java-11-openjdk-amd64 tasks: - name: Write JAVA_HOME to /etc/profile.d/java.sh copy: content: | export JAVA_HOME{{ java_home }} export PATH$JAVA_HOME/bin:$PATH dest: /etc/profile.d/java.sh mode: 0644 - name: Ensure /etc/environment has LANG lineinfile: path: /etc/environment line: LANGzh_CN.UTF-8 create: yes执行$ ansible-playbook setup-env.yml --limit kylin-servers此方案确保 100 台服务器变量完全一致且变更可审计、可回滚远胜手动 SSH 修改。5.3 安全加固敏感变量密码、密钥的合规存储方案export DB_PASSWORDmypass123是严重安全隐患密码会留在进程环境、历史命令、日志中。安全替代方案使用配置文件 严格权限# 创建密钥文件仅属主可读 $ echo mypass123 ~/.db_pass $ chmod 600 ~/.db_pass # 脚本中读取 DB_PASSWORD$(cat ~/.db_pass)利用系统密钥环Keyring# Ubuntu/GNOME 下使用 secret-tool $ secret-tool store --labelDB Password db system $ secret-tool lookup db systemDocker/Kubernetes 原生方案Docker:docker run -e DB_PASSWORD_FILE/run/secrets/db_pass ...Kubernetes:valueFrom: secretKeyRef: {name: db-secret, key: password}国产 Linux 特别提醒统信 UOS 和麒麟 Kylin 已集成国密算法支持敏感变量应优先使用其提供的uos-keyring或kylin-keyring工具符合等保 2.0 要求。5.4 性能优化减少 PATH 搜索开销的实测数据PATH过长会拖慢命令启动。实测对比i5-8250U, SSDPATH 长度目录数time ls平均耗时备注50.002s基准200.005s150%500.012s500%1000.025s1150%优化建议删除重复路径echo $PATH | tr : \n | sort -u | tr \n : | sed s/:$//移除无用路径/usr/games,/usr/local/share/perl5除非真用 Perl 游戏将高频命令目录前置/usr/local/bin自编译工具放/usr/bin前我在一台老旧的飞腾 CPU 国产服务器上将PATH从 87 项精简到 12 项后git status响应时间从 1.2s 降至 0.3s效果立竿见影。6. 终极检查清单与个人经验总结6.1 一分钟变量健康检查可直接粘贴执行将以下代码保存为check-env.sh每次怀疑变量异常时运行#!/bin/bash echo 当前 Shell 信息 echo SHELL: $SHELL echo UID: $(id -u) echo User: $(whoami) echo -e \n 关键环境变量 for var in PATH HOME USER LANG; do printf %-10s: %s\n $var ${!var} done echo -e \n PATH 有效性检查 echo PATH 共 $(echo $PATH | tr : \n | wc -l) 个目录 echo 无效路径不存在: echo $PATH | tr : \n | while read p; do [ -d $p ] || echo $p; done | grep echo -e \n 变量定义来源追踪 echo 当前 shell 初始化文件: ls -1 ~/.bashrc ~/.bash_profile ~/.profile 2/dev/null | grep -E \.(bashrc|bash_profile|profile)$ echo -e \n 推荐操作 echo 1. 检查 ~/.bashrc 末尾是否 export 了你的变量 echo 2. 执行 source ~/.bashrc 立即生效 echo 3. 新开终端验证6.2 我踩过的七个深坑与对应心法坑在~/.bashrc里写PATH$PATH:/new结果ls找不到→ 心法永远用PATH/new:$PATH追加绝不用覆盖。坑export JAVA_HOME/path/to/jdk后java -version仍报错→ 心法JAVA_HOME必须指向 JDK 根目录含bin/java不是jre子目录。坑WSL2 中DISPLAY变量设了但 GUI 应用无法显示→ 心法WSL2 需额外设置export DISPLAY$(cat /etc/resolv.conf | grep nameserver | awk {print $2; exit;}):0.0并运行 X Server。坑echo $PATH显示正常但which cmd找不到→ 心法which只搜索PATH中存在且可执行的文件用ls -l /path/to/cmd确认权限。坑systemctl --user服务读不到~/.bashrc变量→ 心法必须用~/.config/environment.d/*.conf这是 systemd 用户会话的唯一标准。坑脚本中export VARvalue但父 shell 读不到→ 心法子进程无法修改父进程环境这是 Unix 设计铁律。需用source script.sh或管道source (curl ...)坑国产 Linux 中locale -a | grep zh无输出dpkg-reconfigure locales失败→ 心法麒麟 Kylin 用sudo kylin-locales-config统信 UOS 用sudo uos-locales-config勿强行套用 Debian 命令。最后分享一个真实场景上周帮一家做嵌入式 Linux 的客户排查 buildroot 编译失败。现象是make menuconfig报ncursesw5-config: command not found。排查发现PATH里漏了buildroot/output/host/usr/bin而该目录下有ncursesw5-config。修复只需一行export PATH$HOME/buildroot/output/host/usr/bin:$PATH加入~/.bashrc。整个过程 8 分钟但背后是十年对PATH机制的肌肉记忆。变量管理没有玄学只有对机制的敬畏和对细节的偏执。你现在打开终端敲下echo $PATH看到的每一行都是 Linux 世界的宪法条款。