はじめに
以前,VALUE DOMAINのダイナミックDNSを更新するスクリプト書いたことを書きました.このスクリプトは,自宅サーバのcronで実際に動かしているのですが,ログを見てみると,結構500系のエラーが多いことが多いこと.
そんなわけで,失敗した際には成功するまで,またはある上限回数までリトライを繰り返す,といった処理を追加してみました.
また,前回の更新からIPアドレスが変化している場合,im.kayac.com経由でメッセージを投げる処理もついでに追加してみました.
ソースコード
変数のスコープがグチャグチャなのは仕様です ><
なお,wp-syntaxの都合上,ヒアドキュメント内の「’」を全角にしています.
#!/usr/bin/perl use strict; use warnings; use utf8; use LWP::UserAgent; use FindBin; # # 設定 # my $domain = 'yourdomain'; my $passwd = 'yourpassword'; my $host = '*'; my $retry = 10; my $interval = 20; my $username_im = 'yourimusername'; # # 設定 ここまで # my $logfile = sprintf '/var/log/ddns/%s.log', $domain; my $ipaddrfile = sprintf '%s/.ddns-ipaddr-%s', $FindBin::Bin, $domain; my $ua = LWP::UserAgent->new; my $res; my $ipaddr = ''; my $ipaddr_prev = ''; # # 前回更新時のIPアドレスの取得 # if (-f $ipaddrfile) { local $/; open my $fh, '<', $ipaddrfile; $ipaddr_prev = <$fh>; close $fh; } # # IPアドレスの取得 # if($ipaddr eq '') { my $url_get_ip = 'http://dyn.value-domain.com/cgi-bin/dyn.fcg?ip'; $res = $ua->get($url_get_ip); chomp($ipaddr = $res->content); } # # DNS更新リクエスト # my $url_update = sprintf('http://dyn.value-domain.com/cgi-bin/dyn.fcg' . '?d=%s&p=%s&h=%s&i=%s', $domain, $passwd, $host, $ipaddr, ); for( my $i = 0; $i < $retry; $i++ ) { $res = $ua->get($url_update); chomp(my $content = $res->content); $content =~ s{(\x0d\x0a?|\x0a)}{ // }g; my @matched = $content =~ /status=(\d+)/im; my $status = defined $matched[0] ? int($matched[0]) : 9; my $code = $res->code; # 成功 if( $code eq '200' && $status == 0 ) { print_log($ipaddr, 1, $code, $status, $content); if ($ipaddr ne $ipaddr_prev) { post_im($ipaddr, $ipaddr_prev); } save_ipaddr($ipaddr); last; } # 失敗 else { print_log($ipaddr, 0, $code, $status, $content); sleep($interval); next; } } # post im sub post_im { my ($ipaddr, $ipaddr_prev) = @_; my $url_im = sprintf 'http://im.kayac.com/api/post/%s', $username_im; my $message = << "..."; $domain\’s IP address has changed: $ipaddr_prev => $ipaddr ... $ua->post($url_im, {message => $message}); } # save ip address sub save_ipaddr { my ($ipaddr) = @_; open my $fh, '>', $ipaddrfile or die $!; print $fh $ipaddr; close $fh; } # print log sub print_log { my ($ipaddr, $result, $code, $status, $content) = @_; my $datetime; my ($ss, $mm, $hh, $d, $m, $y) = localtime time; $y+=1900; $m++; $datetime = sprintf '%04d-%02d-%02d %02d:%02d:%02d', $y, $m, $d, $hh, $mm, $ss; open(my $fh, '>>', $logfile) or die $!; printf $fh ("[%s] Request: %s => %s / Code: %s, Status: %d, Result: %s\n", $datetime, $ipaddr, $result ? 'o' : 'x', $code, $status, $content, ); close $fh; } __END__
ログの一部
更新に失敗した場合,20秒後にリトライ,これを最大10回繰り返しています.
... [2009-11-26 00:00:23] Request: ***.***.***.*** => o / Code: 200, Status: 0, Result: status=0 // OK [2009-11-26 00:10:03] Request: ***.***.***.*** => o / Code: 200, Status: 0, Result: status=0 // OK [2009-11-26 00:20:01] Request: ***.***.***.*** => o / Code: 200, Status: 0, Result: status=0 // OK [2009-11-26 00:30:05] Request: ***.***.***.*** => x / Code: 503, Status: 9, Result: <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> // <HTML><HEAD> // <TITLE>503 Service Temporarily Unavailable</TITLE> // </HEAD><BODY> // <H1>Service Temporarily Unavailable</H1> // The server is temporarily unable to service your // request due to maintenance downtime or capacity // problems. Please try again later. // </BODY></HTML> [2009-11-26 00:30:26] Request: ***.***.***.*** => o / Code: 200, Status: 0, Result: status=0 // OK [2009-11-26 00:40:02] Request: ***.***.***.*** => o / Code: 200, Status: 0, Result: status=0 // OK [2009-11-26 00:50:01] Request: ***.***.***.*** => o / Code: 200, Status: 0, Result: status=0 // OK [2009-11-26 01:00:02] Request: ***.***.***.*** => o / Code: 200, Status: 0, Result: status=0 // OK [2009-11-26 01:10:04] Request: ***.***.***.*** => o / Code: 200, Status: 0, Result: status=0 // OK [2009-11-26 01:20:02] Request: ***.***.***.*** => o / Code: 200, Status: 0, Result: status=0 // OK [2009-11-26 01:30:02] Request: ***.***.***.*** => o / Code: 200, Status: 0, Result: status=0 // OK [2009-11-26 01:40:01] Request: ***.***.***.*** => o / Code: 200, Status: 0, Result: status=0 // OK [2009-11-26 01:50:02] Request: ***.***.***.*** => o / Code: 200, Status: 0, Result: status=0 // OK [2009-11-26 02:00:15] Request: 500 Server closed connection without sending any data back => x / Code: 503, Status: 9, Result: <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> // <HTML><HEAD> // <TITLE>503 Service Temporarily Unavailable</TITLE> // </HEAD><BODY> // <H1>Service Temporarily Unavailable</H1> // The server is temporarily unable to service your // request due to maintenance downtime or capacity // problems. Please try again later. // </BODY></HTML> [2009-11-26 02:00:47] Request: 500 Server closed connection without sending any data back => x / Code: 500, Status: 9, Result: 500 Server closed connection without sending any data back [2009-11-26 02:01:39] Request: 500 Server closed connection without sending any data back => x / Code: 500, Status: 9, Result: 500 Server closed connection without sending any data back [2009-11-26 02:01:59] Request: 500 Server closed connection without sending any data back => x / Code: 500, Status: 9, Result: 500 Internal Server Error [2009-11-26 02:02:19] Request: 500 Server closed connection without sending any data back => x / Code: 503, Status: 9, Result: <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> // <HTML><HEAD> // <TITLE>503 Service Temporarily Unavailable</TITLE> // </HEAD><BODY> // <H1>Service Temporarily Unavailable</H1> // The server is temporarily unable to service your // request due to maintenance downtime or capacity // problems. Please try again later. // </BODY></HTML> [2009-11-26 02:02:40] Request: 500 Server closed connection without sending any data back => x / Code: 500, Status: 9, Result: 500 Internal Server Error [2009-11-26 02:03:00] Request: 500 Server closed connection without sending any data back => x / Code: 200, Status: 9, Result: status=9 // Unknow Error. [2009-11-26 02:03:21] Request: 500 Server closed connection without sending any data back => x / Code: 200, Status: 9, Result: status=9 // Unknow Error. [2009-11-26 02:03:42] Request: 500 Server closed connection without sending any data back => x / Code: 200, Status: 9, Result: status=9 // Unknow Error. [2009-11-26 02:04:03] Request: 500 Server closed connection without sending any data back => x / Code: 200, Status: 9, Result: status=9 // Unknow Error. [2009-11-26 02:10:01] Request: ***.***.***.*** => o / Code: 200, Status: 0, Result: status=0 // OK[2009-11-26 02:20:01] Request: ***.***.***.*** => o / Code: 200, Status: 0, Result: status=0 // OK [2009-11-26 02:26:52] Request: ***.***.***.*** => o / Code: 200, Status: 0, Result: status=0 // OK [2009-11-26 02:30:01] Request: ***.***.***.*** => x / Code: 503, Status: 9, Result: <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> // <HTML><HEAD> // <TITLE>503 Service Temporarily Unavailable</TITLE> // </HEAD><BODY> // <H1>Service Temporarily Unavailable</H1> // The server is temporarily unable to service your // request due to maintenance downtime or capacity // problems. Please try again later. // </BODY></HTML> [2009-11-26 02:30:21] Request: ***.***.***.*** => o / Code: 200, Status: 0, Result: status=0 // OK [2009-11-26 02:33:17] Request: ***.***.***.*** => o / Code: 200, Status: 0, Result: status=0 // OK [2009-11-26 02:40:02] Request: ***.***.***.*** => o / Code: 200, Status: 0, Result: status=0 // OK [2009-11-26 02:45:02] Request: ***.***.***.*** => o / Code: 200, Status: 0, Result: status=0 // OK ...
おわりに
というわけで,自宅サーバのダイナミックDNS更新スクリプトは,こんな感じのものが動いていますよ,と.
ちなみに,im.kayac.comのメッセージをiPhoneで受け取るためには,iPhoneアプリ「im.kayac.com」をインストールしておく必要があります.(以下のリンクはiTunesが起動します.)

