Capistrano 3.20 常用 CLI 命令详解

Capistrano 3.20.1 cap 命令族全实测:--help 选项总览、cap install、任务发现(-T/-D/-P/-W)、deploy/check/rollback/cleanup 多机编排回显、dry-run、-z/-r 过滤与 doctor 排障报告。

CapistranoCapistranoRuby自动化部署2026/10/27

Capistrano 3.20 常用 CLI 命令详解

目标:逐条详解 Capistrano 3.20.1 的 cap 命令族——选项总览、项目初始化、任务发现(-T/-D/-P/-W)、部署/检查/回滚/清理全流程、doctor 排障报告、dry-run 预演、主机与角色过滤,全部命令均在真实多机环境实测并附回显。已在 Ubuntu 22.04.5 控制机 + 2 台目标服务器(web1.local / web2.local)实测通过(2026-10-27)。

一、环境信息

  • 控制机:Ubuntu 22.04.5 LTS,Ruby 3.0.2p107,Capistrano 3.20.1(/usr/local/bin/cap)
  • 目标服务器:web1.local、web2.local(Ubuntu 22.04.5,OpenSSH + git,部署账号 admin)
  • 演示项目:/root/demo-deploy(stage:production,2 台服务器均挂 app+web 角色)
  • 演示应用:静态站点 demo-app(仓库 http://controller.local:8000/demo-app.git),部署到 /var/www/demo-app

二、工具概览

Capistrano 只提供一个 CLI:cap。它本质是「Rake 任务执行器 + SSHKit 远程执行层」——cap <stage> <task> 把名为 task 的 Rake 任务在 stage 定义的所有服务器上并发执行。因此命令行选项大量继承自 Rake(-T/-P/-t 等),Capistrano 自己加了 stage 概念和 -z/-r 主机过滤。

capify 是随 gem 附带的旧版初始化命令(Capistrano 2.x 遗留),3.x 已统一用 cap install,本文不再单列。

版本确认:

which cap
cap --version

实测回显:

/usr/local/bin/cap
Capistrano Version: 3.20.1 (Rake Version: 13.0.6)

三、前置条件

  1. 已安装 Capistrano 3.20.1,见《Ubuntu 22.04 安装 Capistrano 3.20 指南》。
  2. 项目目录已 cap install 初始化、deploy.rb 与 stage 文件已按《Capistrano 3.20 配置参数详解》配置完毕;控制机可免密 SSH 到全部目标服务器。
  3. 除 cap install/cap -T 等少数命令外,其余命令都要带 stage(如 cap production ...),且必须在含 Capfile 的项目目录内执行。

四、cap 全局选项总览

cap --help

实测回显(完整照抄):

See full documentation at http://capistranorb.com/.

Install capistrano in a project:
    bundle exec cap install [STAGES=qa,staging,production,...]

Show available tasks:
    bundle exec cap -T

Invoke (or simulate invoking) a task:
    bundle exec cap [--dry-run] STAGE TASK

Advanced options:
        --backtrace=[OUT]            Enable full backtrace.  OUT can be stderr (default) or stdout.
        --comments                   Show commented tasks only
        --job-stats [LEVEL]          Display job statistics. LEVEL=history displays a complete job list
        --rules                      Trace the rules resolution.
        --suppress-backtrace PATTERN Suppress backtrace lines matching regexp PATTERN. Ignored if --trace is on.
    -A, --all                        Show all tasks, even uncommented ones (in combination with -T or -D)
    -B, --build-all                  Build all prerequisites, including those which are up-to-date.
    -C, --directory [DIRECTORY]      Change to DIRECTORY before doing anything.
    -D, --describe [PATTERN]         Describe the tasks (matching optional PATTERN), then exit.
    -e, --execute CODE               Execute some Ruby code and exit.
    -E, --execute-continue CODE      Execute some Ruby code, then continue with normal task processing.
    -f, --rakefile [FILENAME]        Use FILENAME as the rakefile to search for.
    -G, --no-system, --nosystem      Use standard project Rakefile search paths, ignore system wide rakefiles.
    -g, --system                     Using system wide (global) rakefiles (usually '~/.rake/*.rake').
    -I, --libdir LIBDIR              Include LIBDIR in the search path for required modules.
    -j, --jobs [NUMBER]              Specifies the maximum number of tasks to execute in parallel. (default is number of CPU cores + 4)
    -m, --multitask                  Treat all tasks as multitasks.
    -N, --no-search, --nosearch      Do not search parent directories for the Rakefile.
    -P, --prereqs                    Display the tasks and dependencies, then exit.
    --execute-print CODE             Execute some Ruby code, print the result, then exit.
        --require MODULE             Require MODULE before executing rakefile.
    -R, --rakelibdir RAKELIBDIR,     Auto-import any .rake files in RAKELIBDIR. (default is 'rakelib')
        --rakelib
    -t, --trace=[OUT]                Turn on invoke/execute tracing, enable full backtrace. OUT can be stderr (default) or stdout.
    -T, --tasks [PATTERN]            Display the tasks (matching optional PATTERN) with descriptions, then exit. -AT combination displays all of tasks contained no description.
    -W, --where [PATTERN]            Describe the tasks (matching optional PATTERN), then exit.
    -X, --no-deprecation-warnings    Disable the deprecation warnings.
    -V, --version                    Display the program version.
    -n, --dry-run                    Do a dry run without executing actions
    -r, --roles ROLES                Run SSH commands only on hosts matching these roles
    -z, --hosts HOSTS                Run SSH commands only on matching hosts
    -p, --print-config-variables     Display the defined config variables before starting the deployment tasks.
    -h, -H, --help                   Display this help message.

重点记四组:任务发现(-T/-A/-D/-P/-W)、执行控制(-n dry-run、-t trace、-j 并行度)、主机过滤(-z 按主机、-r 按角色)、诊断(doctor 任务、--backtrace)。

五、项目初始化:cap install

mkdir -p /root/demo-deploy && cd /root/demo-deploy
cap install STAGES=production

实测回显:

mkdir -p config/deploy
create config/deploy.rb
create config/deploy/production.rb
mkdir -p lib/capistrano/tasks
create Capfile
Capified

STAGES=qa,staging,production 逗号分隔可一次生成多个 stage 文件;不写则默认只生成 production.rb。

六、任务发现类命令

6.1 cap -T:列出带描述的任务

cap -T

实测回显(本项目含自定义任务后的完整清单):

cap app:restart                       # Restart demo app (write restart timestamp into shared/log)
cap app:show_revision                 # Show current release revision
cap deploy                            # Deploy a new release
cap deploy:check                      # Check required files and directories exist
cap deploy:check:directories          # Check shared and release directories exist
cap deploy:check:linked_dirs          # Check directories to be linked exist in shared
cap deploy:check:linked_files         # Check files to be linked exist in shared
cap deploy:check:make_linked_dirs     # Check directories of files to be linked exist in shared
cap deploy:cleanup                    # Clean up old releases
cap deploy:cleanup_rollback           # Remove and archive rolled-back release
cap deploy:finished                   # Finished
cap deploy:finishing                  # Finish the deployment, clean up server(s)
cap deploy:finishing_rollback         # Finish the rollback, clean up server(s)
cap deploy:log_revision               # Log details of the deploy
cap deploy:published                  # Published
cap deploy:publishing                 # Publish the release
cap deploy:revert_release             # Revert to previous release timestamp
cap deploy:reverted                   # Reverted
cap deploy:reverting                  # Revert server(s) to previous release
cap deploy:rollback                   # Rollback to previous release
cap deploy:set_current_revision       # Place a REVISION file with the current revision SHA in the current release path
cap deploy:set_current_revision_time  # Place a REVISION_TIME file with the current revision commit time in the current release path
cap deploy:started                    # Started
cap deploy:starting                   # Start a deployment, make sure server(s) ready
cap deploy:symlink:linked_dirs        # Symlink linked directories
cap deploy:symlink:linked_files       # Symlink linked files
cap deploy:symlink:release            # Symlink release to current
cap deploy:symlink:shared             # Symlink files and directories from shared to release
cap deploy:updated                    # Updated
cap deploy:updating                   # Update server(s) by setting up a new release
cap doctor                            # Display a Capistrano troubleshooting report (all doctor: tasks)
cap doctor:environment                # Display Ruby environment details
cap doctor:gems                       # Display Capistrano gem versions
cap doctor:servers                    # Display the effective servers configuration
cap doctor:variables                  # Display the values of all Capistrano variables
cap git:check                         # Check that the repository is reachable
cap git:clone                         # Clone the repo to the cache
cap git:create_release                # Copy repo to releases
cap git:set_current_revision          # Determine the revision that will be deployed
cap git:set_current_revision_time     # Determine the unix timestamp that the revision that will be deployed was created
cap git:update                        # Update the repo mirror to reflect the origin state
cap git:wrapper                       # Upload the git wrapper script, this script guarantees that we can script git without getting an interactive prompt
cap install                           # Install Capistrano, cap install STAGES=staging,production

支持模式过滤:cap -T deploy 只列 deploy 族;cap -A -T 把无描述的内部任务也列出来。

6.2 cap -D:查看任务详细描述

cap -D deploy:rollback

实测回显:

cap deploy:rollback
    Rollback to previous release.

6.3 cap -P:查看任务依赖树

cap -P deploy

实测回显(节选,完整照抄见下):

cap deploy
cap deploy:check
    git:check
cap deploy:check:directories
cap deploy:check:linked_dirs
...
cap deploy:symlink:release
cap deploy:updated
cap deploy:updating
    new_release_path
cap doctor
    doctor:environment
    doctor:gems
    doctor:variables
    doctor:servers
...

缩进表示前置依赖——cap deploy 实际是按这条依赖链依次触发 20 余个子任务,排障时用它定位「哪一环挂了」。

6.4 cap -W / --where:定位任务定义文件

cap -W deploy:rollback 输出该任务定义在哪个 gem 文件的哪一行,自定义任务冲突时用它查来源。

七、部署主流程命令

7.1 cap <stage> deploy:多机编排部署

cap production deploy

实测回显(首次部署,完整照抄):

00:00 git:wrapper
      01 mkdir -p /tmp
    ✔ 01 admin@web1.local 0.106s
    ✔ 01 admin@web2.local 0.111s
      Uploading /tmp/git-ssh-3f9448fa6b3cbd13ac8c.sh 100.0%
      Uploading /tmp/git-ssh-3f9448fa6b3cbd13ac8c.sh 100.0%
      02 chmod 700 /tmp/git-ssh-3f9448fa6b3cbd13ac8c.sh
    ✔ 02 admin@web2.local 0.006s
    ✔ 02 admin@web1.local 0.007s
00:00 git:check
      01 git ls-remote http://controller.local:8000/demo-app.git HEAD
      01 ecddef79f15c98e77703b4555729e015ae6d0ea9	HEAD
    ✔ 01 admin@web2.local 0.058s
      01 ecddef79f15c98e77703b4555729e015ae6d0ea9	HEAD
    ✔ 01 admin@web1.local 0.059s
00:00 deploy:check:directories
      01 mkdir -p /var/www/demo-app/shared /var/www/demo-app/releases
    ✔ 01 admin@web1.local 0.007s
    ✔ 01 admin@web2.local 0.007s
00:00 deploy:check:linked_dirs
      01 mkdir -p /var/www/demo-app/shared/log
    ✔ 01 admin@web1.local 0.005s
    ✔ 01 admin@web2.local 0.005s
00:00 deploy:check:make_linked_dirs
      01 mkdir -p /var/www/demo-app/shared/config
    ✔ 01 admin@web2.local 0.006s
    ✔ 01 admin@web1.local 0.008s
00:00 git:clone
      01 git clone --mirror http://controller.local:8000/demo-app.git /var/www/demo-app/repo
      01 Cloning into bare repository '/var/www/demo-app/repo'...
      01 Cloning into bare repository '/var/www/demo-app/repo'...
    ✔ 01 admin@web1.local 0.188s
    ✔ 01 admin@web2.local 0.199s
00:00 git:update
      01 git remote set-url origin http://controller.local:8000/demo-app.git
    ✔ 01 admin@web1.local 0.010s
      02 git remote update --prune
    ✔ 01 admin@web2.local 0.012s
      02 Fetching origin
      02 Fetching origin
    ✔ 02 admin@web1.local 0.070s
    ✔ 02 admin@web2.local 0.073s
00:00 git:create_release
      01 mkdir -p /var/www/demo-app/releases/20261027091548
    ✔ 01 admin@web2.local 0.007s
      02 git archive master | /usr/bin/env tar -x -f - -C /var/www/demo-app/releases/20261027091548
    ✔ 01 admin@web1.local 0.016s
    ✔ 02 admin@web2.local 0.016s
    ✔ 02 admin@web1.local 0.011s
00:00 deploy:set_current_revision
      01 echo "ecddef79f15c98e77703b4555729e015ae6d0ea9" > REVISION
    ✔ 01 admin@web1.local 0.007s
    ✔ 01 admin@web2.local 0.009s
00:00 deploy:set_current_revision_time
      01 echo "1793092507" > REVISION_TIME
    ✔ 01 admin@web1.local 0.008s
    ✔ 01 admin@web2.local 0.010s
00:00 deploy:symlink:linked_files
      01 mkdir -p /var/www/demo-app/releases/20261027091548/config
    ✔ 01 admin@web2.local 0.008s
    ✔ 01 admin@web1.local 0.009s
      02 ln -s /var/www/demo-app/shared/config/app.conf /var/www/demo-app/releases/20261027091548/config/app.conf
    ✔ 02 admin@web1.local 0.004s
    ✔ 02 admin@web2.local 0.006s
00:00 deploy:symlink:linked_dirs
      01 mkdir -p /var/www/demo-app/releases/20261027091548
    ✔ 01 admin@web1.local 0.006s
    ✔ 01 admin@web2.local 0.007s
      02 ln -s /var/www/demo-app/shared/log /var/www/demo-app/releases/20261027091548/log
    ✔ 02 admin@web2.local 0.008s
    ✔ 02 admin@web1.local 0.006s
00:00 deploy:symlink:release
      01 ln -s /var/www/demo-app/releases/20261027091548 /var/www/demo-app/releases/current
    ✔ 01 admin@web2.local 0.007s
      02 mv /var/www/demo-app/releases/current /var/www/demo-app
    ✔ 01 admin@web1.local 0.009s
    ✔ 02 admin@web2.local 0.005s
    ✔ 02 admin@web1.local 0.005s
00:00 deploy:log_revision
      01 echo "Branch master (at ecddef79f15c98e77703b4555729e015ae6d0ea9) deployed as release 20261027091548 by " >> /var/www/demo-app/revisions.log
    ✔ 01 admin@web2.local 0.005s
    ✔ 01 admin@web1.local 0.006s

读法:左侧 00:00 为任务名;01/02 为步骤序号;✔ 01 admin@web1.local 0.106s 表示该步骤在该机耗时;两台机并发执行(SSHKit 并行组)。从 git 检查 → 建目录 → 镜像克隆 → 导出 release → 链接 shared → 切换 current → 记审计日志,一条链全绿即发布成功。

目标机验证(web1):

ls -la /var/www/demo-app/
cat /var/www/demo-app/current/index.html
lrwxrwxrwx 1 admin admin   41 Oct 27 09:15 current -> /var/www/demo-app/releases/20261027091548
(其余行:releases、repo、revisions.log、shared)
<h1>Hello Capistrano v1</h1>

7.2 cap <stage> deploy:check:发布前预检

cap production deploy:check

实测回显(节选首尾):

00:00 git:wrapper
      01 mkdir -p /tmp
    ✔ 01 admin@web2.local 0.100s
    ✔ 01 admin@web1.local 0.110s
      Uploading /tmp/git-ssh-4fc0da4b8ff9f2e8af0a.sh 100.0%
...
00:00 git:check
      01 git ls-remote http://controller.local:8000/demo-app.git HEAD
      01 7dd8661a9547f2b51b927db290a9499acd8faa93	HEAD
    ✔ 01 admin@web2.local 0.060s
    ✔ 01 admin@web1.local 0.063s
00:00 deploy:check:directories
      01 mkdir -p /var/www/demo-app/shared /var/www/demo-app/releases
    ✔ 01 admin@web2.local 0.007s
    ✔ 01 admin@web1.local 0.007s
00:00 deploy:check:linked_dirs
    ✔ 01 admin@web1.local 0.011s
    ✔ 01 admin@web2.local 0.012s
00:00 deploy:check:make_linked_dirs
      01 mkdir -p /var/www/demo-app/shared/config

依次检查 git wrapper 上传、仓库可达、shared/releases 目录、linked_dirs 与 linked_files 实体是否存在。新服务器首次接入时必跑。

7.3 cap <stage> git:check:只验仓库可达性

cap production git:check

实测回显(节选):

00:00 git:check
      01 git ls-remote http://controller.local:8000/demo-app.git HEAD
      01 7dd8661a9547f2b51b927db290a9499acd8faa93	HEAD
    ✔ 01 admin@web2.local 0.061s
      01 7dd8661a9547f2b51b927db290a9499acd8faa93	HEAD
    ✔ 01 admin@web1.local 0.064s

7.4 cap <stage> deploy:rollback:一键回滚

把 current 软链指回上一个 release,并把被回滚的 release 打包归档后删除。实测(v2 部署出错后回滚到 v1):

cap production deploy:rollback

实测回显(节选核心段):

00:00 deploy:symlink:release
      01 ln -s /var/www/demo-app/releases/20261027091548 /var/www/demo-app/releases/current
    ✔ 01 admin@web1.local 0.007s
      02 mv /var/www/demo-app/releases/current /var/www/demo-app
    ✔ 01 admin@web2.local 0.008s
    ✔ 02 admin@web2.local 0.005s
    ✔ 02 admin@web1.local 0.007s
00:00 deploy:cleanup_rollback
      01 tar -czf /var/www/demo-app/rolled-back-release-20261027091620.tar.gz /var/www/demo-app/releases/20261027091620
      01 tar: Removing leading `/' from member names
      01 tar: Removing leading `/' from member names
    ✔ 01 admin@web1.local 0.006s
      02 rm -rf /var/www/demo-app/releases/20261027091620
    ✔ 01 admin@web2.local 0.007s
    ✔ 02 admin@web1.local 0.006s
    ✔ 02 admin@web2.local 0.005s
00:00 deploy:log_revision
      01 echo " rolled back to release 20261027091548" >> /var/www/demo-app/revisions.log
    ✔ 01 admin@web2.local 0.007s
    ✔ 01 admin@web1.local 0.008s

回滚后 web1 验证:cat /var/www/demo-app/current/index.html → <h1>Hello Capistrano v1</h1>;目录里多了归档包 rolled-back-release-20261027091620.tar.gz;revisions.log 追加一行 rolled back to release 20261027091548。注意回滚只切软链,不重新执行迁移回退——有数据库迁移的项目需自建 before "deploy:reverting", ... 钩子处理。

7.5 cap <stage> deploy:cleanup:清理旧 release

deploy 末尾会自动清理(按 keep_releases),也可手动跑:

cap production deploy:cleanup

实测回显:

00:00 deploy:cleanup
      Keeping 3 of 3 deployed releases on web2.local
      Keeping 3 of 3 deployed releases on web1.local
      No old releases (keeping newest 3) on web2.local
      No old releases (keeping newest 3) on web1.local

release 数未超上限时不删任何东西;超限时的真实清理动作(历史实测):

00:00 deploy:cleanup
      Keeping 3 of 4 deployed releases on web1.local
      Keeping 3 of 3 deployed releases on web2.local
      01 rm -rf /var/www/demo-app/releases/20261027091548

八、执行控制类选项

8.1 --dry-run:不碰服务器的预演

cap production deploy --dry-run

实测回显(节选):只打印「将要执行的命令」,不真正下发(注意 echo "" > REVISION 这类取值为空——因为 dry-run 不执行前面的取值命令):

00:00 git:wrapper
      01 mkdir -p /tmp
      02 #<StringIO:0x000059ca2985e088> /tmp/git-ssh-a59ae6fe0b0bd1ef5b81.sh
      04 chmod 700 /tmp/git-ssh-a59ae6fe0b0bd1ef5b81.sh
00:00 git:check
      01 git ls-remote http://controller.local:8000/demo-app.git HEAD
00:00 deploy:check:directories
      01 mkdir -p /var/www/demo-app/shared /var/www/demo-app/releases
...
00:00 deploy:set_current_revision
      01 echo "" > REVISION

改完 deploy.rb 后先 dry-run 再过真刀,是安全发布的标准动作。

8.2 -z 按主机过滤:灰度单机发布

cap production deploy -z web1.local

实测回显(节选,全程只出现 web1):

00:00 git:wrapper
    ✔ 01 admin@web1.local 0.103s
    ✔ 02 admin@web1.local 0.005s
00:00 git:check
    ✔ 01 admin@web1.local 0.053s
00:00 deploy:check:directories
    ✔ 01 admin@web1.local 0.005s
...
00:00 deploy:set_current_revision
    ✔ 01 admin@web1.local 0.005s

先发布单台验证、没问题再全量,是最朴素的灰度发布手段。多台用逗号:-z web1.local,web2.local。

8.3 -r 按角色过滤

cap production -r app app:show_revision

实测回显:

00:00 app:show_revision
      0f135f586e7f5b1df8fbd7f7f7343471c0bcf313
      0f135f586e7f5b1df8fbd7f7f7343471c0bcf313

本文两台机同为 app+web 所以输出两行;角色拆分的环境(app/web/db 分机)里 -r web 就只落 web 组。

8.4 -t / --trace:调用链追踪

任务报错时 cap production deploy -t 输出 Rake 完整调用链与 Ruby 堆栈(backtrace),配合 log/capistrano.log(由 :format_options 的 log_file 生成)定位失败步骤。

8.5 -j:任务并行度

-j NUMBER 控制 Rake multitask 并行上限(默认 CPU 核数 + 4)。注意它控制的是本地任务调度并行度;SSH 并发连接上限由 :git_max_concurrent_connections(默认 10)控制。

九、诊断类命令

9.1 cap <stage> doctor:排障报告

cap production doctor

输出四段:Environment(Ruby/Rubygems/Bundler/命令行)、Gems(capistrano 及依赖版本,含 update 提示)、Variables(全部变量最终值)、Servers(生效服务器与角色)。完整实测回显见《Capistrano 3.20 配置参数详解》 3.2 节。也可分段查看:cap production doctor:variables、cap production doctor:servers、cap production doctor:gems、cap production doctor:environment。

9.2 -p / --print-config-variables

cap production -p deploy 在跑任务前先把已定义变量打印出来,效果与 doctor:variables 类似但随任务一起执行。

十、注意事项

  1. 必须在项目目录内执行:cap 向上查找 Capfile,不在项目内会报 Capfile not found(可用 -N/--no-search 关闭向上查找)。
  2. stage 参数不可省略(除 install/-T 等少数):cap deploy 会报 stage 未设置;一律 cap <stage> <task>。
  3. 命令在目标机上以部署用户执行:回显里的 admin@web1.local 即执行身份,权限问题(如 /var/www 不可写)会在对应步骤以 ✘ 红字标出。
  4. dry-run 的变量为空属正常现象:它不执行前置命令,依赖前序输出的变量(如 revision SHA)显示为空字符串,不代表真实部署会出错。
  5. 回滚不回数据库:deploy:rollback 只切换软链与归档目录,涉及数据库结构变更的应用要自建回滚钩子。
  6. 日志两份:终端是 airbrussh 格式化输出,完整 DEBUG 级日志在项目 log/capistrano.log。

十一、常见问题

Q1:cap production deploy 报 ERROR linked file ... does not exist on <host>?

目标机 shared 下缺 linked_files 实体。逐台补建后重跑;首次接入新机先 cap production deploy:check 预检。真实报错与修复见《Capistrano 3.20 配置参数详解》 5.3 节。

Q2:部署卡在 SSH 主机确认或权限拒绝?

首次连接新主机时 host key 未入库会交互等待(CI 里表现为卡死)。设 set :ssh_options, { verify_host_key: :never } 或先 ssh-keyscan 入库;权限拒绝检查部署账号密钥与 auth_methods。

Q3:想看看某任务到底做了什么但不执行?

cap -D <task> 看描述、cap -P <task> 看依赖链、cap <stage> <task> --dry-run 看将执行的命令,三者组合即可不碰服务器摸清任务行为。

Q4:多 stage 项目如何互不影响?

每个 stage 独立 config/deploy/<stage>.rb;命令显式带 stage:cap staging deploy、cap production deploy,各自的 deploy_to/服务器清单互不干扰。

Q5:部署者署名(revisions.log 的 by 字段)为空?

local_user 默认取 ENV['USER'],非登录 shell 下为空。设 set :local_user, "admin" 后实测署名正常(修复前后对比见《Capistrano 3.20 配置参数详解》七、Q1)。

十二、参考链接