質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
cron

cronは、Unix系OS上でデーモンプロセスとして動作する、スクリプトの自動実行が可能なジョブスケジューラです。

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

Ubuntu

Ubuntuは、Debian GNU/Linuxを基盤としたフリーのオペレーティングシステムです。

Docker

Dockerは、Docker社が開発したオープンソースのコンテナー管理ソフトウェアの1つです

Q&A

2回答

1508閲覧

シェルスクリプト実行時に、dockerコマンドをフルパスで書いたときとそうでないときで挙動が異なる

bokupiroki

総合スコア54

cron

cronは、Unix系OS上でデーモンプロセスとして動作する、スクリプトの自動実行が可能なジョブスケジューラです。

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

Ubuntu

Ubuntuは、Debian GNU/Linuxを基盤としたフリーのオペレーティングシステムです。

Docker

Dockerは、Docker社が開発したオープンソースのコンテナー管理ソフトウェアの1つです

1グッド

0クリップ

投稿2023/03/05 10:01

編集2023/03/05 15:47

実現したいこと

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
dameo👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

melian

2023/03/05 10:13

docker-compose exec に -T オプション(pseudo terminal の割当の無効化) を付けてみてください。 /usr/bin/docker-compose exec -T ...
bokupiroki

2023/03/05 10:22

ありがとうございます。質問を更新しました。
dameo

2023/03/05 10:50

このdocker-composeは一体どこのdocker-compose.ymlを探したんだろう…
bokupiroki

2023/03/05 12:38

dameoさん コメントありがとうございます。 ubuntuでいうところの /root/crm-system/docker-compose.yml という階層になっています。 意図した答えになっていなければ申し訳ありません。
dameo

2023/03/05 12:53

あ、こちらこそすみません。そもそもスクリプトにしてcdしてたんですね。 docker-composeってカレントディレクトリにyamlが見つからないと上へ上へディレクトリを登っていくので、cronだと環境変数が違うので、yamlもフルパスで指定した方がいいんじゃないかと思って指摘した次第です(ファイル関連はフルパス指定の癖がついてます)。 cdあるならいらなそうですね。
guest

回答2

0

最後の行
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行目のコマンド(コンテナ内にいったんバックアップを書き出す)がうまくいっていないとばかり思ってましたが盲点でした。

投稿2023/03/05 10:42

bokupiroki

総合スコア54

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

otn

2023/03/05 10:51

> てっきり下から2行目のコマンド(コンテナ内にいったんバックアップを書き出す)がうまくいっていないとばかり思ってましたが盲点でした。 それを確認するために /tmp/dump.sql を見るべきでしたね。 見ていれば、 > 「/tmp/dump.sql の中身が意図通りで無い」という意図で正しいです。 という誤った判断をする事も無かった。 1ステップずつ確認しましょう。
otn

2023/03/05 11:21 編集

> のコマンドをフルパスにしたら正常にバックアップ取れました!! export PATH=/usr/local/bin:$PATH の状態で、 /usr/bin/docker cp ~~ と docker cp ~~ で、動作が異なると言うことは、 /usr/local/bin/dockerが別物として存在することになります。 それはちょっと危険な気がしますが、何者であるか、把握していますか?
bokupiroki

2023/03/05 12:30

確かにそうですね。 which dockerコマンドで調べて解決した気になっていました。 引き続き調査します。
bokupiroki

2023/03/05 12:58

根本的なことがわかっておらず申し訳ありません。 そもそも「同じコマンドが複数、別々の場所にインストールされる」なんてことは、linuxては一般的に起こりえることなんでしょうか。 インストール方法がよくなかった とかそういうことなんでしょうか・・・
otn

2023/03/05 13:25 編集

> そもそも「同じコマンドが複数、別々の場所にインストールされる」なんてことは、linuxては一般的に起こりえることなんでしょうか。 OS標準のパッケージ管理ツール(yumとかdnfとかaptとか)でインストールしている限り、そういう事は無いです。 人が直接実行するようなコマンドは/usr/bin /usr/sbin などにインストールされます。 それ以外の方法では、どこにでもインストール出来ますので、どこに何をインストールしたかは自分で管理します。 ・ソースをダウンロードして自分でコンパイルしてインストール ・git cloneして自分でインストール ・何かダウンロードして、インストールスクリプトを実行 ・などなど 標準のパッケージ管理ツールと競合しないように、/usr/bin /usr/sbin 以外にインストールするのが普通です。 古典的には/usr/local/bin や /opt/hogehoge とか、あるいは $HOME/hogehoge とか。 anacondaやpyenv等を使って、pythonを沢山インストールして、pythonコマンドで実行されるものが一体何者なのか把握できなくなった人の質問が多数出ていますね。 何をどこにどうやってインストールしたかは、記憶するか、記録するかどちらかが必須です。
guest

0

ログファイルに書かれたエラーメッセージ が、

the input device is not a TTY

ということなので、
/usr/bin/docker-compose exec -T ~~
と、-Tオプションを付ければ良いのではないでしょうか。

https://manpages.org/docker-compose

-T Disable pseudo tty allocation. By default a tty is allocated.

投稿2023/03/05 10:23

otn

総合スコア84533

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

bokupiroki

2023/03/05 10:27 編集

ありがとうございます。 付けてみたのですが、解決につながりそうなログは取得できませんでした。 結果も投稿に反映させました。
otn

2023/03/05 10:40

メッセージから見ると、mysqldump コマンドは正常終了してます。 /tmp/dump.sql の中身が意図通りで無いと言うことでしょうか? (あるいは、/tmp/dump.sql を確認していない??)
bokupiroki

2023/03/05 10:43 編集

「/tmp/dump.sql の中身が意図通りで無い」という意図で正しいです。 自分で回答を書きましたが、解決しました。 ありがとうございました。
bokupiroki

2023/03/05 12:45

コマンドをフルパスで書いたら思い通りの動作になったが「/tmp/dump.sql の中身が意図通りで無い」というのは勘違いであることが発覚したため、追記しました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問