From: "高倉 健次" Date: 2011-06-30T12:33:03+09:00 Subject: [ruby-list:48198] Re: Net::FTPの挙動について 高倉です。 Net::FTPについて調べて分かったことを、情報共有としてまとめます。 ・Activeモードの場合、無限待ちになる事がある。 ftp.rbのtransfercmdの中でacceptを呼び出していますが、 次の条件の場合、acceptで無限待ちになります。 1.Net::FTPが送るPORTに対して、サーバが成功(2xx)を返す。 2.Net::FTPが送るSTORに対して、サーバが処理開始(1xx)を返す。 3.サーバ側に何らかのエラーが発生し、サーバがエラーを示す コード(4xxなど)を返す。 acceptにタイムアウト処理がされていないので無限待ちになります。 ・上記無限待ちの場合でも、FTP処理をtimeoutでくくればタイムアウトする。 timeoutのドキュメントに、C言語レベルで実装され、Ruby のスレッドが 割り込めない処理には効かない旨記述があったので、気にしていたのですが、 Linux CentOS 5.5の環境では、タイムアウトが効きました。 ・データのやり取りに対してタイムアウトが必要な場合はftp.rbの改造が必要。 acceptはデータのやり取りがないので、timeoutが効けばそれで対応は十分 ですが、readやwrite中はデータやり取りの停止に対してタイムアウトが 必要になる場合があります。 そのような場合に対応するには、selectを利用してタイムアウト処理を 実装するなどのftp.rbの改造が必要と思われます。 よろしくお願いいたします。 (2011/06/27 12:13), 高倉 健次 wrote: > 高倉です。 > > ご返信ありがとうございます。 > >> 例外処理はされているでしょうか。 > > begin〜resucueでFTPの処理を括り、例外を処理しております。 > > rescueで例外をキャッチした場合は、ログ出力、 > メール送信を行った後、プログラムを終了させます。 > > 今回の場合、ログ出力もメール送信も行われていませんので > FTPの処理で停止していたと推測されます。 > > あと、先のメールで書き忘れていたことを追記いたします。 > FTPでputするファイルは、数100バイトから数100キロバイト > です。100個程度を立て続けにputしています。 > 幾つかのファイルはアップロード完了し、その後サーバ側で > エラーが発生し停止に至ります。停止しているときに > クライアント側(Net::FTPを使っている側)で、netstatを > 実行しソケットの状態を見ると、CLOSE_WAITのまま止まって > いました。 > > よろしくお願いいたします。 > > (2011/06/27 11:48), 成田恭一[NWH] wrote: >> お世話になっております。成田と申します。 >> >> Cの延長でRubyをされているという事で少々気になった >> のですが >> >> 例外処理はされているでしょうか。 >> >> あほな質問で申し訳ありません。 >> >> 以上、よろしくお願いします。 >> ----- Original Message ----- From: "高倉 健次" >> To: "ruby mailing list" >> Sent: Saturday, June 25, 2011 5:06 PM >> Subject: [ruby-list:48191] Net::FTPの挙動について >> >> >>> はじめまして、高倉と申します。 >>> お世話になっております。 >>> >>> Net::FTPの挙動に関してお客様の環境で問題が発生し、色々調査 >>> しております。問題の対処法について、ご質問させてください。 >>> >>> まず、問題の内容をお知らせします。 >>> >>> 【環境】 >>> ハードウェア: DL360G5 >>> OS: Red Hat Enterprise Linux 5(64bit) >>> Ruby: 1.8.7-p334 >>> OSのTCP周りの設定: >>> デフォルトのまま。 >>> (tcp_keepalive_intvl=75, tcp_keepalive_probes=9, >>> tcp_keepalive_time=7200) >>> >>> Net::FTPからWindowsのIISと思われるFTPサーバ(サーバ側環境の >>> 詳細はまだ分かりません)にActiveモードで接続しております。 >>> >>> Net::FTPからファイルをput中にサーバ側で何らかのエラーが >>> 発生しサーバ側からcloseされたのですが、Net::FTP側は >>> その後put中の処理が停止したままタイムアウトになりません。 >>> (問題発生から6時間経過しても停止したままになっています) >>> >>> この処理は排他を掛けていますので、お客様側で問題が発覚しても >>> お客様が出来る操作で、問題からの復帰が出来ないという問題が >>> あります。 >>> >>> 問題は2つあります。 >>> 一つはサーバ側での何らかのエラーであり、根本原因はこちらに >>> あると思いますが、もう一つの復帰できない問題にも対応する >>> 必要があります。 >>> >>> 後者の問題に対して、put処理にタイムアウトを設定しタイムアウト >>> 発生後に復帰処理を行うように考えています。 >>> >>> とりあえずtimeout(sec) {|i|}を利用して対処しますが、根本的な >>> 解決ではないと考えています。 >>> >>> timeoutはブロック内の処理停止に対して働くのであって、パケット >>> 送受信の停止に働くものではありません。 >>> サイズが一定のファイルを送る場合は、問題にはなりませんが、 >>> 大小さまざまなファイルを送る事を考えると、タイムアウト値の >>> 適切な設定が出来なくなります。大きなファイルに合わせると >>> 無駄に長すぎるタイムアウト値になりますし、小さなファイルに >>> 合わせると大きなファイルを正常に処理しているのにタイムアウトが >>> 発生する事が考えられます。 >>> >>> >>> 前置きが長くなりましたが、ここからご質問です。 >>> >>> Net::FTPのput系の処理に適切なタイムアウトを設定することは >>> 可能でしょうか? >>> >>> また、ftp.rbのソースを読んでいた際に疑問が出てきましたので、 >>> あわせて、ご質問させてください。 >>> >>> サーバで何らかのエラーが発生した際、サーバ側から処理を中断 >>> するためにそれを知らせるレスポンスコード(451)をコマンド用 >>> 接続を通して返すと思いますが、そのレスポンスを処理しています >>> でしょうか? >>> >>> >>> 私はRubyの経験が浅く、FTPの処理がftp.rbで完結しているのか >>> よく分かりませんでした。 >>> Cの世界での経験上、selectを使って複数の接続(コマンド用、 >>> データ用)を適切に処理するのが定石だと思っていましたが、 >>> そのような処理がなかったので疑問点として浮上しました。 >>> >>> >>> ご助力いただけますと幸いです。 >>> よろしくお願いいたします。 >>> --- >>> 高倉 >>> >> >> >> > > --- > 高倉 > > --- 高倉