解決済みの質問
質問:No.3323703
すぐに回答ほしいです
お気に入り投稿に追加する (0人が追加しました)
回答数13
閲覧数1782
FTPで書き込み中のファイルの完了を知りたい
FTPで書き込み中のファイルがあるとします。そのファイルが、書き込み中なのか、それとも、書き込みが完了したのかを、知りたいのですが、良い方法はありますでしょうか。書き込みファイル名はあらかじめ、わかっています。(書き込み中に読んだ場合、最後まで読み切ることが出来ないために書き込み完了迄待ちます)当方で、調査した限りでは、ファイル名を指定して、そのファイルが、他プロセスによってオープンされているか否かを知るシステムコールは存在しませんでした。OSは、sun solaris10を使用の予定ですが、UNIX系(linux含む)で実現可能であれば、かまいません。
投稿日時 - 2007-09-07 15:11:05
質問者が選んだベストアンサー
回答:No.2
一般のUnix系のOSで、fopen() でチェックできるかどうかは疑問です^^

たしかに、Unix系のOSで、ファイルをオープンしているプロセスがあるかどうかを調べられるような標準的なシステムコールがあるという話は、あまり聞かないですよね。

http://www.mlb.co.jp/linux/mld-ml/200206/msg00028.html ←存在しないのがほんとに真実かどうかは知りませんが^^

ftp の際、get してくるファイルのサイズ情報をどこかに出力しておいて、そのサイズに達したか否かで、「書き込み中か、書き込み完了か」を判定するのがもっともポータブルな方法かと^^

※ 最初に lseek などして、見掛けのサイズを大きくしておいてから rewind して実際に書き込みを始めるみたいなことしてる ftp の実装なんてあるとまずいですけど^^;
投稿日時 - 2007-09-07 21:29:30
この回答を支持する
(現在0人が支持しています)
お礼
ご回答ありがとうございます。やはり、無いと考えたほうが、良さそうでね。求めるシステムコールが、存在しない場合の対策案は、私のほうで、2、3検討済みです。
1案:対象ファイル送信後に、送信完了を示す、別なファイル(サイズ:0)をおくる。読み込み側は、サイズ:0のファイルの出現で、目的ファイルの送信完了を判定。
2案:対象ファイルを別の一時的な名前で書き込み、完了後に正規の名前にリネームする。リネームされて、求めるファイルが出現したときは、既に書き込みが完了されたファイルとなっている。
3案:実際のファイルの内容の最後に、ファイル終端であることを示す、あらかじめ決められた特定の文字列を書き込む。読み込み側は、その文字列まで読めれば、書き込みが完了したファイルと判定する。
などの方法がありますが、いずれもFTPの送信側(書き込み側)にある一定の操作が必要となります。できたら、そのような操作をさせたくなかったので、質問した次第です。
投稿日時 - 2007-09-07 22:05:34
この質問は役に立ちましたか?
4人が「このQ&Aが役に立った」と投票しています
ベストアンサー以外の回答
回答:No.13
xferlog とか サーバーログの確認では、だめなのでしょうか?
投稿日時 - 2007-09-08 12:19:41
この回答を支持する
(現在0人が支持しています)
お礼
回答ありがとうございました。ちょっと、期待していた回答ではないのですが「サーバーログの確認」ということで、参考になりました。
投稿日時 - 2007-09-08 14:11:14
回答:No.12
> 運用上、上記の短所が問題にならなければ、採用の候補…

あはは。ありがとうございます(笑)まぁ、人間、自分のアイデアを大事にしたいというのが普通ですから^^ ここは、議論の場ではないようですが、色々とアイデアを出し合うのは楽しいですね。ではでは、お邪魔しました^^

====
// ディレクトリから fname にファイル名を得る

char *p = strrchr(fname, '_');
if (p == NULL) return; // 約束違反のファイル名
char *q = strrchr(fname, '.');
if (q == NULL || q < p) return; // 約束違反のファイル名
*q = '\0';
size_t fsiz = atol(p + 1);
if (fsiz == 0) return; // サイズ0はおかしい(笑)

*q = '.';
stat(fname, &statbuf);
if (statbuf.st_size != fsiz) return; // 書き込み中?

===
# .netrc が適当に設定されているとして

fname=`basename $pathname`
fsiz=`ls -l $file | awk '{print $5}'`
remotefile=`echo $fname | sed -e "s/\\([^.]*\\)\\.\\([^.]*\\)/\\1_$fsiz\\2/"`
ftp $remotehost <<EOF
bin
put $pathname $remotefile
bye
EOF
===
とか、やればいいんじゃないですか?^^ 修正時刻のチェックは、エラー処理に活用できますね(現在時刻と最終修正時刻の差があまりに大きいにもかかわらず、サイズが異なる場合など)。
投稿日時 - 2007-09-08 12:17:11
この回答を支持する
(現在0人が支持しています)
お礼
ソースまで提示していただき、ありがとうございます。mikaemi様の案が採用となった暁には、是非このソースも参考にさせていただきます。
投稿日時 - 2007-09-08 13:30:19
回答:No.11
もう一案。
手元にcygwinしかないので確認できないのですが。
まず実験として、
(1)pfilesコマンドでFTPデーモンのファイルディスクリプタ一覧を得る。
(2)ファイルディスクリプタ一覧のinode番号で、目的とするファイルが使用中か確認する。目的のファイルのinode番号はstatで得ておく。
なんてのはどうでしょうか?

pfilesコマンド自体の機能もソース見ればわかると思うので、プログラム上に吸収可能だと思います。
投稿日時 - 2007-09-08 12:10:05
この回答を支持する
(現在0人が支持しています)
お礼
回答ありがとうございます。いくつかの理由があって、たぶん、この方法を採用することは、無いとおもいますが、デーモンが「特定のファイルを書き込み中」か否かを判断する方法としては、最もこの案が、正解に近いと思います。又、pfilesコマンドの存在について判っただけでも収穫でした。ありがとうございました。
投稿日時 - 2007-09-08 14:22:36
回答:No.10
なるほど。。修正時刻のチェックしてもいいですね。各人各様で思いつくテクニックが異なっておもしろいですね^^

そういえば、ファイル名にファイルサイズを入れるとしても、バイナリモードで転送しないと、Windows⇔Unix⇔Macintoshなんかは、サイズが変わってしまいますねぇ。まぁ、でも、バイナリで転送するとして、stat()・lstat() を使うなら読み続けなくても、ファイルが置かれるディレクトリを舐めて、各ファイルの名前から取得したファイルサイズとstat()が返すファイルサイズをチェックするだけでいいですね^^
投稿日時 - 2007-09-08 10:08:50
この回答を支持する
(現在0人が支持しています)
お礼
回答ありがとうございます。
>バイナリで転送するとして、stat()・lstat() を使うなら読み続けなくても、ファイルが置かれるディレクトリを舐めて、各ファイルの名前から取得したファイルサイズとstat()が返すファイルサイズをチェックするだけでいいですね^^
上記の場合の長所と短所は以下になるかと思います。
長所:statが一回ですむ。
短所:FTP送信側での処理が多少発生する。
受信側でもファイル名にファイルサイズを含むため、ファイル名が固定にならずに、XXXXX_nnnnnn(nnnnnはファイルサイズ)にマッチするようなファイルを取得する必要がある。

運用上、上記の短所が問題にならなければ、採用の候補として検討したいと考えています。
投稿日時 - 2007-09-08 11:23:10
回答:No.9
すごく大雑把な方法ですが、statで最終修正時刻を調べて一定時間以上変更がなかったら書き込みが終了とみなすのはだめでしょうか?
信頼性と即時応答性は限りなく低いですが。
投稿日時 - 2007-09-08 09:51:21
この回答を支持する
(現在0人が支持しています)
お礼
回答ありがとうございます。
>すごく大雑把な方法ですが、statで最終修正時刻を調べて一定時間以上変更がなかったら書き込みが終了とみなすのはだめでしょうか?
その方法と同じではないですがstatでファイルサイズを調べて、一定時間経過後、前回と同じなら、書き込み完了とみなす。
ということは、考えておりました。
statで調査する場合は以下の長所/短所になるかと思います。
長所:FTPの送信側によけいな処理をさせないで済む。
短所:>>「信頼性と即時応答性は限りなく低いですが。」
運用上、上記の短所が問題にならなければ、statを繰り返す方法もありかと考えております。
投稿日時 - 2007-09-08 11:03:55
12件中 1~5件目を表示
もっと聞いてみる
関連するQ&Aはこちら
UNIX C言語の質問です。 複数プロセスの起動の仕方を教えてください。 あるプログラムは、ユーザーからの入力待ち状態になると同時に、所定時間のタイマーを起動し、ユーザーからの入力がなく、所定時間が...
UNIX上で実行されているプロセスを常時監視し、停止していたら自動的に再度実行させる手法はないでしょうか? ...
こんにちは。はじめて質問させていただきます。 先日会社で、某メーカのSUN(UNIX)サーバ3台を購入し、 KVMスイッチを用意して効率的に管理をしようと思ってました。ところが...用意したKVMスイ...
この他の関連するQ&Aをキーワードで探す
プログラミングのサブカテゴリ
[PR] おすすめの注目情報
カテゴリ:C・C++
RSS
-PR-
PR
-PR-