A little bit of everything

情報系大学院生の備忘録

HBA:Host-based Authentication(ホストベース認証)とは

よくある認証方法は、User-based Authentication(ユーザベース認証)

FacebookTwitter にログインするときに、自分のユーザIDとパスワードを打ちますよね?
つまり、FacebookTwitter のサーバでは、
「このユーザIDとパスワードの組み合わせは○○さんだ!ログインを許可します!」
みたいな判断をしています。

ユーザごとにユーザIDを持っていて、そのユーザIDをもとに認証をするので、この認証方法を User-based Authentication(ユーザベース認証)といいます。

それに対してHost-based Authentication(ホストベース認証)は

ユーザベース認証ではなく、接続してきたマシン(ホスト)を見て、
「あっ、このマシンからの接続要求なら接続OKですよ」
みたいな認証方法が、Host-based Authentication(ホストベース認証)です。

つまり、AさんだろうがBさんだろうが、中の人は関係なくて、
「そのマシンからアクセスしてきてるならOK!」
とか、
「このマシンは知らないなぁ。接続NG!」
とか、マシン(ホスト)をもとに判断を下すわけです。
だからサーバ側では、「アクセスしてきてOKなホストのリスト」を持っています。

HBAの例

PostgreSQLの設定ファイルの一種に、pg_hba.conf があります。
この pg_hba.conf の hba は Host-based Authentication(ホストベース認証)の略です。
つまり、PostgreSQLでHBAを実現するための設定ファイルということになります。

CentOS 7 のディスクイメージのちがい(DVD ISO, Everything ISO, Minimal ISO)

CentOS 7 のディスクイメージ(DVD ISO, Everything ISO, Minimal ISO)の違いは?

f:id:yuukiyg:20170319025609p:plain CentOSの公式ダウンロードサイトにいくと、↑のようにDVD ISO, Everything ISO, Minimal ISO の3種類がある。 Download CentOS


DVD ISO
CentOSGUIインストーラでインストールできる全パッケージが最初から含まれているディスクイメージ。ふつうにCentOSを使いたい人はとりあえずこれを選んでおけばOK。

Everything ISO
CentOSで利用できる全パッケージが最初から含まれているディスクイメージ。
ローカルミラーリポジトリを作りたい人向け(ふつうにCentOSを使いたい人は、あんまりこのISOファイルは選ばない)。 GUIインストーラでインストールできるもの以外のパッケージもすべて入っている。

Minimal ISO
必要最低限のパッケージだけが含まれているディスクイメージ。CentOSをインストールし終わったあとに、"yum install ○○" 等であとから自分で必要なパッケージを揃えてね、という感じ。

【Java】String#splitで、文字列が分割できない場合

Stringクラスのsplitメソッドで文字列が分割できない場合、その文字列自身が分割後配列の0番目の要素に入る


ふつうにsplitできる場合

String string = "AAA_BBB";
String[] splitStrings = string.split("_");

System.out.println(splitStrings.length);    //2 になる=> "AAA" と "BBB"に分割される


splitできなかった場合

String string = "AAA_BBB";
String[] splitStrings = string.split("_");

System.out.println(splitStrings.length);    //1 になる => 分割されず、配列の0番目にそのまま"AAA_BBB"という文字列が格納される
System.out.println(splitStrings[0]);        //"AAA_BBB" になる


以上、メモでした。

Windowsでシステムファイル属性の削除方法

システムファイル属性とは

システムファイルとは、OSの動作に必要なファイル群。通常はシステムフォルダなど特定の場所に集められており、ユーザが直接操作しないようになっている。システムファイルに異常が起こるとOSが起動しなくなることがある。内容はOSによって様々だが、OS本体のプログラムのほかに、OSやアプリケーションソフトの設定情報や、装着されたハードウェアを動作させるためのドライバソフトウェア、ユーザごとの環境設定(プロファイル)、システムの設定を変更するためのユーティリティソフト、アプリケーションソフトが利用する拡張機能を収めたライブラリファイルなどが含まれている。

引用:システムファイルとは|system file - 意味/定義 : IT用語辞典

つまり大事なファイルということ。


Windowsでシステムファイル属性を消したくなった。

その理由は、なぜか普通の音楽ファイルや普通の動画ファイルにシステムファイル属性が付いて、いろいろ厄介だったから。

普通のファイルにシステム属性がついてると、次のような面倒なことがある。
(1) Windowsでは、システムファイル属性がついたファイルの名前を変更しようとしたり、移動や削除しようとしたりすると、警告が出る。

(2) コマンドプロンプトから、dir をやっても表示されない。
 => dir /a:s とやると、システムファイルだけを表示させられる。

(3) バッチとか書いても、普通のファイルとして処理されないことも。
(今回、ファイルを一気に rename するバッチを書いたんだけど、システムファイルだけ「指定されたファイルが見つかりません。」になってしまって面倒だった)

消し方

Windowsでは、GUIからシステムファイル属性を消すことができないため、コマンドでやる必要がある。

attrib ファイル名 -s とすればOK.

ちなみに、attrib コマンドは、 Windowsコマンド集:(attrib)

Mac で CapsLock キーに Fn を割り当てる方法

Fnだと思ってCapsを押してしまう問題

学生のときはUS配列のキーボードを使っていたけど、会社のPCがJIS配列なこともあり、自宅用にJIS配列のMacBook Air を購入 (US配列のMacは大学からの借り物でした) 。
今までのMacの設定では、Fn+F1 や Fn+F2 で画面の明るさを変えたり、Fn+F11 や Fn+F12 で音量を変えたりできる設定だったので、Fn はかなりよく使う。
しかし、、、US配列のFnはキーボードの一番左下のキーだけど、JIS配列はそこがCapsLockになっている。それゆえに、US配列時代の癖で、Fnだと思ってCapsLockを押してしまうという問題が頻発...

f:id:yuukiyg:20160424014443p:plain

そこでCapsLockにFnを割り当てようとしたんだけど、最後までちゃんと解説しているページが意外と無かったのでここに書いておく。

CapsLock キーに Fn を割り当てる

環境

ハード:MacBook Air
OS:El Capitan(OS X 10.11.4)

1. 事前準備

システム環境設定→キーボード→修飾キーを開く。

ここで、CapsLockキーのところを「アクションなし」にしておく。 f:id:yuukiyg:20160424021250p:plain

2. Seilをインストール

Seil はCapsLockのキーの動作を変更するソフト。
ここからインストール Seil - OS X用のソフトウェア
今回はSeil-12.0.0 をインストールした。

3. Karabinerをインストール

Karabiner は OS X 向けのキーボードリマッパーソフト。
※ただし、Karabiner の説明ページ曰く、CapsLock は "Exceptional Key" なのでリマップできないらしい。代わりにSeil を使ってくれ、とのこと。
Karabiner はここからインストール Karabiner - OS X用のソフトウェア
今回はKarabiner-10.18.0 をインストールした。

4. 実際にCapsLock キーに Fn をリマップ

まず、Seil を起動する。Change the caps lock key のところにチェックを入れ、keycode の欄に 63 と入力。ちなみに 63 は Fn のキーコードを意味する。 f:id:yuukiyg:20160424023000p:plain


次に、Karabiner を起動。Change Key のタブが選択されている状態で、Fn+F1...F12 to Functional の欄にチェックを入れる。項目が多いので、検索欄で "fn" とか入れて検索するとすぐに見つかる。
f:id:yuukiyg:20160424023913p:plain

この状態で再起動すれば、CapsLockにFn が割り当てられ、 CapsLock + F1(or F2) で画面の明るさを変えたり、CapsLock + F11(or F12) で音量を調節したりできるようになる。

cron4j を使ってみた - JavaVM上 で動く cron

そもそも cron とは

cron とは、 定期的に or 指定した時刻に、何らかの処理を実行させたい場合に使うUNIX系のOSの仕組みです。いわゆるスケジューラというプログラムです。
サーバ管理を任されるとよく、「サーバのバックアップを取るためのプログラムを毎朝AM4:00に自動で動かす」みたいなことをしたくなります。そのときに cron というコマンドを使うことが多いです。
Windows でも、タスクスケジューラという似たような機能が使えます。使いにくいけど。

cron4j とは

cron を JVM上で実装するためのライブラリが cron4j です。これを使うと、Java で cron っぽいことをできるようになります。
つまり、このライブラリを使うと、「一度実行すると10分に1回 “Hello” と出力する Java のプログラム」などを簡単に書けるようになります。

cron4j を使ってみる

(1) まず、ここから cron4j-X.X.X.zip をダウンロードする cron4j - a pure Java cron-like scheduler

(2) その zipファイルを解凍する。

(3) 解凍して出てきたファイルに入っている cron4j-X.X.X.jar にパスを通す。
これで、Javaソースコードの中から cron4j の機能を呼べるようになります。

コードの書き方は、まず、cron で実行させたいモジュールを Runnable なクラスとして定義します。

class ScheduledTask implements Runnable{
    @Override
    public void run() {
        System.out.println("hello");
    }
}

次に、Scheduler の schedule()メソッドに、crontab でおなじみの “ * * * * * ” と、実行する Runnable なクラスを渡し、start() するだけ!
“ * * * * * ” の部分を変えてあげれば、1時間に1回実行とか、◯月◯日の×時×分に実行とか、色んなスケジュールを定義できます。
詳しくは、マニュアルを。cron4j - Documentation and manual

import it.sauronsoftware.cron4j.Scheduler;

public class Main {
    public static void main(String[] args) {
        Scheduler scheduler = new Scheduler();
        scheduler.schedule("* * * * *", new ScheduledTask());
        scheduler.start();
    }
}

これで、1分毎に “hello” と言うだけのプログラムが完成。

ただし、これだと Javaの 中で Runnable クラスで定義したコードしか実行できない。もっと、色んなコマンドとか実行させたいときは、ちゃんと本家の cron っぽい使い方もできるようになっています。

本家の cron っぽい使い方をする場合

本家の cron は crontab -eで設定ファイルとしてスケジュールを定義しておき、それを cron デーモンが読み込んで実行するという形態。
これと同じように、外部ファイルにスケジュールを定義して、それを定期的に実行する方法があります。つまり、JVM で動く cron デーモンを作っているような感じです。

まずは、実行させたい外部ファイルを定義し、テキトーにcrontab.txt と名付けます。

* * * * * say "hello" 

自分は Mac を使っているので、say コマンドが使えます。これは、引数に渡した文字列を Mac が喋ってくれる(音声が出る)というコマンドです。

コマンド/say - MacWiki


次に、Java コードはこれだけです。

import it.sauronsoftware.cron4j.Scheduler;

public class Main {
    public static void main(String[] args) {     
        Scheduler scheduler = new Scheduler();
        scheduler.scheduleFile(new File("crontab.txt"));
        scheduler.start();
    }
}

これで実行すると、1分に1度、Mac が “Hello” って喋ってくれます。


また、外部ファイルからスケジュールを読んで実行させたいけど、実行させる内容は Java コード内に書きたい!という場合は、public クラスを作り、static 修飾子がついて、引数に String クラスの配列を取るメソッドを定義する必要があります。

public class Test{
    public static void print(String[] s){
        for(int i=0; i<s.length; i++)
            System.out.println(i+"番目の引数: " + s[i]);
        System.out.println();
    }
}

こんな感じ。

そして crontab.txt の中身は、

* * * * * java:Test#print "こんにちは" "Hello" "ni hao"

のように、「java:クラス名#メソッド名 引数1 引数2 …」とします。

これを実行すると、

0番目の引数: こんにちは
1番目の引数: Hello
2番目の引数: ni hao

が、1分毎に出力されるだけの関数が作れました。こんな感じで、外部ファイルから Java 内で定義したメソッドを呼び出して使います。




これで Java で cron と同じことができるようになります。

RubyでTwitterのBotを作ってみた(後編)

RubyTwitterBotを作ってみた(前編)RubyでTwitterのBotを作ってみた(前編) - A little bit of everything のつづき。
OS X ver.10.9.5 でやってます。

テキストファイルにTweetする内容を列挙しておいて、Postするときにランダムに1つ取ってきてTweetする。みたいなことをやる。
まずは、txtファイルにTweet内容を列挙。

Hello World!
This is a message from Ruby.
I am a bot.
Are you serious?

これを tweet.txt として保存。
前編に書いたプログラムをちょっと修正。

# coding: utf-8
require "twitter"
require 'oauth'

client = Twitter::REST::Client.new do |config|
  config.consumer_key = "XXXXXX"
  config.consumer_secret = "YYYYYY"
  config.access_token        = "ZZZZZZ"
  config.access_token_secret = "XYZXYZ"
end

s=[]

#Fileは絶対パスじゃないと怒られる可能性あり
File.open("/XXX/YYY/ZZZ/tweet.txt","r") do |l|
  l.each_line do |line|
    s.push(line)
  end
end
client.update(s.sample)

参考 Rubyで書いたTwitterのbotをRaspberry Piで動かす - DesignAssembler

これをcronで動かす。
crontab -e でエディタが開くので、

*/1 * * * * ruby /XXX/YYY/ZZZ/index.rb

と書いてみる。
*/1は1分毎に実行という意味。(とりあえず動作を確認したいので、最初は1分毎)
あと、ファイル名は絶対パスじゃないと怒られる可能性あり。 (怒られる場合はcronから/var/mail/にメールが届く)
これでもしPermission Denied だったら、index.rbの権限を変えてあげる。 chmod u+x index.rb

これで1分に1回Tweetされれば成功!
あとはさっきのcrontabで、Tweetしてほしいタイミングに書き換えてあげればOK.

【追記】

tweet.txtの中身が日本語だとエラーが出た。

/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/uri/common.rb:304:in `gsub': invalid byte sequence in US-ASCII (ArgumentError)
    from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/uri/common.rb:304:in `escape'
    from /Library/Ruby/Gems/2.0.0/gems/simple_oauth-0.3.1/lib/simple_oauth/header.rb:32:in `escape'
    from /Library/Ruby/Gems/2.0.0/gems/simple_oauth-0.3.1/lib/simple_oauth/header.rb:114:in `block (2 levels) in normalized_params'
    from /Library/Ruby/Gems/2.0.0/gems/simple_oauth-0.3.1/lib/simple_oauth/header.rb:114:in `collect'
    from /Library/Ruby/Gems/2.0.0/gems/simple_oauth-0.3.1/lib/simple_oauth/header.rb:114:in `block in normalized_params'
    from /Library/Ruby/Gems/2.0.0/gems/simple_oauth-0.3.1/lib/simple_oauth/header.rb:114:in `collect'
    from /Library/Ruby/Gems/2.0.0/gems/simple_oauth-0.3.1/lib/simple_oauth/header.rb:114:in `normalized_params'
    from /Library/Ruby/Gems/2.0.0/gems/simple_oauth-0.3.1/lib/simple_oauth/header.rb:110:in `signature_base'
    from /Library/Ruby/Gems/2.0.0/gems/simple_oauth-0.3.1/lib/simple_oauth/header.rb:101:in `hmac_sha1_signature'
    from /Library/Ruby/Gems/2.0.0/gems/simple_oauth-0.3.1/lib/simple_oauth/header.rb:97:in `signature'
    from /Library/Ruby/Gems/2.0.0/gems/simple_oauth-0.3.1/lib/simple_oauth/header.rb:77:in `signed_attributes'
    from /Library/Ruby/Gems/2.0.0/gems/simple_oauth-0.3.1/lib/simple_oauth/header.rb:83:in `normalized_attributes'
    from /Library/Ruby/Gems/2.0.0/gems/simple_oauth-0.3.1/lib/simple_oauth/header.rb:65:in `to_s'
    from /Library/Ruby/Gems/2.0.0/gems/twitter-5.15.0/lib/twitter/headers.rb:36:in `auth_header'
    from /Library/Ruby/Gems/2.0.0/gems/twitter-5.15.0/lib/twitter/headers.rb:27:in `request_headers'
    from /Library/Ruby/Gems/2.0.0/gems/twitter-5.15.0/lib/twitter/rest/request.rb:31:in `perform'
    from /Library/Ruby/Gems/2.0.0/gems/twitter-5.15.0/lib/twitter/rest/utils.rb:50:in `perform_request'
    from /Library/Ruby/Gems/2.0.0/gems/twitter-5.15.0/lib/twitter/rest/utils.rb:72:in `perform_request_with_object'
    from /Library/Ruby/Gems/2.0.0/gems/twitter-5.15.0/lib/twitter/rest/utils.rb:64:in `perform_post_with_object'
    from /Library/Ruby/Gems/2.0.0/gems/twitter-5.15.0/lib/twitter/rest/tweets.rb:158:in `update!'
    from /Library/Ruby/Gems/2.0.0/gems/twitter-5.15.0/lib/twitter/rest/tweets.rb:128:in `update'
    from /Users/Yuuki/Desktop/bot/index.rb:19:in `<main>'

解決策は、tweet.txtを開くときにエンコードを指定してやる。こんなふうに。

# coding: utf-8
require "twitter"
require 'oauth'

client = Twitter::REST::Client.new do |config|
  config.consumer_key = "XXXXXX"
  config.consumer_secret = "YYYYYY"
  config.access_token        = "ZZZZZZ"
  config.access_token_secret = "XYZXYZ"
end

s=[]

#Fileは絶対パスじゃないと怒られる可能性あり
#Fileを開くときに、utf-8としてopen
File.open("/XXX/YYY/ZZZ/tweet.txt","r:utf-8") do |l|
  l.each_line do |line|
    s.push(line)
  end
end
client.update(s.sample)

これでOK!


【追記2】

実験をしていて、
①「同じ内容がTweetされないぞ?」とか、
②「1分間隔で設定しているのに、2分以上間隔をあけてTweetされたりするぞ?」
という現象が起こった。

調べたら、Twitterでは、ここの記事のとおり、同じ内容はある程度時間をおかないとTweetできないみたい(もしくは、10Post以上の間隔をあける)。これが原因。

cronでrbを実行して、ランダムにTweet内容を選んでTweetしようとしたけど、以前と同じ内容だったのでできない。というパターンが①。
何度かcronで実行するうちに、以前と違う内容が偶然選ばれればTweetされる。だから2分以上の間隔があいた。というパターンが②。