感謝のプログラミング 10000時間

たどり着いた結果(さき)は、感謝でした。

RubyでSSH,telnet,バッチ実行、メッセージ出力など。

Rubyでポップアップを表示する

require 'win32ole'

def popup(msg, title)
  wsh = WIN32OLE.new('WScript.Shell')
  wsh.Popup(msg, 0, title, 0 + 64 + 0x40000)
end

popup("ポップアップです", "注意")

・Rubyからバッチファイルを実行する
test.bat

echo "test"

上記のtest.batというバッチファイルをRubyから呼び出してみる(実行してみる)
invoke.rb

exec("test.bat")

このrubyを実行すると。。。

>ruby invoke.rb

"test"

と、バッチで実行した中の内容が表示される。

・RubyでSSHを実行する。

gem list net-ssh

でnet-sshがインストールされていること

gem search --remote ssh

で検索。

net-sshが見つかったらインストールする。

gem install --remote net-ssh

RubyでSSH(まだちゃんと稼働確認してないです)

require 'rubygems'
require 'net/ssh'

domain = 'example.com' #ここにIPアドレスかドメイン名を入れる
Net::SSH.start( domain, :username =>'leonardr',
			 :password => 'mypass', :verbose => :debug)  do |session|
	shell = session.shell.sync
	puts "Original working directory: #{shell.pwd.stdout}"
	shell.cd 'test_dir'
	puts "Working directory now: #{shell.pwd.stdout}"
	puts 'Directory contents:'
	puts shell.ls("-1").stdout
	shell.exit
end

Rubyでtelnetのテスト

require 'net/telnet'

webserver = Net::Telnet::new('Host' => 'www.oreilly.com',
	'Port' => 80,
	'Telnetmode' => false)
	
size = 0
webserver.cmd("GET / HTTP/1.1\nHost: www.oreilly.com\n") do |c|
	size += c.size
	puts "Read #{c.size} bytes; total #{size}"
end

色々と調べてみて思ったのは、ちょっとしたツールを作るなら、
Javaを使ったりするよりもRubyの方がダントツで便利だということ。

Linux上での対話的な操作を実現するために

expect
http://www.uetyi.mydns.jp/wordpress/command/entry-158.html

を使ったりしたけど、
同じことがRubyでもっと簡単に、もっと便利に実現できてしまう。はずだ。

なんとなく感じがつかめたので、明日出社したときに早速ツールを作成してみたい。

Rubyクックブック ―エキスパートのための応用レシピ集

Rubyクックブック ―エキスパートのための応用レシピ集

  • 作者: Lucas Carlson,Leonard Richardson,株式会社クイープ
  • 出版社/メーカー: オライリー・ジャパン
  • 発売日: 2007/04/27
  • メディア: 大型本
  • 購入: 1人 クリック: 73回
  • この商品を含むブログ (55件) を見る

Springフレームワークでスケジューラを作ってみた。

■Springでタスクスケジューリング

タスクスケジューリングとは、処理(=タスク)をあらかじめ設定した時刻や一定間隔で実行するものである。
タスクとスケジュールはTaskSchedulerインターフェースを通して結びつく。

タスクスケジューリングを設定するためには、beans.xmlに名前空間taskを宣言する。
task:scheduler要素を使ってTaskSchedulerを登録する。

これを使うといちいちcronを仕込まなくても自動で時間指定でJavaを実行してくれる。

タスクスケジュールを使う時は、コードを記述する必要はない。
Spring設定ファイルに記述するだけでよい。

<task:scheduled-tasks>用をのscheduler属性にTaskSchedulerのidを指定し、
その子要素として<task:scheduled>要素を記述する。
<task:scheduled>要素のref属性にタスクとするBeanのidを指定する。
method属性にタスクとして実行させたいメソッドを指定する。

Springのcron

秒 分 時 月 年 曜日

の順。
Eclipse上でAntでコンパイルするときに、
「エラー: この文字は、エンコーディングUTF8にマップできません」
みたいなエラーが出た。
build.xmlのjavacに適当にencodingを設定したら、とりあえず回避できた。
(適当にしてしまってごめんなさい。もう深夜なのでw)

<javac destdir="${classes.dir}" debug="on" debuglevel="lines,vars,source" encoding="MS932">

http://www.ne.jp/asahi/hishidama/home/tech/ant/tag/javac.html

まずは結果から。
コンソールにメッセージを表示するメソッドを1秒おきに実行するスケジューラを作成した。
antを実行すると、こんな感じで表示される。

     [java] TASK NAME is TASK TESTTASK NUMBER is 1MESSAGE is SCHEDULER TEST
     [java] TASK NAME is TASK TESTTASK NUMBER is 1MESSAGE is SCHEDULER TEST
     [java] TASK NAME is TASK TESTTASK NUMBER is 1MESSAGE is SCHEDULER TEST
     [java] TASK NAME is TASK TESTTASK NUMBER is 1MESSAGE is SCHEDULER TEST
     [java] TASK NAME is TASK TESTTASK NUMBER is 1MESSAGE is SCHEDULER TEST
     [java] TASK NAME is TASK TESTTASK NUMBER is 1MESSAGE is SCHEDULER TEST
     [java] TASK NAME is TASK TESTTASK NUMBER is 1MESSAGE is SCHEDULER TEST
     [java] TASK NAME is TASK TESTTASK NUMBER is 1MESSAGE is SCHEDULER TEST

実行しているメソッドは、以下のようなソース。
インターフェースと共に載せる。

package schedule1;

public interface TaskBean {
	void doTask();
}

このdoTask()を1秒ごとに実行しているわけだ。

package schedule1;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.scheduling.annotation.Scheduled;

public class TaskBeanImpl implements TaskBean {

	private Log log = LogFactory.getLog(getClass());
	private String taskName;
	private String message;
	private int taskNumber;
	
	public TaskBeanImpl(String taskName) {
		this.taskName = taskName;
	}
	
	public void setMessage(String message) {
		this.message = message;
	}
	
	public void setTaskNumber(int taskNumber) {
		this.taskNumber = taskNumber;
	}
	
	@Scheduled(cron = "* * * * * ?")
	public void doTask() {
		System.out.println("TASK NAME is " + taskName + "TASK NUMBER is " + taskNumber 
				+ "MESSAGE is " + message);
		log.info("TASK NAME is:" + taskName + "TASK NUMBER is:" + taskNumber 
				+ " MESSAGE is" + message);
	}
	
}

ここにある@Scheduledがポイント。
ここで、cronの時刻を設定している。
全て「*」にしたから、毎秒という意味だ。

・・・と思ったけど、beans.xmlに書いたcronの通りに実行されるみたい。
アノテーションの役割は今後確認する。。

beans.xmlを読み込むクラスはこんな感じ。

package schedule1;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TaskTest {
	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
	}
}

読み込まれるbeans.xmlはこの通り。これもポイント。

<?xml version="1.0" encoding="Windows-31J" ?>

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:task="http://www.springframework.org/schema/task"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
	http://www.springframework.org/schema/task
	http://www.springframework.org/schema/task/spring-task-3.0.xsd">

	<bean id="taskBean" class="schedule1.TaskBeanImpl">
		<constructor-arg>
			<value>TASK TEST</value>
		</constructor-arg>

		<property name="message">
			<value>SCHEDULER TEST</value>
		</property>
		<property name="taskNumber">
			<value>1</value>
		</property>
	</bean>

	<task:scheduler id="taskScheduler" pool-size="5" />

	<task:scheduled-tasks scheduler="taskScheduler">
		<task:scheduled ref="taskBean" method="doTask"
			cron="* * * * * ?" />
	</task:scheduled-tasks>

</beans>

scheduled-tasksのところで、taskBeanのdoTaskメソッドを実行する設定がされている。
このtaskBeanというのは、bean idで指定されたクラスだ。

ref="beanID"で、タスクを実行するクラスを指定して、methodで、叩くメソッドを指定する。
これをスケジュール通りに実行してくれる。

あとは、log4j.xml

<?xml version="1.0" encoding="Windows-31J" ?>

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:task="http://www.springframework.org/schema/task"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
	http://www.springframework.org/schema/task
	http://www.springframework.org/schema/task/spring-task-3.0.xsd">

	<bean id="taskBean" class="schedule1.TaskBeanImpl">
		<constructor-arg>
			<value>TASK TEST</value>
		</constructor-arg>

		<property name="message">
			<value>SCHEDULER TEST</value>
		</property>
		<property name="taskNumber">
			<value>1</value>
		</property>
	</bean>

	<task:scheduler id="taskScheduler" pool-size="5" />

	<task:scheduled-tasks scheduler="taskScheduler">
		<task:scheduled ref="taskBean" method="doTask"
			cron="* * * * * ?" />
	</task:scheduled-tasks>

</beans>

commons-loging.properties

org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger

build.xml

<?xml version="1.0"?>

<project name="task1" basedir="." default="run.task1">
	<property name="src.dir" value="src"/>
	<property name="lib.dir" value="lib" />
	<property name="classes.dir" value="classes" />
	
	<path id="classpath">
		<fileset dir="${lib.dir}">
			<include name="*.jar"/>
		</fileset>
	</path>
	
	<target name="init" description="作業ディレクトリの初期化">
		<delete dir="${class.dir}"/>
		<mkdir dir="${class.dir}" />
	</target>
		
	<target name="compile" depends="init" description="コンパイルします">
		<javac destdir="${classes.dir}" debug="on" debuglevel="lines,vars,source" encoding="MS932">
			<src path="${src.dir}"/>
			<classpath refid="classpath"/>
		</javac>
		<copy todir="${classes.dir}">
			<fileset dir="${src.dir}">
				<include name="**/*.xml" />
			</fileset>
		</copy>
	</target>
	
	<target name="run.task1" depends="compile" description="アプリケーションを実行します">
		<java classname="schedule1.TaskTest" classpath="${classes.dir}" classpathref="classpath" fork="true"></java>
	</target>
</project>
			
			
	


1番苦戦しがちなファイル体系だが、こんな感じ。


Eclipse上でAntを実行するのは、Javaの道を参考にしました。
http://www.javaroad.jp/opensource/js_eclipse3.htm

参考書籍はこちら。この本、本当にいい。
サンプルの真似をするとだんだんわかってくる。説明も的確だし。

SpringによるWebアプリケーションスーパーサンプル 第2版

SpringによるWebアプリケーションスーパーサンプル 第2版

うまく動いたので、寝る。4時になってしまう。。

★★
ちょっと余談だけど、はてなブックマークのホットエントリーに「僕が読んだ300冊のうち影響を受けた10冊を紹介する」
とか、
「ブログで本を紹介しちゃいます」
的なのを見かけるけど、そういう本の紹介がほとんど自己啓発本やビジネス書なのはなんでだろう。
「アイデアが浮かぶ本!」を読んで、じゃあそのアイデアで何を作ったのかが知りたい。
自己啓発本は30分くらいで読み終える割に、書いてあることはみんな一緒で、読んだところで自分を劇的に変えることなんてできないと思うんだよね。
地道に、積み重ねるしかないと思うんだ。

ただ、カーネギーの「人を動かす」とドラッカーの「経営者の条件」だけは本当に良かった。

新版 ハンディーカーネギー・ベスト(3冊セット): 「人を動かす」「道は開ける」「カーネギー名言集」

新版 ハンディーカーネギー・ベスト(3冊セット): 「人を動かす」「道は開ける」「カーネギー名言集」

  • 作者: D・カーネギー,ドロシー・カーネギー,山口博,香山晶,神島康
  • 出版社/メーカー: 創元社
  • 発売日: 2011/11/22
  • メディア: 単行本
  • 購入: 4人 クリック: 14回
  • この商品を含むブログ (5件) を見る
ドラッカー名著集1 経営者の条件

ドラッカー名著集1 経営者の条件

FTPする。

RubyでFTPを実行するサンプルコード

require 'net/ftp'

ftp = Net::FTP.open('ftp.ibiblio.org') do |ftp|
	#サーバーにログインするためのメソッド
	ftp.login
	#FTPサーバのディレクトリを変更する
	ftp.chdir('pub/linux')
	#lsと同じ
	ftp.list('*Linux*') { |file| puts file }
	puts
	
	puts 'Saving a text file to disk while processing it.'
	#テキストファイルを取得する
	ftp.gettextfile('How-do-I-get-Linux') { |line| puts "! #{line}" }
	puts "Saved #{File.size 'How-do-I-get-Linux'} bytes."
	puts
	
	puts 'Saving a binary file to disk.'
	#バイナリファイルを取得する
	ftp.getbinaryfile('INDEX.whole.gz')
	puts "Saved #{File.size 'INDEX.whole.gz'} bytes."
end

ftp.loginは、

ftp.login('user','pass')

のようにユーザーとパスワードを指定できる。

chdirメソッド:ディレクトリを移動する。
listメソッド:ディレクトリ構造を参照する。

FTPの「GET」に相当するのが、
gettextfile
getbinaryfileメソッド

gettextfileメソッドはダウンロード時にプラットフォーム固有の改行フォーマットを変換する。

FTPの「PUT」に相当するのが
puttextfile
putbinaryfileメソッド


現在は、ファイルのコピーにはSCP、ファイルの配布にはWeb、大容量ファイルの配信にはBitTorrentが使用されている場合が多い。<参考>

Rubyクックブック ―エキスパートのための応用レシピ集

Rubyクックブック ―エキスパートのための応用レシピ集

  • 作者: Lucas Carlson,Leonard Richardson,株式会社クイープ
  • 出版社/メーカー: オライリー・ジャパン
  • 発売日: 2007/04/27
  • メディア: 大型本
  • 購入: 1人 クリック: 73回
  • この商品を含むブログ (55件) を見る