GitHub Actions から特定のサーバに SSH 接続してデプロイ作業を行う
Cloudflare Pages や Netlify、Vercel などであれば、GitHub 連携で自動的にデプロイができるが、IaaS にデプロイしてあるシステムを GitHub Actions から更新するのはさすがに無理か…?
と思ったら、GitHub Actions から SSH 接続できる Actions があった。
↑ のサンプルコードを見る限り、複数行のスクリプトも実行できるようだ。自分はとりあえず以下のように全て Secrets にしておいた。
.github/workflows/deploy-ssh.yaml
name: Deploy SSH
on:
push:
branches:
- main
workflow_dispatch:
jobs:
deploy-ssh:
runs-on: ubuntu-latest
steps:
- name: Executing Remote SSH Commands Using SSH Key
uses: appleboy/ssh-action@v1.0.3
with:
host : ${{ secrets.SSH_HOST }}
port : ${{ secrets.SSH_PORT }}
username: ${{ secrets.SSH_USERNAME }}
key : ${{ secrets.SSH_KEY }}
script : ${{ secrets.SSH_SCRIPT }}
仮に平文で書いたとしたら、こんな感じになるようにした。
- name: Executing Remote SSH Commands Using SSH Key
uses: appleboy/ssh-action@v1.0.3
with:
host : 140.0.0.0 # Public IP
port : 22
username: admin
key : ${{ secrets.SSH_KEY }} # ← SSH 秘密鍵の文字列
script : |
whoami
pwd
ls -la
bash ./deploy-script.bash
script
の中に具体的なデプロイ用のコマンドを書いていくのではなくて、SSH 先に既に格納してある deploy-script.bash
を叩くだけ、という風にしておいた。万が一 Secrets が漏れた時も「なんかスクリプトファイルを実行してるんだな」というところまでしか分からないようにしたかったので。
そんな deploy-script.bash
の中では、次のように nohup
・&
コマンドでバックグラウンド起動しておきたいウェブサーバがあった。
nohup node ./dist/main.js &
しかし、前述のように SSH 経由でスクリプトを実行すると、この行でバックグラウンド起動したはずのプロセスの出力が延々と続いてしまい、GitHub Actions が完了しなくなってしまった。
どうも標準出力だけでなく標準エラー出力も決めたファイルに逃がすように明記してあげないと、こういう呼び出し方の場合は詰まってしまうみたい。以下のようにすれば回避できた。
nohup node ./dist/main.js > ./nohup.out 2>&1 &
ついでに、nohup
・&
でバックグラウンド起動したプロセスの ID (PID) は、$ echo $!
で取得できることが分かった。つまり、
nohup node ./dist/main.js > ./nohup.out 2>&1 &
echo $! > ./pid.txt
こんな風に pid.txt
に PID を書き出しておけば、後でバックグラウンドプロセスを終了したくなった時に $ ps aux | grep node
なんてプロセス ID を調べたりせずとも、
kill "$(cat ./pid.txt)"
rm ./pid.txt
で簡単に kill
もできるというワケである。
色々と Bash の細かな挙動も知れて楽しかった。