|

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Yapra: hAtomまたはユーザ定義XPathを使ってウェブページをフィードに変換するプラグイン

表題の通りです。 再発明くさいのですが、他のプラグインから呼び出して使うことを想定して作っています

単体でも使えなくはないです。RSS::save に渡せばフィードとして保存できたりします。

ダウンロード

https://gist.github.com/raw/824665/2fcfd878b2cfd5f8e50aab97282c537213bbe453/extract.rb

{class base plugin dir}/yapra/plugin/feed/extract.rb として保存してください。

コード


Yapra メモ … その他の Yapra 関連記事についてはこっちにまとめてあります
スポンサーサイト

Yapra: フィードの要約を表示するプラグイン

「何かのプラグインでフィードを生成する → 結果を見る → パラメータなど修正」 という手順のうち、結果を確認する部分がめんどくさかったので作ってみました。

設定ファイルをいじってフィードを生成する場合だけでなく、 フィードを加工するプラグインを作る場合にも便利。


# test.yaml
- module: RSS::load
  config:
    url: http://feeds.fc2.com/fc2/xml?host=haraita9283.blog98

- module: Feed::PrintSummary
  config: 
    size: 3

このように設定ファイルを書いて端末から実行すると、標準出力に次のように出力されます。

$ yapra -c test.yaml
(略)
title: [Yapra: クラスベースのプラグインの書き方とファイル配置、パスの通し方]
date: [2011-02-08T00:05:20+09:00]
link: [http://haraita9283.blog98.fc2.com/blog-entry-407.html]
description: [Yapra のプラグインには legacy なもの class base なもの の 2種類あり、新たに自作する場合はクラスベースな方が推奨されているらしい。 参考: とりあえずネタ振り的なも ...]
--------------------------------
title: [whileループで動き続けるプログラムをログアウト時に終了させる(Ubuntu 10.10)]
date: [2011-02-05T22:07:22+09:00]
link: [http://haraita9283.blog98.fc2.com/blog-entry-406.html]
description: [注)いろいろよく分かってない人が書いてます。 1 環境 2 期待する動作 3 詳細 3.1 SIGHUP は送信されているか?3.2 明示的に SIGHUP を送信する 4 まとめ 5 備考 ...]
--------------------------------
title: [ローカルファイルシステムのファイルをHTTPで取得できるようにする(Ruby/WEBrick)]
date: [2011-02-01T01:10:36+09:00]
link: [http://haraita9283.blog98.fc2.com/blog-entry-405.html]
description: [あるファイルをローカルファイルシステムに置いて別のアプリケーションから利用したいが、 そのアプリケーションはネット上のリソースを使うことを前提としている、という場合があります。 たとえば Fi ...]
$ 

コード


# -*- coding: utf-8 -*-
require 'yapra/plugin/base'

module Yapra::Plugin::Feed

  # description:
  #
  # Data must be a collection of RSS::RDF::Item instance.
  # 
  # example:
  # 
  # - module: Feed::PrintSummary
  #   config: 
  #     reverse: true
  #     size: 10
  #     description_length: 100
  # 
  # config is optional.

  class PrintSummary < Yapra::Plugin::Base
    def shorten(element, length)
      return nil if element.nil?

      chars = element.gsub(/\s+/, " ").strip.split(//u)
      if chars.size > length
        chars = chars[0...(length-4)]
        chars << " ..."
      end

      chars.join("")
    end

    def run(data)
      description_length = config["description_length"] || 200

      summaries = data.map{|item|
        temp_item = item.clone

        if temp_item.description.respond_to? :inner_text
          temp_item.description = temp_item.description.inner_text
        end

        temp_item.description = shorten( temp_item.description,
                                         description_length )

        %w(title date link description).map{|field|
          "#{field}: [%s]\n" % temp_item.send(field)
        }.join("")
      }

      summaries.reverse! if config["reverse"]

      if config["size"]
        summaries = summaries[0...( config["size"] )]
      end

      puts summaries.join("-"*32 + "\n")

      data
    end
  end
end

関連記事


Yapra メモ … その他の Yapra 関連記事についてはこっちにまとめてあります

Yapra: クラスベースのプラグインの書き方とファイル配置、パスの通し方

Yapra のプラグインには

  • legacy なもの
  • class base なもの

の 2種類あり、新たに自作する場合はクラスベースな方が推奨されているらしい。

参考: とりあえずネタ振り的なものを - yapra | Google グループ

以下、クラスベースのプラグイン自作についてメモ。


Ruby の $LOAD_PATH/foo/bar/ が含まれていると、 その下のディレクトリ階層がクラスの階層に対応する。

たとえば設定ファイルをこのように書きたい場合、

- module: Foo::BarBaz
  config: #...

プラグインを次のように書き、 /foo/bar/yapra/plugin/foo/bar_baz.rb (={ロードパスの通ったディレクトリ}/yapra/plugin/foo/bar_baz.rb) として保存する。


require "yapra/plugin/base"
 
module Yapra::Plugin::Foo
  class BarBaz < Yapra::Plugin::Base
    def run(data)
      puts "plugin Foo::BarBaz"
      p config
      # ...
      return data
    end
  end
end

クラスベースのプラグインを自作して使いたいが Yapra のインストールされているディレクトリや site_ruby には余計なものを入れたくない。 かといってわざわざ gem にするほどでもない。 そういう場合は、Ruby の -I オプションを使って別のディレクトリを指定するのが良いかもしれない。

そこで、次のようなシェルスクリプトを用意した。


#!/bin/bash
 
YAPRA_DIR=~/my-yapra/yapra
MY_PLUGIN_DIR_CLASS_BASE=~/my-yapra/my-dir-class-base
 
ruby -I ${YAPRA_DIR}/lib \
     -I ${MY_PLUGIN_DIR_CLASS_BASE} \
     ${YAPRA_DIR}/bin/yapra \
     "$@"

レガシーなプラグインも使いたい場合は (Ruby ではなく Yapra の) -p オプションで指定する。


#!/bin/bash
 
YAPRA_DIR=~/my-yapra/yapra
MY_PLUGIN_DIR_CLASS_BASE=~/my-yapra/my-dir-class-base
MY_PLUGIN_DIR_LEGACY=~/my-yapra/my-dir-legacy
 
ruby -I ${YAPRA_DIR}/lib \
     -I ${MY_PLUGIN_DIR_CLASS_BASE} \
     ${YAPRA_DIR}/bin/yapra \
     -p ${MY_PLUGIN_DIR_LEGACY} \
     "$@"

Windows XP でも次のようなバッチファイルで同じように動かせました。

- ruby 1.9.2p136 (2010-12-25 revision 30365) [i386-mswin32]
- Yapra 0.1.3

@echo off

set YAPRA_DIR="c:\dev\yapra"
set MY_PLUGIN_DIR_CLASS_BASE="C:\dev\yapra\my-plugin\class-base"
set MY_PLUGIN_DIR_LEGACY="C:/dev/yapra/my-plugin/legacy"

ruby192.bat ^
  -I "%YAPRA_DIR%\lib-plugins" ^
  -I "%MY_PLUGIN_DIR_CLASS_BASE%" ^
  "%YAPRA_DIR%\bin\yapra" ^
  -p "%MY_PLUGIN_DIR_LEGACY%" ^
  %*

関連記事

参考(外部リンク)

whileループで動き続けるプログラムをログアウト時に終了させる(Ubuntu 10.10)

注)いろいろよく分かってない人が書いてます。


1 環境

  • Ubuntu Linux 10.10 Desktop
  • GNOME 2.32.0
  • GNU bash, version 4.1.5(1)-release (i686-pc-linux-gnu)
  • Ruby 1.8.7 (2010-06-23 patchlevel 299) [i686-linux]

2 期待する動作

whileループなどで動作し続けるプログラムをログイン時に自動的に実行し、 ログアウト時に自動的に終了するようにしたい。

3 詳細

サンプルとしてこのような Rubyスクリプト ~/test.rb を用意した。


while true
  puts Time.now
  sleep 60
end

ログイン時に自動実行させるため ~/.profile に次の行を追加した。


ruby ~/test.rb &

  • グラフィカルログインで GNOMEセッション開始 (要するに普通にログイン)。
  • test.rb (pid=1772)が動いていることを確認。
  • デスクトップ画面右上のボタンでログアウト。
  • さっきと同じようにログイン。

この時点で ps ax | grep ruby すると、前回のログイン時に実行されたものと 今のログイン時に実行されたものが両方表示される。

 1772 ?        S      0:00 ruby /home/testuser/test.rb
 2165 ?        S      0:00 ruby /home/testuser/test.rb

前回ログイン時に実行したものは前回のログアウト時に終了してほしい。


ちなみに pstree で確認すると以下のようになっている(余計な部分は省略してある)。

前回のログイン時に実行された test.rb :

init
  ├─ruby /home/testuser/test.rb

今回のログイン時に実行された test.rb :

init
  ├─gdm-binary
  │   ├─gdm-simple-slav --display-id /org/gnome/DisplayManager/Display1
  │   │   ├─gdm-session-wor
  │   │   │   ├─gnome-session
  │   │   │   │   ├─ruby /home/testuser/test.rb

参考:

3.1 SIGHUP は送信されているか?

可能性としては 2つ考えられる。

  1. ログアウト時に SIGHUP が送信されていない
  2. ログアウト時に SIGHUP が送信されているが、何らかの理由でプロセスが終了しない

これを切り分けるため、 test.rb で trap を設定した。

 
log = open(File.expand_path("~/test.log"), "a")
 
log.puts "#{Time.now} ** start **"
log.flush
 
# HUP 以外のシグナルも一応見張ってみる
%w(HUP TERM INT QUIT).each {|sig|
  Signal.trap(sig) {
    log.puts "%s - pid:%d sig:%s" % [Time.now, Process.pid, sig]
    log.flush
    exit
  }
}
 
loop do
  puts Time.now
  sleep 60
end

一旦 test.rb を すべて終了させて

  • 上と同じように ログイン
  • 実行されているのを確認
  • ログアウト・再ログイン

この状態では 2つのプロセスが動いており、 test.log を見ても SIGHUP , SIGINT などを受け取った形跡はない。

一方、手動で kill -HUP {PID} した場合は test.log にそのことを示すログが残り、 プロセスが終了する。

したがって、 SIGHUPtest.rb に送信されていない ( test.rbSIGHUP を受け取っていない) と考えられる。

3.2 明示的に SIGHUP を送信する

なぜログアウト時に SIGHUP が送信されないのか、という点については 難しい話になるようなので深追いしなかった(帰ってこれなさそうでした……)。

OSまかせ(?)にせず、 ログアウト時に明示的に SIGHUP を送信する方法で進めることにした。


まず ~/.bash_logout を利用することを考えたが、 GNOMEパネルのログアウトボタンを押してログアウトした場合、 ~/.bash_logout は呼ばれない。

ちなみに、bash の manpage には次のように書いてあった。

When a login shell exits, bash reads and executes commands from the file ~/.bash_logout, if it exists.

「ログインシェルが終了するとき」とあるので、 「ログアウトするときに呼ばれる」という認識だと正確ではないのかも。


他に何か方法はないかと調べてみたところ /etc/gdm/PostSession/Default を使えばよいと分かった。

参考: How to run a script during Gnome log out - Unix and Linux - Stack Exchange

exit 0; の行の前に次のように書く

 
TARGET_USER=testuser

echo "executing /etc/gdm/PostSession/Default" >> /home/${TARGET_USER}/test.log # 確認用
 
if [ ${USERNAME} = "${TARGET_USER}" ];then
  su ${TARGET_USER} -c /home/${TARGET_USER}/.gdm_postsession
fi

# ↓これだけでもいいかも?
# if [ -e /home/${USERNAME}/.gdm_postsession ] ; then
#   su ${USERNAME} -c /home/${USERNAME}/.gdm_postsession
# fi

呼び出される ~/.gdm_postsession の内容:

 
echo "executing ~/.gdm_postsession" >> ~/test.log # 確認用

chmod u+x ~/.gdm_postsession で実行権限を与えておく。

※ この .gdm_postsession というファイル名はこのように決められているわけではなく、 自分で考えて付けたもの


上と同様にログイン・再ログインしてログを見ると、ログアウト時に /etc/gdm/PostSession/Default~/.gdm_postsession が呼ばれていることが確認できた。

あとは .gdm_postsession で 終了させたいプロセスに SIGHUP を送ればいいはず。

送信するには対象となるプロセスの一覧をどこかから得なければならないため、 ~/test.rb の最初の方に次の行を追加し、 自身の PID を ~/.my_hup_list に追記することにした。 このファイル名も自分で決めたもの。


open(File.expand_path("~/.my_hup_list"), "a") {|f| f.puts Process.pid }

ちなみに、他の Rubyスクリプトも同じように(ログインしている間だけ)動作させたいなら、 この 1行だけ別ファイル append_to_hup_list.rb に抜き出して、 メインのスクリプトの方では


require "append_to_hup_list"

とだけ書くようにすると良いかも。


~/.gdm_postsession の方では、 ~/.my_hup_list にリストアップされている PID に SIGHUP を送り ~/.my_hup_list を空にする


kill -HUP `cat ~/.my_hup_list`
echo -n "" > ~/.my_hup_list

ここまでやってようやく期待通りの動作になった。

~/.my_hup_list は 1行ごとに PID が並んでいるだけのプレインテキストなので、 Ruby 以外のプログラムからでも簡単に利用できる。

4 まとめ

  • プログラムの側で自身の PID を ~/.my_hup_list に追記
  • gdm セッション終了時に /etc/gdm/PostSession/Default が呼ばれる
  • そこから ~/.gdm_postsession が呼ばれるようにする
  • ~/.gdm_postsession~/.my_hup_list の PID を参照し SIGHUP を送る

5 備考

やりたいことができるようにはなったが、 煩雑なので tcsh の組み込みコマンド hup のようなものが使えるならそうしたい。

参考: Manpage of TCSH

または、Bash の機能を使って shopt huponexit とする方法もあるようだが、 これだとグローバルな設定を変えることになり 影響範囲が把握できなかったので今回は使わないことにした。


GNOME の画面右上のログアウトボタンを押したときに起こることを 単に「ログアウト」と呼んでしまっていいのか、 それとも「gdmセッションの終了」のように呼ぶのがいいのか、 結局よく分からなかった。 それとログインシェルとの関係とかも詳しく調べてすっきりさせたいところ……。


2013-01-14 追記:
最近のUbuntuなど、LightDM を使っている場合は /etc/gdm/PostSession/Default の代わりに /etc/lightdm/lightdm.conf で指定します。
参考: [SOLVED] LightDM login and logout scripts - Ubuntu Forums

参考(外部リンク)

ローカルファイルシステムのファイルをHTTPで取得できるようにする(Ruby/WEBrick)

あるファイルをローカルファイルシステムに置いて別のアプリケーションから利用したいが、 そのアプリケーションはネット上のリソースを使うことを前提としている、という場合があります。

たとえば Firefox でフィード(のファイル)を開くと、 ローカルのファイルを開いた場合と HTTP越しの場合とで表示が異なりますし、 ローカルのフィードはライブブックマークに登録できません。
他のフィードリーダや podcatcher もローカルのフィードに対応していなかったりします。
フィードを生成するプログラムを使っていて、 パラメータをいじって確認しながら試行錯誤したいのに……と。

また、all rights reserved なコンテンツなど外部に公開できない場合も困ります (アクセスを制限する方法は何かしらあるんでしょうけど)。



** ホームに戻る

|
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。