---
title: "后台 bash 命令"
description: "长命令一跑，对话就停。这一节把长任务挪到后台：让 Claude 托管、用感叹号自己跑、加日志重定向、分屏协作，各有适用场景。"
updated: 2026-11-13
canonical: https://docai.cc/learn/background-bash-commands/
markdown_mirror: https://docai.cc/learn/background-bash-commands.md
---
## 为什么会被一条命令卡住

开发服务器、监听模式、完整的测试套件，共同点是要么不主动结束，要么要跑很久。交给 Claude 在前台执行，界面会一直等它结束；超过超时时间后，Claude Code 会自动把它转到后台（以 sleep 开头的命令除外），但在那之前它没法继续回答，你也只能看着日志滚动。想边跑边聊，核心思路是把耗时的任务挪出对话主线程。

具体有四层做法：让 Claude 自己把命令放到后台；你在输入框里直接跑 shell；绕开 Claude，用 nohup 和日志自己托管；或者用终端复用器分屏，把不同的活分到不同窗格。四层可以混着用，按任务长短以及是否需要 Claude 看见输出来挑。

## 第一层：让 Claude 放到后台

直接说「这个服务放后台跑，别等我」。Claude 启动后不会阻塞，而是拿到一个任务编号，你们可以接着讨论别的改动。需要看进度时，让它按编号读取新增的那部分输出，或者去读它写出的日志文件；要停，就让它结束对应任务。按编号读取一般是增量的，上次看过的内容不会重复刷屏；直接读文件则要自己控制范围。命令已经在前台跑起来时，按 Ctrl+B 也能把它挪到后台；tmux 用户要按两次，因为 Ctrl+B 是 tmux 的前缀键。

这一层最适合「跑起来之后还要根据结果继续改」的场景：服务起在后台，你让它改组件，改完再读一遍日志，确认没有编译错误。退出 Claude Code 时，这些后台任务会被清理；如果你只是把整个会话转到后台而不是退出，任务会继续跑。

## 第二层：感叹号自己跑

在输入框最前面加一个感叹号，后面整行会被当作 shell 命令直接执行，不需要模型先理解或批准。命令与输出都会写进对话记录，Claude 随后会自动就输出作出回应；如果只想把输出放进上下文、不要回应，可以在设置里把 `respondToBashCommands` 设为 false。长跑命令在 shell 模式里同样可以按 Ctrl+B 挪到后台。

```bash
!git status --short
!pnpm dev
# 回车后按 Ctrl+B，把它挪到后台
```

第一行属于秒回的命令；第二行启动服务后立刻转后台，避免占住输入框。由于命令和输出都会进上下文，别在感叹号后面跑那种会把密钥或内部地址打印出来的命令；真要跑，先在别处确认输出范围。

## 第三层：shell 的后台与日志

不经过 Claude，也可以自己托管进程：命令末尾加 & 让它后台运行，标准输出与错误用重定向写进文件。这样关掉终端时，进程可能收到挂断信号而退出；要让它活得更久，用 nohup 包一层。disown 则把任务从当前 shell 的作业表里摘掉，效果相近，但不会替你处理日志。

```bash
nohup pnpm dev > /tmp/api.log 2>&1 &
jobs
kill %1
```

后台跑起来后，用 jobs 看当前 shell 的任务，用 kill 按作业号或进程号停止。排查端口占用时，lsof 或 netstat 能帮你找到占着端口的进程。日志配合 tail 查看，比让 Claude 通读整个文件省事得多。

## 用分屏把活分开

最稳的协作方式不是让一个进程包办所有事，而是分屏：一个窗格跑 Claude，一个跑服务，一个盯日志，一个留给自己敲临时命令。终端复用器（例如 tmux）能在同一个窗口里切出多个窗格，断开连接后任务还在。

在这种布局里，Claude 只需要看它该看的东西：你让它把服务窗格末尾几十行取回来分析。反过来，也可以让它往指定窗格发送启动命令。把「谁在哪个窗格」约定清楚，比每次重新解释上下文有效。

## 四层手段怎么选：一张判断表

先看任务持续多久、需不需要 Claude 参与判断，再决定用哪一层：

| 场景 | 选哪层 | 理由 |
|---|---|---|
| 跑测试、装依赖，几分钟内结束 | 第一层，交给 Claude 后台执行 | 结束后还要它读结果、接着改 |
| 临时查目录、看 Git 状态 | 第二层，感叹号直接跑 | 不必让模型代劳，也不占回合 |
| 开发服务要开一整天 | 第三层，nohup 加日志 | 跨会话存活，不随对话退出 |
| 多个服务、日志、测试并行 | 第四层，终端复用器分屏 | 每块输出各归其位，互不干扰 |

用这张表时按两个问题排除：任务结束后还需不需要 Claude 读结果、接着改？需要，就用第一层；不需要，再看进程要不要活过本次会话——几秒内返回的临时命令用第二层，要活过就用第三层或第四层。第一层的调用会立刻返回任务句柄，按句柄取输出通常只送回上次之后新增的部分，不阻塞，标准错误也一并带回；多数实现还允许附一个正则，只取匹配行。停止时按同一个句柄结束任务，不同版本的工具名和参数略有差异，以当前版本的说明为准。

第二层省掉一轮模型调用，适合「我自己扫一眼就行」的命令，代价是输出直接进入对话上下文，敏感的地址和令牌不要这样跑。

第三层不依赖 Claude 是否在运行：用 `nohup` 加日志重定向，再把进程号存进文件，是最小可用的托管方式，第二天要停也能按文件里的编号找到进程。

第四层适合长时间、多进程的活，断开后仍保留会话。以 tmux 为例，建会话、切窗格、把命令发给指定窗格分别是 `tmux new -s dev`、`tmux split-window -h`、`tmux send-keys -t dev:0.1 'pnpm dev' C-m`，取某个窗格末尾输出用 `tmux capture-pane -pt dev:0.1 | tail -n 40`；别的复用器先查它自己的帮助。

判断时还要看输出量：日志每秒几百行时，先重定向到文件再按需截取，比一直读进上下文便宜。

## 一个可复用的启动脚本与故障排查

把启动、停止、查状态固定成脚本，比每次手敲长命令可靠。下面这份可以直接保存为 `dev-env.sh`：

```bash
#!/usr/bin/env bash
set -u
PID_DIR=/tmp/demo-pids
mkdir -p "$PID_DIR"

start() {
  nohup pnpm dev > /tmp/demo-dev.log 2>&1 &
  echo $! > "$PID_DIR/dev.pid"
  echo "started: $(cat "$PID_DIR/dev.pid")"
}

stop() {
  [ -f "$PID_DIR/dev.pid" ] || { echo "not running"; return; }
  kill "$(cat "$PID_DIR/dev.pid")" 2>/dev/null || true
  rm -f "$PID_DIR/dev.pid"
  echo "stopped"
}

status() {
  if [ -f "$PID_DIR/dev.pid" ] && kill -0 "$(cat "$PID_DIR/dev.pid")" 2>/dev/null; then
    echo "running"
  else
    echo "down"
  fi
}

case "${1:-}" in
  start|stop|status) "$1" ;;
  *) echo "usage: $0 {start|stop|status}" ;;
esac
```

两个细节值得留意：`$!` 拿到的是刚放入后台那个进程的编号，存下来才能精确停止；`kill -0` 只探测进程是否存在，不会真的发信号，适合用来查状态。日志路径固定之后，你只要让 Claude 读文件末尾若干行，就能判断服务有没有起来。

跑不起来时，先按症状分桶，再动手：

| 现象 | 为什么 | 怎么办 |
|---|---|---|
| 任务显示在跑，读输出却是空的 | 程序发现输出不是终端，改成了块缓冲 | 等积满一块再看；或在 Linux 下用 `stdbuf -oL` 启动；或让程序打开行缓冲选项 |
| 关掉终端后进程消失 | shell 退出时向子进程发了挂断信号 | `nohup` 加日志重定向，或启动后 `disown`；Windows 改用后台作业 |
| 服务起不来，提示端口被占 | 上一次的进程没退干净 | `lsof -i :3000` 或 `netstat -ano | findstr :3000` 找编号，再按编号结束 |
| 第二天回来，Claude 的任务句柄失效 | 句柄只在会话内有效，退出会清理 | 改用 `nohup` 或终端复用器托管 |

还有一类命令不该硬塞进后台：需要键盘输入、需要确认提示、依赖终端的程序。它们没有可用的标准输入，跑起来会一直等。真要与这类程序交互，可以走伪终端复用器的发送按键功能，或者用命名管道把输入接进去：

```bash
mkfifo /tmp/demo-in
nohup ./interactive-tool < /tmp/demo-in > /tmp/demo.log 2>&1 &
echo "yes" > /tmp/demo-in
```

这条路径只适合偶尔为之；能改造成读参数或读配置的工具，优先改工具。历史里那些调好的等待与监控写法，可以配合[命令历史](/learn/command-history/)一起整理。

## 边界：什么时候不要后台

几秒钟就结束的命令，前台跑更省事：结果直接回到对话里，不需要再读一次。需要立刻拿输出做下一步判断的，也别绕后台。后台真正适合的是长跑、持续输出、你可以先去忙别的任务的情况。

另外，要让任务跨会话存活，别依赖 Claude 的后台编号，自己用 nohup 或分屏托管。Windows 上没有 nohup 时，可以用 PowerShell 的后台作业，或者直接在 WSL 里按 Linux 的方式做。工具执行与权限的边界，见[工具调用](/concepts/tool-use/)。

判断标准只有一句：这条命令是不是会一直占着对话。会，就挪到后台；不会，就让它在前台跑完。下一节换个角度，讲输入框本身怎么变得更趁手，见[Vim 编辑器模式](/learn/vim-editor-mode/)。
