Final Fantasy XIV: オープンβをやってみた

Final Fantasy XIVのオープンβを遊んでみた!!

クローズβに参加していた友達が先に仕事終わったし、ログインしていろいろ終わらせていたので、スカイプで説明してもらいながら、うろうろと・・・

キャラメイクは、いつも短時間で終わるので、今回も5分もかからなかったかなぁ・・・

俺と同じタイプのの猫は多いのに、みんな白いのね。

黒いのはまったく見かけない・・・青いのがいた!!たぶん、外国人っぽい雰囲気が・・・w

Final Fantasy XIV Open Beta

Final Fantasy XIV Open Beta

まあ、仕事もあるので、無理しない程度にがんばるかな。

今回も、起動時にしか画面サイズ変更できないようになっているね。FF11はバックバッファーが1280×1024しか対応してなくて、ワイド画面だと潰れてた。で、今回はバッフバッファーとか、シャドウマップのサイズとか調節できるのね。シャドウマップは思いし、影なんてそんなに品質上げても仕方がないし、このあたりは設定を普通くらいで。ほかは最高品質でプレイしている。

被写界深度をONにしているので、若干フォーカスっぽい演出がかかっているねー

それにしても黒猫可愛いと思うんだけれどなぁ・・・今のところ友達には不評w
友達は、サンシーカーで明るい猫にしたみたい。

ま、俺は黒猫気に入ったので、正式サービスを遊ぶとしても、同じ猫にするね!!

30インチモニターも対応しているみたいなので、やっぱり、30インチモニター買おうかな~

SQUARE ENIX: The 3rd Birthday

The 3rd Birthday

パラサイト・イブの続編の情報が更新されていたのね。
随分前に、ドコモ用携帯アプリで出すみたいな話もあったかと思うんだけれど、PSPに落ち着いたみたいだね。グラフィック的にやれることは、ドコモアプリの最新機種もPSPもそれ程変わらないんだけれど、画面サイズとインターフェイスとメモリ容量とか、リソース容量が違うからね・・・本格的にゲーム作るならPSPの方がいいね。
個人的には、ムービー用の3Dモデルが好みだから、PS3で出して欲しかった・・・

ムービーでは、使っているスキルはOVERDIVEだけっぽいんだけれど、他のスキルはどこにいったんだ?!

ってか、今までのアヤ・ブレアの記憶ないのかね・・・?
色々新しくなってそうだなぁ・・・まあ、前作からして10年も前だしね・・・

一作品目も二作品目も、まだゲームメディア持っていたはずだな。そのうちまたプレイするかな~

Diary: 引越し

また引越し。
自分でも、余り引越しはしたくないとは思うんだけれど・・・多いね。
しかも、今回は長野市に引越し。インターネット回線も2週間以上止まるので、このサイトも暫くアクセス不能になります。

インテグラは残念な事にまだ見つかっていないので、長野に行ったらCBRのほうが活躍することに・・・それなりに田舎だから、車必要だと思うんだよね。

さて、ちょっと用事があって上野に行ったので、ついでに浅草寄ってこようと思って、上野駅から浅草まで歩きました。

途中で見かけたスカイツリー。

スカイスリー

スカイツリー

そして雷門。

雷門

雷門

更に山形の人たちが毎年奉納している草履。

草履

草履

最後に舟和。ここの芋羊羹は美味しい。中学のときの修学旅行でここの芋羊羹を購入したのはいいけれど、ホテルを出て直ぐにホテルの冷蔵庫に忘れたのに気が付いてバスを止めたぜ。そういえば、修学旅行実行委員長だったな。

舟和

舟和

まあ、次は長野を観光でもしますかね。善光寺があるよ!!戸隠神社があるよ!!バイクで直ぐだーわー

Cassandra: Cassandra のデータモデル

まずは、公式wikiで日本語訳があるので、そちらの紹介。

DataModel_JP – Cassandra Wiki

次にDiggのエンジニアの人のブログと、その翻訳をしてくれた人のブログの紹介。
WTF is a SuperColumn? An Intro to the Cassandra Data Model
Cassandraデータモデル入門 – Arin Sarkissian

最後にウノラボの記事。
今からはじめるCassandra入門

一番データモデルに関して詳しいのは、Arin Sarkissianさんの記事だね。blogを構築する場合のデータモデル設計例を出してくれているのが大きい。
公式のwikiでも理解出来ないことはないけれど、実例がないからね。

リレーショナルデータベースとの一番の違いは、Columnが固定長じゃない事かな。Key-Value-Storeだから、当然、キーとバリューの関係を次々増やしていける。で、Key-Value-Timestampが1つのColumnなので、自然な流れとして、Columnは増えていく。

更に、リレーショナルという関係がないので、一つのキーを元に複数のバリューを参照したい場合には、SuperColumnという概念が登場する。SuperColumn自体は、通常のColumnとは違い、ハッシュマップでしか無い。つまり、キーを元に複数のColumnを参照する事になる。そして、SuperColumnには、Timestampが存在しない。

そして、ColumnFamilyは、Column, SuperColumnをグルーピングする為の存在。単一のデータ群とみなせるなら、それはColumnFamilyとして纏まる。

最後に、Keyspaceは、データモデルとしては最上位の名前空間といったところかな。リレーショナルデータベースの、データベース名に当たる。

1つのキーで所得したいColumn数が後から増える場合にはこれは非常に便利だ。リレーショナルデータベースの場合は、Tableを追加して、リレーション関係を構築して行うか、ADD COLUMN を行う事になる。どちらにしても、再設計が必要になる。

重要なのが、Nameでソートされる事だろうか。これを利用して、サンプルではエントリーをソートしてる。

ちょっと、Pythonで書いてみた。

エントリー編

from thrift import Thrift
from thrift.transport import TTransport
from thrift.transport import TSocket
from thrift.protocol.TBinaryProtocol import TBinaryProtocolAccelerated
from cassandra import Cassandra
from cassandra.ttypes import *
import time
import pprint
import uuid

def main():
  socket = TSocket.TSocket('localhost', 9160)
  transport = TTransport.TBufferedTransport(socket)
  protocol = TBinaryProtocol.TBinaryProtocolAccelerated(transport)
  client = Cassandra.Client(protocol)
  pp = pprint.PrettyPrinter(indent=2)

  keyspace = 'BloggyApply'

  try:
    transport.open()

    column_path = ColumnPath(column_family='BlogEntries', column='title')
    key = '001'
    value = '001 title'
    timestamp = time.time()

    try:
      # Insert blog entry.
      client.insert(keyspace,
                    key,
                    column_path,
                    value,
                    timestamp,
                    ConsistencyLevel.ZERO)

    except Thrift.TException, tx:
      print "Thrift: %s" % tx.message

    column_path = ColumnPath(column_family='TaggedPosts', column=uuid.uuid1().bytes)
    key = '__notag__'
    value = '001'
    timestamp = time.time()

    try:
      #Insert the data into TaggedPosts
      client.insert(keyspace,
                    key,
                    column_path,
                    value,
                    timestamp,
                    ConsistencyLevel.ZERO)
      #Query for data
      column_parent = ColumnParent(column_family='TaggedPosts')
      slice_range = SliceRange(start='', finish='')
      predicate = SlicePredicate(slice_range=slice_range)
      result = client.get_slice(keyspace,
                                key,
                                column_parent,
                                predicate,
                                ConsistencyLevel.ONE)

      pp.pprint(result)

    except Thrift.TException, tx:
      print "Thrift: %s" % tx.message

  except Thrift.TException, tx:
    print "Thrift: %s" % tx.message
  finally:
    transport.close()

if __name__ == '__main__':
      main()

コメント編。

from thrift import Thrift
from thrift.transport import TTransport
from thrift.transport import TSocket
from thrift.protocol.TBinaryProtocol import TBinaryProtocolAccelerated
from cassandra import Cassandra
from cassandra.ttypes import *
import time
import pprint
import uuid

def main():
  socket = TSocket.TSocket('localhost', 9160)
  transport = TTransport.TBufferedTransport(socket)
  protocol = TBinaryProtocol.TBinaryProtocolAccelerated(transport)
  client = Cassandra.Client(protocol)
  pp = pprint.PrettyPrinter(indent=2)

  keyspace = 'BloggyApply'

  try:
    transport.open()

    super_column = uuid.uuid1().bytes
    values = dict()
    values['commenter'] = 'Hoge Mash'
    values['email'] = 'hoge@hoge.com'
    values['comment'] = 'my comment...'

    column_path = ColumnPath(column_family='Comments', super_column=uuid.uuid1().bytes)
    super_key = '002'
    timestamp = time.time()

    try:
      # Insert blog entry.
      for column in values:
        column_path.column = column
        client.insert(keyspace,
                      super_key,
                      column_path,
                      values[column],
                      timestamp,
                      ConsistencyLevel.ZERO)

    except Thrift.TException, tx:
      print "Thrift: %s" % tx.message

    try:
      #Query for data
      column_parent = ColumnParent(column_family='Comments')
      slice_range = SliceRange(start='', finish='')
      predicate = SlicePredicate(slice_range=slice_range)
      result = client.get_slice(keyspace,
                                super_key,
                                column_parent,
                                predicate,
                                ConsistencyLevel.ONE)

      pp.pprint(result)

    except Thrift.TException, tx:
      print "Thrift: %s" % tx.message

  except Thrift.TException, tx:
    print "Thrift: %s" % tx.message
  finally:
    transport.close()

if __name__ == '__main__':
      main()

これを見て分かると思うけれど、リレーショナルデータベースで既に組まれているシステムを、Cassandraに置き換えるのは、大変な努力が必要だね。データ構造も違うし、プログラム側の処理も全然違うものになってしまう。リレーショナルデータベースみたいに、日付でソートしようと思うだけで、2箇所にデータを入れないといけないという。
CassandraのIOアクセスの速さの理由に、データが常にソートされた状態で保存されている。というのがあるから、ソート順番が決まっているデータにしか使えないっていうのもあるね。ソートをいじるということは、一度データベースを止めないといけない気がする。

そんな訳で、リレーショナルデータベースが得意な部分と、Cassandraが得意な部分を見つけて、うまく混ぜて使うのがいいんじゃないかなと思う。一貫性や、トランザクションを使いたいデータとかはリレーショナルデータベースがいいし、ある程度矛盾や壊れてもいいようなデータで、負荷が高いものは、Cassandraとなるのだろうか。
う~ん、これは本当に使いどころを考えるのが難しいね。サーバプログラムでローカルのメモリ上には持つには大きすぎるような構造体を、Cassandraに持たせてしまうとかだろうか。それでいて、一貫性が緩くても良いもの。
DynamoはAmazonのショッピングカートで使っているっていう話だけれど・・・
後は、単純な集計結果のキャッシュかな。それが、Memcachedを使うよりもCassandraのほうがいい。ってのがあるならいいんだけれど・・・まあ、データ構造が持てる分、複数の集計結果を1度に取得出来るとかはあるか。集計結果がスケールアウトする程の物量になるのか?!っていうのもあるね。

後は、リレーショナルデータベース+Cassandraでデータベース定義を作る事かな。トランザクションが使えないから、MySQLなら、MyISAMで構築していた部分をCassandraに持って行けるなら、特に問題はなさそう。1テーブルが余りにも肥大化しすぎてメモリに乗らないようなデータもCassandra向きかなぁ
2重管理はしたくないから、その辺りが落しどころなのかな・・・Cassandraも持っていて、リレーショナルデータベースも持っている。なんていうデータは作りたくないし。

Final Fantasy XIV: システム的な作業だ!!

この動画を見ていたんだけれど、デザイナーでシステム的に考えられる人がいるんだなぁと思った。

MMORPGでは、要素数が多ければそれだけユーザーが感じられる世界に広がりが出てくると自分は思うんだよね。同じメッシュでもマテリアルを変えるだけで、質感もテクスチャも変わる訳だし、DirectXでいうアトリビュートを積極的に使う構成をすれば、マテリアル情報も節約出来るんだよね。

モーションとボーン構造を考えると、プログラム側では、パーツ単位で持っている気がするけれど・・・
この装備品は、このオリジナルモデルのどのパーツを表示させるかと、そのパーツはどのマテリアルに関連付けるか。を持っていればいい訳だし、それ程プログラム設計も複雑にはならない。
むしろ、MAYAとかはそういうデータ構造をしているし。

数を作るためにはどうすればいいか。というので、オリジナルを100個準備するのではなく、10個のオリジナルから、10個ずつの派生パターンを作ればいい。と考えたんじゃないだろうか。

システムエンジニアを経験したせいか、自分のプログラムとかシステム設計ってひたすら、こういう設計になっていくんだよね。

例えば、モンスターのバランス設定をシステム的にしようという話をした時に、そんなのはやったことがないから、無理。って言われたらどうする!?。システム的な考え方が出来る人ならいいけれど、そうじゃない場合モンスター1匹1匹、全ステータス、スキルを手入力!?結局、コピペしたり、コピペミスとか、コピペそのままでリリースとかして、ミスが多くなるかと思われる。
まあ、これはアナログなやり方で、自分みたいに、設計が大好きな人間には、激しくあほくさい事しているとしか思えない。オブジェクト指向や関数やループを使わないで、ひたすらソースコードべた書き的な印象だね。

システム的に考えると、プレイヤーとモンスターのレベル差で強さを決める場合もあるし、単純にレベル毎に補正値がかかるようになっている場合もあると思う。どちらにしても、100種類のモンスターがいたとしても、100種類全部のベースレベルが10なら、基本的な強さは同じになる。これは、データ量も少なくて済む。

最初音1匹1匹個別設定では、確実に変数を全部持たないといけないが、レベル依存の場合、10レベルでの強さ、50レベルでの強さを持っているだけでいいので、100匹のモンスターをレベル1~50まで作成した時、50×100 か 50 の違いがでる。

で、更にそれじゃ面白くないだろうから種族を加える。FF11で言うなら、クロウラー系は防御力低めの補正値、攻撃力高めの補正値、デーモン族は防御力、攻撃力高めの補正値。10種族準備して、先程の100匹作ったら。という仮定に均一に種族を割り振っても 50×10 で済む。リレーショナルデータベース的にもこちらのほうが優しい。

ここまで来ると後は簡単で、レベル依存でモンスターの大きさを変えたいとか、モンスターが使うスキルを設定したいとか、種族単位で設定するなり、統一で設定するなりも出来る。

このほうが、モンスターのバランス調節をする時も楽だし、新しい種族を追加したとしても、種族特性だけを吟味すればいいから作業も少ないと思われる。

で、動画の話だけれど、スクウェア・エニックスのデザイナーの人は、よくこういう設計でいく。っていうのを押しとせたなぁと思う。結構、スクウェア・エニックスのゲームデザインって思いっきりがある時がたまにあるんだよね。

FF11では、プレイヤー、モンスターの見た目は表示されないけれど、チャットもターゲットも、レーダーにも映る。っていう状態がある。つまり、見た目が表示されない以外のゲームとしての機能は全て動く。これは、見た目が一番不可の高い処理で、そこに存在している。って事を処理するのは大した負荷がかからないからだ。MMORPGの設計としては、理想的だと思っている。しかし、これが許容できない場合、表示しないなら、いないことにする。だ。

え!?って感じがするのは自分だけなのかな。FF11みたいに、見た目が表示されない状態のほうが明らかにプレイに支障がないと思うんだけれど。特に、マップの移動を早くして、キャラクターの表示はマップを歩いている間に、少しずつ表示されていく。っていう特性を持っていたりする。これこそ、ストレスを感じさせない良いシステムだと思うんだけれど。

ゲームの進行スレッドと描画スレッドは基本的に、基本的にHDDにアクセスしないから、それとは別にHDDからモデルデータを読み取るスレッドがあれば、ゲーム進行に支障をきたすことなく、データ読み込みが出来るし、マルチスレッド化としても理想的な割り振りになるかと。FF14は更にマップもシームレスになっているしね。

プログラムには必ずトレードオフな部分があって、絶対に両立させられない。っていうのがいくつも存在する。それを、踏まえた上でFF11は良い設計をしているなぁと思う。ってかねぇ・・・FF14何でもかんでもノーマルマップ貼ってるだろう・・・どんだけ贅沢なんだよ!!確かに凄いけれど、負荷高いよ!!テクスチャデータ転送されまくりだよ!!w
ノーマルマップはプログラム側でON/OFF切り替えしやすい項目ではあるけれど・・・

まあ、正直、スクウェア・エニックスのデザイナーは作業工数が凄い多いし、テクスチャ班が存在するから、ノーマルマップ班も存在するんだろうけれど・・・それでも、プログラムの処理負荷は軽くならないよ!!プログラマー頑張り過ぎだな!!w しかも、シームレスマップだしなぁ・・・作ってて楽しそうだなぁ・・・w
これが、PS3で動くってことは、過去最高レベルに、PS3の性能引き出してるんじゃね!?w

Cassandra: Cassanra のセットアップ

The Apache Cassandra Project

openSUSE 11.3 に Cassandra 0.6.4 をセットアップしてみたのでメモ。
Debian は既にパッケージングされていて、apt-get で入れる事ができるみたい。

自分はまだ、sun の java を使う人なので、sun に入れ替えて環境構築。
openSUSE 11.3 だと、デフォルトでは、OpenJDK にPATHが通っているので、/usr/lib64/jvm 以下のシンボリックリンクを自分で調節するか、アンインストールして、sun の jdk を入れればいいかな。
もっとスマートな設定ファイルがどっかにありそうだけれど・・・su -

yast --remove java-1_6_0-openjdk
yast -i java-1_6_0-sun

最初に、binary を公式からダウンロード。

wget ftp://ftp.kddilabs.jp/infosystems/apache/cassandra/0.6.4/apache-cassandra-0.6.4-bin.tar.gz
tar zxf apache-cassandra-0.6.4-bin.tar.gz
su -
mv apache-cassandra-0.6.4-bin.tar.gz /usr/local/
ln -s /usr/local/apache-cassandra-0.6.4-bin.tar.gz /usr/local/cassandra

# 起動
/usr/local/cassandra/bin/cassandra -p /var/run/cassandra.pid

# 停止
kill -KILL `cat /var/run/cassandra.pid`

デフォルトでは、bin/cassandra.in.sh を読み込む設定になっているので、独自の設定を読み込ませたい場合には、このファイルをコピーして、そちらを読むように指定するのも可能。

cp bin/cassandra.in.sh /tmp/new.in.sh
vim /tmp/new.in.sh
$CASSANDRA_INCLUDE=/tmp/new.in.sh bin/cassandra -p [pid_file]

終了するとき、killコマンドを使うしか無いようだ。まあ、いいんだけれど。pidファイルがあると、cat でプロセスIDを表示して、kill コマンドを発行できるので、そこは楽だね。

デフォルトでは 8080 port で起動するようになっているので、これが嫌な人は、bin/cassandra.in.sh を編集すればいい。
-Dcom.sun.management.jmxremote.port=8080
が、portを指定している部分。

JVM_OPTS=" \
        -ea \
        -Xms256M \
        -Xmx1G \
        -XX:+UseParNewGC \
        -XX:+UseConcMarkSweepGC \
        -XX:+CMSParallelRemarkEnabled \
        -XX:SurvivorRatio=8 \
        -XX:MaxTenuringThreshold=1 \
        -XX:+HeapDumpOnOutOfMemoryError \
        -Dcom.sun.management.jmxremote.port=8080 \
        -Dcom.sun.management.jmxremote.ssl=false \
        -Dcom.sun.management.jmxremote.authenticate=false"

Java なだけあって、単純に起動するだけなら簡単。

log : /var/log/cassandra
data : /var/lib/cassandra/data

起動時にログを吐き出すので、それで構成を確認すればいいかな。

後は、ちょっと接続テスト。

/usr/local/cassandra/bin/cassandra-cli

# サーバに接続
cassandra> connect localhost/9160
# Keyspaceを確認
cassandra> show keyspaces
# Keyspaceの構成を確認
cassandra> describe keyspace Keyspace1

# データセット
cassandra> set Keyspace1.Standard2['jsmith']['first'] = 'John'
Value inserted.
cassandra> set Keyspace1.Standard2['jsmith']['last'] = 'Smith'
Value inserted.
cassandra> set Keyspace1.Standard2['jsmith']['age'] = '42'
Value inserted.

# データ取得
cassandra> get Keyspace1.Standard2['jsmith']
=> (column=last, value=Smith, timestamp=1271921526614000)
=> (column=first, value=John, timestamp=1271921521923000)
=> (column=age, value=42, timestamp=1271921532713000)
Returned 3 results.

1つの Key に対して、複数の Column を関連付けていくので、RDBMS に慣れていると最初戸惑いが・・・まあ、カラムを動的に追加していく。ってことだね。住所が必要なら、 set keyspace1.Standard2['jsmith']['address'] = ‘New York City’ とでも入れればいいし。

Python: Cassandra: Python で Cassandra に接続する

Cassandra へのアクセスでベースになっているプロトコルが Thrift のようだ。
Cassandra用のPythonライブラリが、python-cassandra の模様。これが、Thrift に依存している。

Python 開発環境を作るのも久しぶりだったので、こちらのサイトを参考に構築。
2009年版Python開発環境を整えよう
環境は OpenSUSE 11.3 Cassandra 0.6.4

su -
yast -i python python-devel gcc python-setuptools
easy_install virtualenv
easy_install virtualenvwrapper
exit
vim ~/.bashrc

# 以下を .bashrc に追加
# Import virtualenvwrapper
if [ -f /usr/local/binvirtualenvwrapper.sh ]; then
  source /usr/local/bin/virtualenvwrapper.sh
fi

mkdir ~/.virtualenvs

source ~/.bashrc

mkvirtualenv --python=/usr/bin/python2.6 cassandra

# bashの表示が変わる。
(cassandra)user@domain:>

pip install thrift
pip install python-cassandra

これで完了。特につまるところはないかなぁ C言語で書かれているモジュールっぽいので、gcc は必要みたいだね。で、その為に、Python.h が必要だから、python-devel を入れておく必要性がある。

ちなみに、virtualenv はローカル環境構築用なので、pipでインストールしたライブラリは ~/.virtualenvs/cassandra/lib/python2.6/site-packages 以下に入る。

サンプルはこちら拝借。
ThriftExamples – Cassandra Wiki

#!/usr/bin/env python # encoding: utf-8
"""Sample Cassandra Client

Created by Chris Goffinet on 2009-08-26."""

from thrift import Thrift
from thrift.transport import TTransport
from thrift.transport import TSocket
from thrift.protocol.TBinaryProtocol import TBinaryProtocolAccelerated
from cassandra import Cassandra
from cassandra.ttypes import *
import time
import pprint

def main():

    socket = TSocket.TSocket("localhost", 9160)
    transport = TTransport.TBufferedTransport(socket)
    protocol = TBinaryProtocol.TBinaryProtocolAccelerated(transport)
    client = Cassandra.Client(protocol)
    pp = pprint.PrettyPrinter(indent=2)
    keyspace = "Keyspace1"
    column_path = ColumnPath(column_family="Standard1", column="email")
    key = "1"
    value = "foobar@example.com "
    timestamp = time.time()
    try:
        transport.open()
        #Insert the data into Keyspace 1
        client.insert(keyspace,
                      key,
                      column_path,
                      value,
                      timestamp,
                      ConsistencyLevel.ZERO)
        #Query for data
        column_parent = ColumnParent(column_family="Standard1")
        slice_range = SliceRange(start="", finish="")
        predicate = SlicePredicate(slice_range=slice_range)
        result = client.get_slice(keyspace,
                                  key,
                                  column_parent,
                                  predicate,
                                  ConsistencyLevel.ONE)
        pp.pprint(result)
    except Thrift.TException, tx:
        print 'Thrift: %s' % tx.message
    finally:
        transport.close()

if __name__ == '__main__':
    main()

pycassa というのもあるみたいだけれど、これ以上ラッピングしても意味あるのかなぁ~ DjangoみたいなWebフレームワークに組み込まれるくらいかな?

Linux: logrotate で log 圧縮設定

Apache の VirtualHost とかの設定をして、ついつい忘れてしまうのがログの圧縮設定。
Linux の場合 logrotate を使ってログを圧縮しているので、こちらの設定を変更しよう。

/etc/logrotate.conf

上記ファイルを見ると、以下のディレクトリのファイルを include しているのが分かる。

/etc/logrotate.d

という訳で、独自の設定をする場合には新しくファイルを作成して、Apache の場合には、apache とか apache2 で既にファイルがあると思うので、そちらを編集。

/var/log/apache2/blog.redhawk.jp-access.log {
    compress
    dateext
    maxage 365
    rotate 99
    size+=4096k
    notifempty
    missingok
    create 644 root root
    postrotate
     /etc/init.d/apache2 reload
    endscript
}

ログファイルに対して、コマンドを設定していく。
compress : ログを圧縮する
nocompress : ログを圧縮しない
compresscmd : 圧縮コマンドを指定
uncompresscmd : 解凍コマンドを指定
daily : 毎日
weakly : 毎週
dateext : 日付を拡張子にする
missingok : ファイルが無い場合でもエラーを出力しない
nomissingok : ファイルが無い場合エラーを出力する
rotate : ログファイルのローテート回数。指定ファイル数に達すると古いものから削除される
size : 指定したサイズ以上の場合は、ログをローテートする
prerotate : endscript までのコマンドをローテート実行前に実行する
postrotate : endscript までのコマンドをローテート実行後に実行する

こんなところかな。
圧縮さえしておけば、HDDがパンクする可能性が低くなるし。ログ消えて困るんだったら、HDDパンクしない程度にsizeとかrotate調節して、後はバックアップを取りつづけることかな。ログファイルがいつまでも可動サーバー上に安全な状態で残るとは限らないからね。

ライトノベル: ゼロの使い魔 18 19

1年ぶりくらいにゼロの使い魔を読んでみる。

なんか、久しぶりに読んだせいか、エロい部分を余りしつこく感じなかった。

18巻はロマリアがサイトたちを丸め込む話。しかし、こいつらは情報を握っているだけあって強いね。サイトとかは、余りにもハルケギニアという世界に対する情報が少なすぎる。そのおかげで、色々踊らされておりますなぁ・・・まあ、今は最後の章に向けての、序章といった感じで、結構穏やかな感じで物語が進んでいっている気がする。アルビオンの時のようなバトルもないしねぇ~ まあ、じわじわと進めていきたい人なのかな?

19巻はついにエルフが話に本格的に絡んでくる。今まで作ってきたエルフとの伏線を回収しつつ、新しい謎が生まれていく感じ。ここを突破すれば、一気にハルケギニアの真相に辿りつくんじゃないだろうか。本自体の厚さも余りないから、それ程急展開っていうのも期待していなかったけれど、まじで進むのがゆっくりだなぁ・・・もうね、ゆっくりすぎて、昔の事は忘れてしまうよ!!2年前に読んだ部分を持ち出されても、そうだっけか?って感じw

まあ、読んでいてつまんないってことはないし、面白い部類ではあるんだけれどねぇ・・・もうちょっと何かを求めてしまうね。
無駄にえろくてダラダラしてる部分も減ってきたから、またファンタジーの世界を楽しませて欲しい!!

ライトノベル: とある飛空士への恋歌 4

最新刊発売したので、早速読んでみた!!

クライマックスという事で、どの程度クライマックスなのかと思ったら、怒涛の展開がひたすら続く感じ。言葉を借りるなら「最初から最後までクライマックスだぜ」って感じw
まあ、物語の大きな流れとしては、1歩進んだ感じで、まだまだこれからも怒涛の展開が続きそうな印象を受ける。つまり、まだ終わんねぇーーって自分は見てる。
クライマックスっていうから、あと1巻くらいで終わるのかなぁって思ったけれど、どうにもそうじゃないような感じがするんだよね。

さて、今回も読み応えのある1冊でした。内容が濃くて、読むのも疲れるので、もうちょっと色々書いてくれても。って思いつつも、1冊にまとめるにあたってこの辺りがちょうどいい具合かな。と思った。余り量が多すぎると、読んでる方もダレてくるんだよね・・・

今まで多かった、おちゃらけた部分、まあ、ドタバタしてるようなのは、殆どなくなっていて、シリアスな展開ばかりが続く。カルエルにも、アリエルに代わって新しいパートナーが出来るし、今後この二人の展開が楽しみ。なんだかんだで、息があっているので、このペアには奮闘して欲しいものだ。

気になるのが、アリエルってカルエルの事を好きだと思ったいたんだけれど、カルエルとクレアが両想いなだけに、この先どうなるんだ!?って思ったり・・・アリエルの性格からして、特に何もなさそうな気もしないでもないけれど、今後何かあるんだろうか・・・?w

そして、プロペラ同調装置が出てきたね。これは、零式艦上戦闘機(零戦)に搭載されていたやつで、弾数が少なくなるから瞬間的な火力は劣るんだけれど、発射軸が機体の軸と同じになるから、狙いやすいというやつだね。

しかし、相変わらず、森沢晴行さんの描くキャラは可愛い。岸田メルさんのイラストと並んでお気に入りだね。気になるのが、クレアの時と、ニナの時で胸の大きさが明らかに違うんだが・・・どゆこと!?偽乳か!?まあ、いいんだけれど・・・