FTP更新チェッカ
30分プログラム、その92。FTPのログを解析して、ごにょごにょするやつ。
id:mzp:20070723:ftpのバージョンアップ版。
使い方
$ ruby ftup.rb
地味ですね。
コード
#! /opt/local/bin/ruby -w # -*- mode:ruby; coding:utf-8 -*- # # ftup.rb - # # Copyright(C) 2007 by mzp # Author: MIZUNO Hiroki <hiroki1124@gmail.com> # http://mzp.sakura.ne.jp/ # # Timestamp: 2007/07/27 22:42:02 # # This program is free software; you can redistribute it and/or # modify it under the same terms as Ruby itself. # require 'kconv' require 'net/ftp' require 'time' class Time def same_day?(o) self.day == o.day and self.month == o.month and self.year == o.year end end # ------------------------------ # Feeds # ------------------------------ def file(*filenames) filenames.map(&File.method(:open)) end def ftp_get(host,pass,user,pattern,count=5) ftp = Net::FTP.new host,pass,user list = ftp.nlst pattern list[-count..-1].map{|file| STDERR.puts file begin local = File.basename file ftp.getbinaryfile file,local File.open local rescue Net::FTPTempError end } end # ------------------------------ # Filter # ------------------------------ Command = Struct.new 'Command',:type,:filename,:mtime def filezilla(files) timestamp = %r!\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}! files.map{|io| commands = [] cwd = '/' io.each{|line| case line.chomp when %r!(#{timestamp}).*STOR (.*)\Z! commands << Command.new(:up, File.expand_path($2,cwd), Time.parse($1)) when %r!(#{timestamp}).*RETR (.*)\Z! commands << Command.new(:down, File.expand_path($2,cwd), Time.parse($1)) when %r!"(/.*)" is current directory.\Z! cwd = $1 end } commands } end def rank(commands,count=5) rank = Hash.new 0 commands.each{|command| rank[command.filename] += 1 } rank.keys.sort{|a,b| b<=>a}[0,count].map{|key| [key,rank[key]] } end def recent(commands,count=5) commands.select{|command| command.type == :up }.reverse[0,count] end # ------------------------------ # Publish # ------------------------------ def ftp_put(host,user,pass,file) ftp = Net::FTP.new host,user,pass ftp.putbinaryfile file ftp.close end # ------------------------------ # customize # ------------------------------ feeds = ftp_get 'example.com','mzp','xxx','/Logs/*.log',7 feeds.delete nil commands=filezilla feeds File.open('update.txt','w'){|io| c = commands.flatten r = "" time = nil recent(c,20).each{|cmd| if time == nil or not time.same_day?(cmd.mtime) then r += cmd.mtime.strftime("\n**%Y/%m/%d\n") end r += "-- #{cmd.filename}\n" time = cmd.mtime } t = rank(c,10).map{|name,count| span = ' ' * [50-name.size,0].max "- #{name}#{span}#{'=' * count}" }.join("\n") io.puts <<-UPDATE * 最近更新されたファイル(20件分) #{r} * 最近人気のファイル(Top 10) #{t} UPDATE } ftp_put 'example.com','mzp','xxx','update.txt'
メモ
- 出力の方法や、入力の方法がいろいろある。そこで、各機能を関数で実現して、組合せやすいようにした。
- だから、なるべく副作用は使わない方向で
- 続きはまた明日