更新
Value-Domain用のDDNS更新スクリプト・デーモン版
デーモンとして起動するように、色々書き換えた。
設定ファイルの書き方などは前回の記事参照のこと。
致命的なミスが見つかったので、/usr/local/sbin/vdddnsを更新。
/usr/local/sbin/vdddns
#!/usr/bin/perl
use LWP::UserAgent;
use File::Slurp;
use Sys::Syslog;
use POSIX qw(setsid);
use Digest::MD5 qw(md5_hex);
# settings
$interval = 600; # seconds
$save_file = '/var/vdddns/ip';
$conf_hash_file = '/var/vdddns/conf_hash';
$ip_check_uri = "http://dyn.value-domain.com/cgi-bin/dyn.fcg?ip";
$update_uri_template = 'http://dyn.value-domain.com/cgi-bin/dyn.fcg?d=@DOMAIN@&p=@PASSWORD@&h=@HOST@&i=@IP_ADDRESS@';
$conf_file = "/etc/vdddns.conf";
# load conf list
@entries = ();
my $conf_list = read_file($conf_file, err_mode => 'quiet');
unless ($conf_list) {
print("Could not load the configration file: $conf_file\n");
die;
} else {
my @lines = split /\n/, $conf_list;
foreach my $line (@lines) {
my @values = split /\s+/, $line;
if (@values > 0) { # remove empty line
push(@entries, [@values]);
}
}
}
# load conf hash
$conf_hash = read_file($conf_hash_file, err_mode => 'quiet');
unless ($conf_hash) {
# the first running
$conf_hash = 'UNSET';
}
$new_conf_hash = md5_hex($conf_list);
# load saved ip address
$ip = read_file($save_file, err_mode => 'quiet');
if (! $ip || ($conf_hash ne $new_conf_hash)) {
$ip = 'UNSET';
}
# save conf hash
unless (write_file($conf_hash_file, $new_conf_hash)) {
print( "Could not write conf hash.\n");
die;
}
# HTTP requset
$ua = LWP::UserAgent->new;
$ip_req = HTTP::Request->new(GET => $ip_check_uri);
# daemon process
if (my $pid = fork) {
# exit the parent process
exit 0;
} elsif (defined $pid) {
# leave the child process as a daemon
setsid;
sleep 2;
main();
exit 0;
} else {
# fork error
print "Could not create a daemon process\n";
die;
}
sub main {
if ($ip eq 'UNSET') {
print_log("Conf file updated. Trying to update the entries.", 'info');
} else {
print_log("Current IP address: $ip", 'info');
}
# start observation
while (1) {
my $ip_res = $ua->request($ip_req);
if ($ip_res->is_success) {
my $new_ip = $ip_res->content;
if ($new_ip ne $ip) {
if ($ip eq 'UNSET') {
print_log("Current IP address: $new_ip", 'info');
} else {
print_log("IP address changed: $ip -> $new_ip", 'info');
}
$ip = $new_ip;
unless (write_file($save_file, $ip)) { # save to the file
print_log( "Could not write the ip address: $save_file", 'err');
}
foreach my $entry (@entries) {
# make uri for updating
my ($account, $password, $domain, $host) = @{$entry};
my $update_uri = $update_uri_template;
$update_uri =~ s/\@ACCOUNT\@/$account/g;
$update_uri =~ s/\@PASSWORD\@/$password/g;
$update_uri =~ s/\@DOMAIN\@/$domain/g;
$update_uri =~ s/\@HOST\@/$host/g;
$update_uri =~ s/\@IP_ADDRESS\@/$ip/g;
# request to update
my $update_req = HTTP::Request->new(GET => $update_uri);
my $update_res = $ua->request($update_req);
if ($update_res->is_success) {
# parse result
my ($status_code_line, $status_message) = split /\n/, $update_res->content;
$status_code_line =~ /^status=(.*)$/;
my $status_code = $1;
# print result
if ($status_code eq "0") {
print_log("Updating success: $host.$domain", 'info');
} else {
print_log("Updating error: $host.$domain $status_message", 'err');
}
} else {
print_log("Updating HTTP error: $update_uri " . $update_res->status_line, 'err');
}
sleep 10;
}
print_log("All updating done.", 'info');
}
} else {
my $trymax = 3;
for (my $trycount = 0; $trycount < $trymax; $trycount++) {
print_log ("IP address lookup error: " . $ip_res->status_line, 'warning');
sleep 60;
}
if ($trycount eq $trymax) {
print_log ("IP address lookup error $try times.", 'err');
}
}
sleep $interval;
}
}
sub print_log {
my ($message, $priority) = @_;
openlog('vdddns', 'cons,pid', 'user');
syslog($priority, $message);
closelog();
}
/etc/init.d/vdddns
#!/bin/sh
#
# chkconfig: - 92 34
# description: Starts and stops VDDDNS daemon.
#
# config: /etc/vdddns.conf
# Source function library.
if [ -f /etc/init.d/functions ] ; then
. /etc/init.d/functions
elif [ -f /etc/rc.d/init.d/functions ] ; then
. /etc/rc.d/init.d/functions
else
exit 0
fi
# Avoid using root's TMPDIR
unset TMPDIR
RETVAL=0
start() {
KIND="vdddns"
echo -n $"Starting $KIND services: "
daemon /usr/local/sbin/vdddns
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/vdddns || \
RETVAL=1
return $RETVAL
}
stop() {
KIND="vdddns"
echo -n $"Shutting down $KIND services: "
killproc /usr/local/sbin/vdddns
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/vdddns
return $RETVAL
}
restart() {
stop
start
}
rhstatus() {
status vdddns
}
# Allow status as non-root.
if [ "$1" = status ]; then
rhstatus
exit $?
fi
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
restart
;;
status)
rhstatus
;;
condrestart)
[ -f /var/lock/subsys/vdddns ] && restart || :
;;
*)
echo $"Usage: $0 {start|stop|restart|status|condrestart}"
exit 1
esac
exit $?
init.dスクリプトは一応手元では動いているが、適当に拾ってきたものを編集しただけなので微妙に変なところがあるかもしれない。
[root@example.com ~]# chkconfig --add vdddns [root@example.com ~]# chkconfig vdddns on [root@example.com ~]# service vdddns start
このように打てばデーモンとして起動する。設定ファイルを更新したらservice vdddns restartで再起動すること。設定ファイルが更新されていると、再起動時にIPアドレスが変化していなくても更新作業を行ってくれる。