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

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

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

CentOSは、主にRed Hat Enterprise Linux(RHEL)をベースにした、フリーのソフトウェアオペレーティングシステムです。

シェルスクリプト

シェルスクリプトは、UNIX系のOSもしくはコマンドラインインタプリタ向けに記述されたスクリプト。bash/zshといったシェルによって実行されるため、このように呼ばれています。バッチ処理などに使用されており、テキストファイルに書かれた命令を順に実行します。

Q&A

1回答

2481閲覧

inotifyを用いた「フォルダに変更があったら1度だけコマンドを実行する」シェルスクリプトについて

ousia

総合スコア10

CentOS

CentOSは、主にRed Hat Enterprise Linux(RHEL)をベースにした、フリーのソフトウェアオペレーティングシステムです。

シェルスクリプト

シェルスクリプトは、UNIX系のOSもしくはコマンドラインインタプリタ向けに記述されたスクリプト。bash/zshといったシェルによって実行されるため、このように呼ばれています。バッチ処理などに使用されており、テキストファイルに書かれた命令を順に実行します。

0グッド

1クリップ

投稿2019/04/25 01:08

編集2019/04/25 01:09

前提・実現したいこと

inotifyというlinuxのツールを使い、特定フォルダの中に何か変更があった際、すべての変更が完了したら
特定のコマンドを実行するという処理を書きたい。

例えば
/data/app フォルダの中で

/data/app/test1
/data/app/test2
/data/app/test3

というフォルダを別のところからコピーしてきた際に、3つが完全にコピーが終わったときに(appフォルダ内の処理がすべて終わった際)
コマンドを実行したいです。

それぞれtest1,2,3には大量の画像などがはいっているので、イベントが始まった瞬間に実行されると困る。

該当のソースコード

watch-file.sh /data/app "echo"
これで/data/app を監視スタートし、watch-file.shの中は下記になります。

WATCH_DIR=$1 # 監視するディレクトリ COMMAND=$2 # ファイル更新時に実行するコマンド inotifywait -e CLOSE_WRITE -m -r ${WATCH_DIR} --format "%w %f %e" | \ while read LINE; do ${COMMAND} "コピー完了" done

試したこと

whileの1回目でbreakをはさんでみたが、うまくいかなかったです。

補足情報(FW/ツールのバージョンなど)

centos 6
inotify

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

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

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

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

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

otn

2019/04/25 02:02

「3つが完全にコピーが終わった」とは、具体的にどういう条件ですか? 何か、コピーが終わったときにコピーした人から通知される?
ousia

2019/04/25 03:27

うまく説明ができなくてすいません。 /data/app/test1 /data/app/test2 /data/app/test3 にそれぞれ100枚の画像が入っているとしますね。 それを /data/app/に移動とかコピーするんですね。 で、そのそれぞれ100枚の画像の名前を取得するというシェルスクリプト自体はできているので、それを実行させたいんですよ。 ただ、ディレクトリtest1,test2,test3がコピーされた瞬間にコマンドが実行されてしまうと まだtest1のなかに100枚無い状態(コピー中)にコマンドが始まってしまうので、すべての画像名が取得できないというのが困っている点なんです。 私の言うコピーというのは単純に「右クリックの貼り付ける」を想定してもらえれば大丈夫です。 windowsからsamba経由でlinux上にある[data/app]フォルダに、フォルダをコピーして、それが完了したら上記のコマンドを実行したいんです。 (すべて完了=3フォルダ内合計300画像が完全にコピーし終えた状態) これで伝わりますか? よろしくお願いします。
otn

2019/04/25 06:30

それは分かっているのですが、「完全にコピーし終えた」とは何で判断するのですか? 別の聞き方をすると、自動化しないで人力でやるとして、コピー完了を待っている人はなにをもって、次の作業をするのですか? 100と個数が決まっていてカウントするのならできます。あるいは、コピー元のディレクトリが分かっていて、そこと同じ数になれば終わりというのも出来ます。
ousia

2019/04/25 06:35

えと、その「終えたら」をどう判断すればいいのか を知りたいのです・・・ そういう風に書いていたつもりなのですが・・・ 数は決まってないです。 213個の時もあれば2この時もあります
ousia

2019/04/25 06:35

人力だとしたら普通に目視で「終わったら」らコマンドを実行してます。 それが手間がかかるので自動化してコマンドを実行したいと思っているんです。 これで伝わりますか?
otn

2019/04/25 06:44 編集

シェルスクリプトの書き方の質問だと思っていたのですが、違うんですね。 要件が決められないとコード化は出来ません。
ousia

2019/04/25 06:46

私はスクリプトの質問のつもりではいるんですが・・・ 違うんですかね? inotifywait -e CLOSE_WRITE -m -r ${WATCH_DIR} --format "%w %f %e" | \ while read LINE; do ${COMMAND} "コピー完了" done ここら辺の話だと思ってます。
ousia

2019/04/25 06:47

分からないなら大丈夫です。 難しいみたいですね・・・
otn

2019/04/25 06:55 編集

> 私はスクリプトの質問のつもりではいるんですが・・・ いや、要件が決めれないという質問になってます。 「どうコード化するか」の質問じゃなくて「何をコード化するか」の質問。
Y.H.

2019/04/25 07:00

>213個の時もあれば2この時もあります > 人力だとしたら普通に目視で「終わったら」 人力でも、事前に「今回は213個」という個数を把握したうえで 「目視で213個ファイルが出来てたら」終わり という判断をするのですよね? shellやスクリプトなどで自動化するにはこの「今回は213個」という個数をパラメーターとして渡す必要があります。でないと何個のファイルができていたら終わりという判断ができません。
Y.H.

2019/04/25 07:40

> マウスで右クリック、「このフォルダをコピー」とかでコピーしたものを貼り付け Windows内でのファイル移動/コピーであっても、スクリプト(BAT/vbscript/powershell)などで、 すべてコピーが終わったことを判断するのは容易ではないと思います。 これが可能であれば、コピー終了後にWindowsからteratermマクロやsshなどでlinuxへ接続し任意のコマンドを実行をするバッチを起動すればいいだけです。
guest

回答1

0

質問がinotifyを使ったシェルスクリプトの書き方の質問じゃなくて、
「コピーの後に別の処理をしたいがどうしたらいいか」
のようなので、その前提で回答します。

監視して実行するのをやめて、

sh

1#!/bin/sh 2 3cd コピー元 4for dir in test1 test2 test3 5do cp -rp $dir /data/app/$dir 6done 7 8コピー完了後に実行したい処理を書く

というシェルスクリプトを作り、コピーに連続して実行します。

#追記
なんと、コピー処理は別PCで行うと言う追加要件があったので、そういう場合にどうしたらいいかという方法です。

案1:
コピー側PCで、コピー終了後に、「コピー終わりましたよ」という名前の空ファイルをコピーする。
受け側では、inotifyで「コピー終わりましたよ」という名前のファイルの作成を監視して、それが出来たら、そのファイルを削除して、後続処理を行う。

案2:
コピー側で、コピー終了後に、受け側サーバーのプロセスを、sshとかTerarmマクロとかで、起動して処理する。
受け側で、ウェブサーバーを起動し、コピー側から後処理CGIのページにアクセスするという手もある。

案3:
コピー側で、コピー実施頻度が低い&コピーするファイルサイズの上限が想定できるという前提であれば、
受け側で、inotifyでファイル作成を検知する毎に、目印ファイルにtouchする。
別途、cronから1分ごととかにチェック処理を走らせ、目印ファイルのタイムスタンプから、最大ファイルサイズのコピー時間以上経っていれば、目印ファイルを削除して、後続処理を行う。

簡単にできるのはこれくらいでしょうか。

投稿2019/04/25 06:49

編集2019/04/25 07:45
otn

総合スコア84538

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

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

ousia

2019/04/25 07:02

すいません、なにか伝わって無い感がすごいです。 cpコマンドでコピーするわけではないんです。 手動で、マウスを使ってコピーした際になんです。 なので監視をしたいんです。 伝わってないみたいなので大丈夫です・・・
ousia

2019/04/25 07:04

otnさんもPCを使うときに、例えばファイルサーバーにwindowsからファイルを移動させるといった経験とかは無いでしょうか? そのときはマウスで右クリック、「このフォルダをコピー」とかでコピーしたものを ファイルサーバー上の特定フォルダに「貼り付け」しますよね? その際に、「コピーが完全に終わったら」をイベントにしたいんです。 これで伝わらないのでしたら説明が難しいです。。。
Y.H.

2019/04/25 07:27

クライアントPC(Windows)でしか把握できない事象(イベント:コピー終わり)を、 サーバー(linux)のshellなどで把握したいということなら、 すべて終わったことをWindowsからLinuxへ何らかの方法で通知し、それをLinuxで受ける以外方法はありません。 Linux側だけでクライアントで発生している事象を把握し判断することは不可能です。
otn

2019/04/25 07:30

GUIでのコピーをやめて、スクリプトでコピーしなさいと言うのが回答でした。 > ファイルサーバーにwindowsからファイルを移動させるといった経験とかは無いでしょうか? これは質問に書いてなかった新しい要件ですね。 回答に、追記しておきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問