Jenkins から別サーバに SSH 接続してファイル転送する

Jenkins が動作しているサーバから別のサーバに SSH 接続して、指定のディレクトリに指定の資材を配置するジョブを作ってみる。

SSH でファイル転送するジョブを作る際は、「Publish Over SSH」というプラグインを使うと、環境設定などを Jenkins 上に持たせられて便利。つい最近パイプライン記法にも対応したので、より使いやすくなるだろう。

では、手順を紹介。

  1. 「Publish Over SSH」プラグインを導入すると、「システムの設定」の中に「Publish Over SSH」という項目が増える。ココに、接続先サーバの認証情報を定義しておく。
  2. Name : 自由に決める
  3. Hostname : 接続先ホスト名 (IP アドレス)
  4. Username : 接続先のユーザ名
  5. Remote Directory : 接続後、自動的に移動するディレクトリ
  6. 「Use password authentication, or use a different key」にチェックを付ける
  7. Passphrase / Password : 接続先のパスワードを指定する
  8. その他、「Port」は「22」などデフォルト設定のままで良いだろう。
  9. 新規ジョブを作る。パイプラインでも、通常の「フリースタイル・プロジェクトのビルド」ジョブでも良い。
    対象のプロジェクトをチェックアウトしてビルドし、転送するファイルを用意しておく。
  10. パイプラインの場合は Pipeline Syntax ページより「sshPublisher: Send build artifacts over SSH」を選ぶ。
    通常のジョブの場合は、ビルドの中で「Send files or execute commands over SSH」を選び、以下のように設定する。
    • Name : 「システムの設定」画面で定義したサーバを選択する。
    • Source files : 転送するファイルを指定する。Glob 形式で書けるので、例えば dist/**/* といった形で dist/ ディレクトリ内の全てのファイルを転送対象に指定できる。
    • Remove prefix : 転送時に除去するディレクトリ構成。 例えば「Source files」を dist/my-app/**/* と指定したが、転送先はディレクトリ直下に my-app/ 配下のファイルを配置したい、という時は、この「Remove prefix」に dist/my-app と入れておくことで、階層を上げられる。
    • Remote directory : 転送先ディレクトリ。「システムの設定」の「Remote directory」で指定したディレクトリからのパスになる。 例えば、システム設定の方で /var/www/ と指定し、この項目で my-app/assets と指定下とすると、資材は /var/www/my-app/assets/ 配下に格納されることになる。
    • Exec command : ファイル転送後、転送先サーバで実行したいコマンドがあれば指定できる。 例えばファイルを転送した後でリネームしたかったりする場合はココで mv コマンドを指定するなど。
    • 「Source files」「Remove prefix」指定なしで、「Exec command」だけを指定する = SSH 接続先サーバで任意のコマンドを実行するだけ、といった使い方も可能。
  11. Pipeline Syntax の場合は「Generate Pipeline Script」ボタンを押下すると、以下のようなコードが生成できるので、コレを Jenkinsfile に組み込む。
sshPublisher(
  publishers: [
    sshPublisherDesc(
      configName: '対象サーバ',
      transfers: [
        sshTransfer(
          excludes: '',
          execCommand: '【実行コマンドを指定した場合はココに入る】',
          execTimeout: 120000,
          flatten: false,
          makeEmptyDirs: false,
          noDefaultExcludes: false,
          patternSeparator: '[, ]+',
          remoteDirectory: '【リモートディレクトリの指定】',
          remoteDirectorySDF: false,
          removePrefix: '【除去するディレクトリパスの指定】',
          sourceFiles: '【転送対象ファイルの指定】'
        )
      ],
      usePromotionTimestamp: false,
      useWorkspaceInPromotion: false,
      verbose: false
    )
  ]
)

これで完了。

通常のシェルで SSH 接続するジョブを作るとなると、Jenkins サーバ上の ssh コマンドの特性を考慮してスクリプトを組む必要があり面倒だが、このプラグインならサクッと SSH 接続できるようになるのでとてもお手軽だ。