# Linux 与命令行 *命令行是机器学习工程的主要界面:训练任务、服务器管理、数据管道和集群管理都通过终端进行。本文涵盖 Shell、文件系统、权限、进程管理、包管理器、环境变量、SSH 以及每位机器学习工程师日常使用的基本命令。* - GUI 适合浏览网页,但在凌晨 2 点在远程 GPU 集群上运行训练任务时却很糟糕。**命令行**(或终端、Shell)是能够扩展的工具:它在任何机器上都能工作,可编写脚本,可组合,并且在你的笔记本电脑、云 VM 和 HPC 集群上完全相同。 - 如果你是一名只使用 Jupyter notebook 和 VS Code 按钮的机器学习工程师,你正在浪费巨大的生产力。每个生产级机器学习系统都是通过命令行进行部署、监控和调试的。 ## Shell - **Shell** 是一个读取你的命令并执行它们的程序。它是你和操作系统之间的中介(第 13 章)。最常见的 Shell 是 **bash**(大多数 Linux 系统的默认 Shell)和 **zsh**(macOS 的默认 Shell)。 - 命令的格式为:`command [options] [arguments]` ```bash ls -la /home/user # 命令=ls, 选项=-la, 参数=/home/user ``` - 选项修改行为(通常以 `-` 表示短选项,`--` 表示长选项)。`ls -l` 以长格式列出,`ls --all` 显示隐藏文件。许多选项可以组合:`ls -la` 表示将 `-l` 和 `-a` 一起使用。 ### 基本导航 ```bash pwd # 打印当前工作目录(我在哪?) ls # 列出当前目录中的文件 ls -la # 列出所有文件(包括隐藏文件)及详细信息 cd /path/to/dir # 切换目录 cd .. # 返回上一级 cd ~ # 返回用户主目录 cd - # 返回上一个目录 ``` ### 文件操作 ```bash cp source dest # 复制文件 cp -r dir1 dir2 # 递归复制目录 mv old new # 移动/重命名文件 rm file # 删除文件(没有回收站——永久删除) rm -rf dir # 递归删除目录(危险——无确认) mkdir -p a/b/c # 创建嵌套目录 touch file.txt # 创建空文件(或更新时间戳) cat file.txt # 打印文件内容 head -n 20 file # 显示前 20 行 tail -f logfile # 实时跟踪日志文件(监控训练时非常有用) ``` - **陷阱**:`rm -rf` 是计算中最危险的命令。没有撤销操作。按回车前请三次检查路径。切勿运行 `rm -rf /` 或 `rm -rf ~`。 ### 管道与重定向 - Shell 的杀手级特性是**可组合性**:将小命令连接起来完成复杂任务。 - **管道**(`|`):将一个命令的输出作为下一个命令的输入。 ```bash cat training.log | grep "loss" | tail -5 # 最后5行包含"loss"的内容 ps aux | grep python # 查找正在运行的 Python 进程 history | grep "docker" # 查找之前的 docker 命令 ``` - **重定向**:将输出发送到文件而不是屏幕。 ```bash python train.py > output.log 2>&1 # stdout 和 stderr 都输出到文件 python train.py >> output.log # 追加(不覆盖) echo "data" > file.txt # 覆盖文件 echo "more" >> file.txt # 追加到文件 ``` - `2>&1` 将 stderr(文件描述符 2)重定向到 stdout(文件描述符 1)。没有它,错误消息仍会出现在屏幕上,只有正常输出会进入文件。 ### 文本处理 ```bash grep "error" logfile.txt # 查找包含"error"的行 grep -r "import torch" src/ # 递归搜索目录 grep -i "warning" log.txt # 不区分大小写搜索 grep -c "epoch" train.log # 统计匹配行数 wc -l file.txt # 统计行数 wc -w file.txt # 统计单词数 sort data.txt # 按字母顺序排序 sort -n numbers.txt # 按数值排序 sort -u data.txt # 排序并去重 uniq -c sorted.txt # 统计连续重复项 cut -d',' -f2,3 data.csv # 提取 CSV 的第 2 和第 3 列 awk '{print $1, $3}' data.txt # 打印第 1 和第 3 个空白分隔字段 sed 's/old/new/g' file.txt # 将所有"old"替换为"new" ``` - 这些命令可以优美地组合: ```bash # 查找日志文件中最常见的 10 种错误类型 grep "ERROR" app.log | awk -F': ' '{print $2}' | sort | uniq -c | sort -rn | head -10 ``` ### 查找文件 ```bash find . -name "*.py" # 查找所有 Python 文件 find . -name "*.pyc" -delete # 查找并删除编译后的 Python 文件 find /data -size +100M # 查找大于 100MB 的文件 find . -mtime -1 # 查找过去 24 小时内修改过的文件 which python # python 可执行文件在哪? locate filename # 快速查找文件(使用预构建索引) ``` ## 文件系统层次结构 - Linux 将所有内容组织在以 `/` 为根的单棵树中: | 目录 | 用途 | |-----------|---------| | `/` | 整个文件系统的根 | | `/home/user` | 你的个人文件、配置、项目 | | `/etc` | 系统级配置文件 | | `/usr` | 用户程序、库、文档 | | `/usr/local` | 本地安装的软件(非包管理器安装) | | `/var` | 可变数据:日志(`/var/log`)、数据库、缓存 | | `/tmp` | 临时文件(重启后清除) | | `/opt` | 可选的第三方软件 | | `/proc` | 暴露内核和进程信息的虚拟文件系统 | | `/dev` | 设备文件(磁盘、GPU 在这里显示) | - 对于机器学习:你的训练数据通常在 `/data` 或 `/home/user/data`,模型在 `/home/user/models`,CUDA 在 `/usr/local/cuda`。GPU 设备显示为 `/dev/nvidia0`、`/dev/nvidia1` 等。 ## 文件权限 - 每个文件和目录有三种用户类别的三种权限类型: | 权限 | 文件 | 目录 | |------------|------|-----------| | **r**(读) | 查看内容 | 列出内容 | | **w**(写) | 修改内容 | 在内部创建/删除文件 | | **x**(执行) | 作为程序运行 | 进入(cd 进入)目录 | - 三种用户类别:**所有者**(u)、**组**(g)、**其他人**(o)。 ```bash ls -l script.py # -rwxr-xr-- 1 henry ml_team 2048 Mar 28 script.py # ^^^ 所有者权限:rwx(读、写、执行) # ^^^ 组权限:r-x(读、执行,不可写) # ^^^ 其他人权限:r--(只读) ``` ```bash chmod 755 script.py # owner=rwx, group=rx, others=rx chmod +x script.py # 为所有人添加执行权限 chmod u+w,g-w file.txt # 为所有者添加写权限,移除组的写权限 chown henry:ml_team file # 更改所有者和组 ``` - **陷阱**:顶部带有 `#!/usr/bin/env python3` 的 Python 脚本需要执行权限(`chmod +x`)才能以 `./script.py` 方式运行。没有它,你必须使用 `python3 script.py`。 ## 进程管理 - **进程**是一个正在运行的程序(第 13 章)。Shell 为你提供了管理它们的工具: ```bash ps aux # 列出所有正在运行的进程 ps aux | grep python # 查找 Python 进程 top # 实时进程监控(CPU、内存) htop # top 的增强版(需单独安装) nvidia-smi # GPU 使用情况(机器学习必备) watch -n 1 nvidia-smi # 每秒刷新 nvidia-smi kill PID # 优雅终止进程 kill -9 PID # 强制终止(优雅方式失败时使用) killall python # 终止所有 Python 进程 # 后台运行 python train.py & # 后台运行 nohup python train.py > log.txt & # 后台运行,退出登录后仍存活 ``` - **`nohup`** 对机器学习训练至关重要:没有它,关闭 SSH 连接会终止训练任务。`nohup` 将进程从终端分离出来。 - **`screen`** 和 **`tmux`** 是终端复用器,可以创建持久会话。你可以在 tmux 会话中启动训练任务,断开 SSH 连接,稍后重新连接,会话(和训练)仍在运行。 ```bash tmux new -s training # 创建命名会话 # ... 开始训练 ... # Ctrl+B, 然后 D # 从会话分离 tmux attach -t training # 稍后重新连接(即使 SSH 重新连接后也可用) tmux ls # 列出会话 ``` ## 包管理器 - **系统包**(操作系统级软件): ```bash # Debian/Ubuntu sudo apt update # 刷新包列表 sudo apt install htop # 安装包 sudo apt upgrade # 升级所有包 # macOS brew install wget # 通过 Homebrew 安装 ``` - **Python 包**: ```bash pip install torch # 从 PyPI 安装 pip install -e . # 以可编辑模式安装当前项目 pip install -r requirements.txt # 从 requirements 文件安装 pip freeze > requirements.txt # 导出已安装的包 # Conda(用于复杂依赖,如 CUDA) conda create -n myenv python=3.11 conda activate myenv conda install pytorch torchvision cudatoolkit=12.1 -c pytorch ``` - **陷阱**:永远不要将 `pip install` 安装到系统 Python 中。始终使用虚拟环境(`python -m venv env`、`conda create` 或 `uv venv`)。系统 Python 被操作系统工具共享;破坏它可能导致系统崩溃。 ## 环境变量 - **环境变量**是所有程序都可以访问的键值对。它们在不改变代码的情况下配置行为。 ```bash export CUDA_VISIBLE_DEVICES=0,1 # 仅使用 GPU 0 和 1 export PYTHONPATH=/home/user/src # 添加到 Python 的导入路径 export WANDB_API_KEY=abc123 # Weights & Biases 的 API 密钥 echo $PATH # 查看当前 PATH export PATH=$PATH:/usr/local/cuda/bin # 将 CUDA 添加到 PATH ``` - **`.bashrc`**(或 `.zshrc`):每次打开 Shell 时运行的命令。把你的 `export` 语句放在这里,这样它们就会持久存在。 - **`.env` 文件**:由 `python-dotenv` 等工具加载的项目特定变量。将密钥(API 密钥、数据库密码)保存在 `.env` 中,并将 `.env` 添加到 `.gitignore`。切勿将密钥提交到 Git。 ## SSH(安全外壳协议) - **SSH** 通过加密通道将你连接到远程机器。这是你访问云 VM、GPU 服务器和 HPC 集群的方式。 ```bash ssh user@hostname # 连接到远程机器 ssh -i ~/.ssh/key.pem user@ip # 使用特定密钥连接 ssh -L 8888:localhost:8888 user@server # 端口转发(远程 Jupyter) ``` - **SSH 密钥**(公钥/私钥对)替代密码: ```bash ssh-keygen -t ed25519 # 生成密钥对 ssh-copy-id user@server # 将公钥复制到服务器 # 现在无需输入密码即可 SSH ``` - **SSH 配置**(`~/.ssh/config`)保存连接详情: ``` Host gpu-server HostName 10.0.1.42 User henry IdentityFile ~/.ssh/gpu_key LocalForward 8888 localhost:8888 ``` - 现在输入 `ssh gpu-server` 即可自动使用所有这些设置进行连接。 - **`scp`** 和 **`rsync`** 在机器之间传输文件: ```bash scp model.pt user@server:/data/models/ # 将文件复制到远程 scp -r user@server:/data/results/ ./ # 从远程复制目录 rsync -avz --progress data/ user@server:/data/ # 带进度同步(比 scp 更智能) ``` ## 机器学习必备命令速查表 ```bash # GPU 监控 nvidia-smi # GPU 使用快照 watch -n 1 nvidia-smi # 实时监控 gpustat # 更清晰的 GPU 概览(pip install gpustat) # 训练管理 nohup python train.py > train.log 2>&1 & # 退出登录后仍存活的后台训练 tail -f train.log # 监控训练输出 kill %1 # 终止最后一个后台任务 # 磁盘使用(数据集很大) df -h # 所有挂载点的磁盘空间 du -sh /data/* # /data 中每个项目的大小 du -sh --max-depth=1 . # 子目录的大小 # 内存 free -h # RAM 使用情况 cat /proc/meminfo # 详细内存信息 # 网络 curl -O https://example.com/dataset.tar.gz # 下载文件 wget https://example.com/model.bin # 替代下载工具 curl -X POST http://localhost:8080/predict \ -H "Content-Type: application/json" \ -d '{"text": "hello"}' # 测试模型推理端点 # 归档 tar -czf archive.tar.gz directory/ # 压缩 tar -xzf archive.tar.gz # 解压 zip -r archive.zip directory/ # zip 压缩 unzip archive.zip # zip 解压 # 快速数据检查 head -5 data.csv # CSV 的前 5 行 wc -l data.csv # 统计行数 cut -d',' -f1 data.csv | sort -u | wc -l # 统计第 1 列的唯一值数量 ```