Bitbucket Pipelines Inappropriate ioctl for device error 使用 Capistrano

Bitbucket Pipelines Inappropriate ioctl for device error using Capistrano

我有一个带有 Rails 应用程序的 DigitalOcean Droplet,我想在其中通过 Pipelines 和 Capistrano 自动部署。

这是我的 Capfile:

# Load DSL and set up stages
require "capistrano/setup"

# Include default deployment tasks
require "capistrano/deploy"

# Load the SCM plugin appropriate to your project:
#
# require "capistrano/scm/hg"
# install_plugin Capistrano::SCM::Hg
# or
# require "capistrano/scm/svn"
# install_plugin Capistrano::SCM::Svn
# or
require "capistrano/scm/git"
install_plugin Capistrano::SCM::Git

# Include tasks from other gems included in your Gemfile
#
# For documentation on these, see for example:
#
#   https://github.com/capistrano/rvm
#   https://github.com/capistrano/rbenv
#   https://github.com/capistrano/chruby
#   https://github.com/capistrano/bundler
#   https://github.com/capistrano/rails
#   https://github.com/capistrano/passenger
#
# require "capistrano/rvm"
# require "capistrano/rbenv"
# require "capistrano/chruby"
# require "capistrano/bundler"
require "capistrano/apache/systemd"
require "capistrano/rails"
# require "capistrano/rails/migrations"
# require "capistrano/passenger"

# Load custom tasks from `lib/capistrano/tasks` if you have any defined
Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }

deploy.rb:

# config valid for current version and patch releases of Capistrano
lock "~> 3.11.0"

server "xx.xx.xx.xx", port: 22, roles: [:web, :app, :db], primary: true

set :application, "myapp"
set :repo_url, "git@bitbucket.org:user/repo.git"
set :user, "deployuser"

# Default branch is :master
# ask :branch, `git rev-parse --abbrev-ref HEAD`.chomp

# Default deploy_to directory is /var/www/my_app_name
set :deploy_to, "customdir"

# Default value for :format is :airbrussh.
# set :format, :airbrussh

# You can configure the Airbrussh format using :format_options.
# These are the defaults.
# set :format_options, command_output: true, log_file: "log/capistrano.log", color: :auto, truncate: :auto

# Default value for :pty is false
# set :pty, true

# Default value for :linked_files is []
# append :linked_files, "config/database.yml"

# Default value for linked_dirs is []
# append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "public/system"

# Default value for default_env is {}
# set :default_env, { path: "/opt/ruby/bin:$PATH" }

# Default value for local_user is ENV['USER']
# set :local_user, -> { `git config user.name`.chomp }

# Default value for keep_releases is 5
# set :keep_releases, 5

# Uncomment the following to require manually verifying the host key before first deploy.
# set :ssh_options, verify_host_key: :secure
#

namespace :deploy do
  desc "Make sure local git is in sync with remote."
  task :check_revision do
    on roles(:app) do
      unless `git rev-parse HEAD` == `git rev-parse origin/master`
        puts "WARNING: HEAD is not the same as origin/master"
        puts "Run `git push` to sync changes."
        exit
      end
    end
  end

  desc 'Restart application'
  task :restart do
    on roles(:app), in: :sequence, wait: 5 do
      invoke 'apache:reload'
    end
  end

  before :starting, :check_revision
  after  :finishing, :compile_assets
  after :finishing, :restart
  after :rollback, :restart
end

bitbucket-pipelines.yml:

image: ruby:2.5.3

pipelines:
  default:
    - step:
        script: # Modify the commands below to build your repository.
          - apt-get update -y
          - apt-get install -y build-essential git-core curl nodejs default-libmysqlclient-dev ssh
          - gem install bundler
          - bundle install
          - bundle exec cap production deploy

我在设置 -> 管道 -> SSH 密钥下创建了一个 SSH,并将其添加到 deploy.rb 上指定的 deployuser 下的 droplet 中的 authorized_keys 文件中。当我 运行 管道时,这是日志跟踪:

+ bundle exec cap production deploy
00:00 git:wrapper
      01 mkdir -p /tmp
#<Thread:0x000055ed4cf70528@/usr/local/bundle/gems/sshkit-1.18.2/lib/sshkit/runners/parallel.rb:10 run> terminated with exception (report_on_exception is true):
/usr/local/bundle/gems/sshkit-1.18.2/lib/sshkit/runners/parallel.rb:15:in `rescue in block (2 levels) in execute': Exception while executing on host xx.xx.xx.xx: Inappropriate ioctl for device (SSHKit::Runner::ExecuteError)
    from /usr/local/bundle/gems/sshkit-1.18.2/lib/sshkit/runners/parallel.rb:11:in `block (2 levels) in execute'
(Backtrace restricted to imported tasks)
cap aborted!
SSHKit::Runner::ExecuteError: Exception while executing on host xx.xx.xx.xx: Inappropriate ioctl for device
Caused by:
Errno::ENOTTY: Inappropriate ioctl for device
Tasks: TOP => deploy:check => git:check => git:wrapper
(See full trace by running task with --trace)
The deploy has failed with an error: Exception while executing on host xx.xx.xx.xx: Inappropriate ioctl for device
** DEPLOY FAILED
** Refer to log/capistrano.log for details. Here are the last 20 lines:
# Logfile created on 2019-05-30 00:35:51 +0000 by logger.rb/61378
  INFO ---------------------------------------------------------------------------
  INFO START 2019-05-30 00:35:51 +0000 cap production deploy
  INFO ---------------------------------------------------------------------------
  INFO [5548bb68] Running /usr/bin/env mkdir -p /tmp on 142.93.227.140
 DEBUG [5548bb68] Command: /usr/bin/env mkdir -p /tmp
@xx.xx.xx.xx's password:

我不确定最后一行是否与正在发生的事情有关。我打算使部署无密码且尽可能简单。

更新:

我尝试将 ssh -T deployUser@xx.xx.xx.xx 添加到脚本步骤中。好像没什么问题:

ssh -T deployUser@xx.xx.xx.xx
Welcome to Ubuntu 18.04.2 LTS (GNU/Linux 4.15.0-50-generic x86_64)
 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage
  System information as of Fri May 31 02:14:16 UTC 2019
  System load:  0.01               Processes:           140
  Usage of /:   19.7% of 24.06GB   Users logged in:     1
  Memory usage: 74%                IP address for eth0: xx.xx.xx.xx
  Swap usage:   0%
  Get cloud support with Ubuntu Advantage Cloud Guest:
    http://www.ubuntu.com/business/services/cloud
 * Canonical Livepatch is available for installation.
   - Reduce system reboots and improve kernel security. Activate at:
     https://ubuntu.com/livepatch
1 package can be updated.
0 updates are security updates.
The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

回到基础。我关闭了 Bitbucket 上的 Pipelines 并尝试在本地 运行 cap production deploy 指向远程服务器。事实证明它确实在不应该的时候要求输入密码,而且它没有与正确的用户进行 SSH,所以 a) 只向 deployUser 的 authorized_keys 文件添加了必要的密钥 b) 修改了 deploy.rb 像这样:

lock "~> 3.11.0"
set :user, "deployUser" # Notice that set user was moved here so it can be fetched later

server "xx.xx.xx.xx", user: fetch(:user), port: 22, roles: [:app], primary: true

set :application, "my_app"
set :repo_url, "my_git_repo"
set :rvm_type, :system
set :rvm_ruby_version, '2.5.3'

set :bundle_jobs, 2 # Small modification so it doesn't eat up the Droplet's memory

我又遇到了一个错误,但这是一个需要更多谷歌搜索的问题:)