実現したいこと
Docker環境のsqlを、コンテナの外であるWSL2のUbuntu内のディレクトリに定期バックアップしたいです。
前提
・WSL2環境
・Dockerを利用
シェルスクリプトを手動で実行するとうまく動作するのですが、
シェルスクリプトをcronから呼び出すと、ファイルのタイムスタンプが更新されません。
平たく言うと、中身が更新されていません。
発生している問題・エラーメッセージ
18:30に/bin/bash /usr/local/bin/database-backup.sh
を手動で実行しました。
シェルスクリプトの中身は下記です。
sh
1#!/bin/bash 2export PATH=/usr/local/bin:$PATH 3 4#目的のディレクトリへ移動 5cd ${projectDirectory} 6 7#sqlのデータをコンテナ内の/tmpに書き出し 8/usr/bin/docker-compose exec -T db bash -c 'mysqldump --no-tablespaces -u hogehoge -phogehoge laravel_local > /tmp/dump.sql' 9 10#コンテナ内に書き出したデータを、コンテナ外にコピー 11docker cp `docker-compose ps -q db`:/tmp/dump.sql ${backupDirectory}/sql/backup_`date +%Y%m%d%H%M`.sql
18:30のタイムスタンプでbackup_202303051830.sql
というファイルが、
コンテナの外である\\wsl.localhost\Ubuntu\tmp\backup\sql
に無事生成されました。
しかし、このスクリプトをcrondから実行すると、タイムスタンプが過去の時間で中身の更新されていないデータが生成されてしまいます。(上記スクショ参照)
cronは下記のファイルで実行しいます。
/etc/cron.d/ubuntu
cron
1* * * * * root /bin/bash /usr/local/bin/database-backup.sh >> /var/log/cron.log 2>&1
試したこと1
ログを確認しましたが、データベースの接続情報をハードコーディングしないほうがいいぞ、って警告が出てくるだけです。
cat /var/log/cron.log
log
1mysqldump: [Warning] Using a password on the command line interface can be insecure.
これは普段成功するときも出ます。
手動でシェルスクリプトを呼び出したときは正しく動作するのに、
cronで呼び出すと、
#sqlのデータをコンテナ内の/tmpに書き出し /usr/bin/docker-compose exec -T db bash -c 'mysqldump --no-tablespaces -u hogehoge -phogehoge laravel_local > /tmp/dump.sql'
だけがうまく実行できていないように思えます。
↓
勘違いでした。追記します。
試したこと2(追記)
最後の行
docker cp `docker-compose ps -q db`:/tmp/dump.sql ${backupDirectory}/sql/backup_`date +%Y%m%d%H%M`.sql
のコマンドをフルパスにしたら意図通りの動きになりました。
↓
/usr/bin/docker cp `docker-compose ps -q db`:/tmp/dump.sql ${backupDirectory}/sql/backup_`date +%Y%m%d%H%M`.sql
sh
1#!/bin/bash 2 3projectDirectory=/root/crm-systrem 4backupDirectory=/tmp/backup 5 6export PATH=/usr/local/bin:$PATH 7cd ${projectDirectory} 8/usr/bin/docker-compose exec -T db bash -c 'mysqldump --no-tablespaces -u hogehoge -phogehoge laravel_local > /tmp/dump.sql' 9/usr/bin/docker cp `docker-compose ps -q db`:/tmp/dump.sql ${backupDirectory}/sql/backup_`date +%Y%m%d%H%M`.sql
てっきり下から2行目のコマンド(コンテナ内にいったんバックアップを書き出す)がうまくいっていないとばかり思ってましたがそうではなったということになりますよね。
ただ、これだとotnさんがおっしゃるように
/usr/local/bin/dockerが別物として存在することになりますね。
which docker
コマンドで調べると、/usr/bin/docker
との結果が返ってきました。
export PATH=/usr/local/bin:$PATH
をシェルスクリプト冒頭で宣言していて、フルパスじゃない状態でも違う挙動で動いたので、dockerコマンドが2つあるってことですよね。
ちょっとこれが何者なのかはまだわかりません。
よって根本解決とは言えないので、「未解決」に戻しました。
試したこと3(追記)
/usr/bin/docker
と/usr/local/bin/docker
のバージョン確認
bash
1# /usr/bin/docker -v 2Docker version 23.0.1, build a5ee5b1 3 4# /usr/local/bin/docker -v 5-bash: /usr/local/bin/docker: No such file or directory 6 7#ls /usr/local/bin/ 8database-backup.sh
確認方法があっているかわかりませんが、/usr/local/bin/docker
なんて元々いないんじゃ・・・
/usr/local/bin/
には該当のシェルスクリプトがあるだけでした。
これは憶測ですが、WSL2環境なのでWindows側にインストールされているDocker Desktopを参照しようとしたのか?
などとも考えています。
ほぼ同じ方法でgit cloneした別環境ではどうなのか、日をまたぎますが試そうと思います。
今回cronで実行しているシェルスクリプトであるdatabase-backup.sh
末尾に
sh
1echo "job done" 2docker -v 3/usr/bin/docker -v
の3行を追加してみました。
↓結果
bash
1cat /var/log/cron.log 2echo "job done" 3Docker version 23.0.1, build a5ee5b1 4Docker version 23.0.1, build a5ee5b1
「2つのdockerコマンドが独立していてそれぞれのバージョンが異なる」とかはちょっと考えづらいかな?
って感想です。
そもそもdockerコマンドがフルパスかどうかで実行されるコマンドが違うなら、
「cronではなく手動で実行した時には意図した動作をしていた」ことの説明がつかない気がしてきました。
補足情報(FW/ツールのバージョンなど)
- Laravel8
- Docker
- docker-compose
- WSL2
- Ubuntu


