🖥️ 第08章 · 重定向/管道/环境变量
export PATH > >> < |
重定向 / 管道 / 环境变量¶
这一章讲 Shell 的"连接"能力:把输出送到文件、把文件读进命令、把一个命令的结果喂给下一个命令,以及那个藏在背后的环境变量表。它是把简单命令组合成强大工具的分水岭。
标准输入输出与文件描述符¶
每个进程默认有三个流:
| 名称 | 文件描述符 | 默认去向 | 符号 |
|---|---|---|---|
| 标准输入 stdin | 0 |
键盘 | < |
| 标准输出 stdout | 1 |
屏幕 | > |
| 标准错误 stderr | 2 |
屏幕 | 2> |
重定向就是把这几个流"改道"。
输出重定向 > 与 >>¶
命令 > 文件 # 把标准输出写入文件(覆盖旧内容)
命令 >> 文件 # 把标准输出追加到文件末尾
echo "hello" > app.log # 写入,覆盖
echo "world" >> app.log # 追加到末尾
警告
>会直接覆盖目标文件,不留备份。想保留就用>>追加,或先cp一份原文件。误用>覆盖系统配置是最常见的"我把配置清空了"事故。
错误重定向 2>¶
如果命令执行出错,报错信息走的是 stderr(2),普通 > 拦不住它。
命令 2> error.log # 把错误信息写入 error.log
命令 > all.log 2>&1 # 把标准输出和错误都写入同一个文件
命令 > /dev/null 2>&1 # 既不看输出也不看错误(静默)
2>&1 的含义是"把 stderr(2)重定向到当前 stdout(1)已经指向的地方"。
提示 排查部署脚本时,
命令 2>&1非常重要——因为 Python/Node 报错、apt 报错都走 stderr,只重定向>时看不到任何错误,会误以为"成功"。
输入重定向 < 与 <<<¶
命令 < 文件 # 把文件内容作为命令的输入
wc -l < access.log # 统计 input.log 行数,不走"文件参数"方式
mysql -u root <<< "SHOW DATABASES;" # 把字符串作为输入喂给命令
<<<(Here-string)把一段文本直接作为输入传给前面的命令。<<EOF(Here-doc)则能在脚本里嵌入多行内容。
管道 |¶
管道是重定向的升华:把左边命令的标准输出,直接接成右边命令的标准输入。它不经过文件,数据扇贝一样流过。
命令1 | 命令2 | 命令3
ps aux | grep node # 筛进程
cut -d: -f1 /etc/passwd | sort | wc -l # 数用户
grep "GET" access.log | awk '{print $1}' | sort | uniq -c | sort -rn
提示 管道是"命令组合拳"的灵魂。管道链里只有最后一条命令的输出会显示到屏幕,前面的都作为"中间数据"。常见"三件套":
grep 筛行 | cut/awk 提列 | sort|uniq 统计。
在这台服务器上统计 nginx 访问量:
awk '{print $9}' /var/log/nginx/access.log 2>/dev/null | sort | uniq -c
环境变量与环境变量表¶
环境变量是"进程启动时就带着的一组键值对",影响程序行为。它们存进 Shell 的环境变量表,并继承给所有子进程。
echo $PATH # 查询变量,取值加 $
echo $HOME # 家目录
printenv # 列出所有环境变量
| 变量 | 常见含义 |
|---|---|
PATH |
命令查找路径(冒号分隔) |
HOME |
当前用户家目录 |
USER/USERNAME |
当前用户名 |
SHELL |
当前 Shell 路径 |
LANG |
语言/编码 |
NODE_ENV |
应用运行环境(production/development) |
注意 查询变量要
$前缀(echo $PATH);赋值时不加$,且=两边不能有空格。
设置与导出环境变量 export¶
export NODE_ENV=production # 设置并导出给子进程
export PATH=$PATH:/opt/custom/bin # 追加路径
export 以外的普通赋值只在当前 Shell 生效,不传给子进程。要让 CDN/部署脚本、systemd 服务读到,往往要 export 或用 env 指定。
NODE_ENV=production node server.js # 单次启动时临时带环境
env | grep NODE_ENV # 确认变量
在这台服务器上,前端应用由 systemd 托管时,环境变量写在服务的 Environment= 里(比如 NODE_ENV=production),而非常驻 export——因为 systemd 启动的进程没走你的 Shell。
环境变量持久化¶
要让某个变量永久生效,取决于你想影响谁:
| 方式 | 写入位置 | 生效范围 |
|---|---|---|
~/.bashrc |
当前用户登录 Shell | 当前用户 |
~/.profile |
当前用户登录时 | 当前用户 |
/etc/profile |
所有用户登录 | 全系统 |
/etc/environment |
登录时全局 | 全系统 |
systemd Environment= |
特定服务 | 该服务 |
# 以追加 PATH 为例,写进 ~/.bashrc 末尾
echo 'export PATH=$PATH:/opt/bin' >> ~/.bashrc
source ~/.bashrc # 让修改在当前会话立即生效
警告
source后临时生效,但要重开终端才真正落定。还有一个坑:export PATH=...时如果不小心写错路径,可能让 shell 找不到任何命令,连ls都用不了。修改 PATH 前务必先备份原值。
综合实战:环境变量 + 管道¶
给一个 Node 服务临时设置生产模式并把输出记到日志:
NODE_ENV=production node server.js >> /var/log/app.log 2>&1
# 环境变量注入 + 追加日志 + 错误也进日志
易错点¶
>是覆盖,>>是追加,别用错。- 报错要走
2>&1,否则看不到错误。 =两边不能有空格(NODE_ENV = xxx是错的)。- 查询需要
$,赋值不能带$。 - 改 PATH 前先记下原值,以免把自己锁死。
相关命令¶
echo、export、unset、env、printenv、>、>>、<、|、tee(边输出到屏幕边写文件)、xargs(把管道输出当成参数交给命令)。