2015年12月30日水曜日

EdgeRouterLiteを触ってみる

このブログはすごい広島#137の成果です。
(なお、この日は同時にとても大事なイベントがあったのですが、あくまで「すごい広島」ということで・・・)

VyattaからフォークしたVyOSをMIPSなCPUで動くように移植したEdigeRouteLiteを購入しましたので、まずはつなげれるように最低限IPの設定をしました。

このルータは17,000円という格安ながらVyOSベースということもありスペック上は中々高性能です。
しかも、Webインターフェースもあるらしい。
RTX1200が定価10万越えだったりします。まぁ中古で2万切っていますけど。

このルータはNICの口がそれぞれeth0~eth2までの3つあります。
実はeth0にIPが割り当てられているのですが、説明書なんて読まずにいきなりシリアルコンソールでつなぎます(笑)
シリアルコンソールは俗に言うシスコ的なケーブルが使用でき、通信速度は115200bpsです。

起動しますと、

ubnt login:
と出ますので、デフォルトではID、PW共に「ubnt」でログインできます。


Linux ubnt 2.6.32.13-UBNT #1 SMP Tue Jun 4 14:54:28 PDT 2013 mips64
Welcome to EdgeOS
ubnt@ubnt:~$
とでたら、以下のコマンドを打って、編集モードに移行します。

ubnt@ubnt:~$ configure
[edit]
と出てきたら、編集モードになっています。

では、まず現在のNICの設定状況を確認します。
以下のコマンドを実行します。なお、コマンドはTAB補完が効きますし、途中まで打ったら候補が出てきます。このあたりVyattaの頃から大変便利です。

ubnt@ubnt# show interfaces ethernet
こんな感じで出てきます。

 ethernet eth0 {
     address 192.168.1.1/24
     duplex auto
     speed auto
 }
 ethernet eth1 {
     duplex auto
     speed auto
 }
 ethernet eth2 {
     duplex auto
     speed auto
 }
現在はeth0に192.168.1.1が割り当てられているようですね。
では、eth2に192.168.0.1/24を割り当ててみます。
ubnt@ubnt# set interfaces ethernet eth2 address 192.168.0.1/24
何となく、eth2のところをeth1とかにしたら変わりそうですし、
addressの後はdhcpにしたらDHCPになりそうですね。
このように、コマンドも分かりやすいです。
VyOSもといEdgeOS(このルータのOS)は、普通のルータと違い、設定しただけでは反映されません。
では、設定を確認します。

ubnt@ubnt# show interfaces ethernet
今度は変更点が+で出ています。

 ethernet eth0 {
     address 192.168.1.1/24
     duplex auto
     speed auto
 }
 ethernet eth1 {
     duplex auto
     speed auto
 }
 ethernet eth2 {
+    address 192.168.0.1/24
     duplex auto
     speed auto
 }
では、変更を確定させます。

ubnt@ubnt# commit
これで、eth2にIPが割り当てられました。
再度設定を確認すると、+がなくなっています。

この状態では、設定は有効ですが、ファイルに保存されていません。
つまり、電源を切ると元に戻ります。

変更内容をファイルに保存するために以下のコマンドを実行します。

ubnt@ubnt# save
これで、電源を切っても内容が保存され、次回以降も設定が有効になります。
電源を切って、再ログインし、設定が保存されているか確認してみましょう。

実際の設定はVyattaのコマンドが参考になると思います。













2015年12月27日日曜日

EdgeRouterLiteがきた!

年末の押し迫った中、来年来るかなーと思っていたEdgeRouterLiteが来ました!
注文してから2日ほどで到着。早っ!

というわけで、通電前に早速バラしてみました(笑)
なお、6ヶ月ほど保障があるようです。分解すると多分保証はなくなると思います。

箱がでかくてビビリましたが、単に2重底になっていて、下にACアダプタが入っていました。

大きさ的には普通のルータより一回り小さいくらいですね。

左が付属のもの。右が代理店が付属しているものになります。
付属のものはPSEマークが無いので、国内使用が出来ないようです。
随分大きさが違いますが、表記上は両方とも12V1Aらしいです。


構造的には以外にシンプル。業務用ルータというより市販の俗に言うブロードバンドルーターぽい感じですね。

 特筆すべきは、流石寿命を決定付ける電解コンデンサが電源部にも一切使用されていません。
ただ、逆刺し保護はダイオードのみで、ヒューズがあるわけでもないので、規格外のACアダプタつなげるとDCDCが死にそうです。


各NICのチップは蟹なんて使っていませんが、Atherosのチップが使用されています。
Atherosは無線LANで有名ですが、有線LANのチップも作っているんですね。

OSが入っていると思われるUSBメモリです。
4GBっぽいです。(一説によると2GBらしい)
CPUアーキテクチャが違うので、OS書き換えの際は注意が必要です。
なお、アクセスランプはついていないので、起動中に光ったりはしません。

こんな感じで普通にUSBが出ています。
が、どうもちゃんとしたUSB規格ではないようで、何でも刺さるわけではなさそうです。
サンディスクの奴はいけるらしい??
なお、通信は俗に言うシスコ的なケーブルでつなげばいけます。
通信速度は115200bpsでした。


AWS-SDK For Ruby V2に対応してみた。

AWS SDK For Rubyのバージョンが2にあがってはや一年がたとうとしています。
AWSなどのクラウドサービスはAPIを叩いて自動化が出来るのがメリットのひとつでして、
自分も簡単なスクリプトを作成して自動化、省力化をしています。

そんな中、AWS SDK For Rubyのバージョンが2に上がり、これまでのバージョン1とは互換性がない為、絶賛稼働中のものや、作りこんだChefのレシピなどは簡単に移行できませんし、
テストも容易ではなかったりします。

しかし、いつまでもバージョン1を使い続けると、いつかは切られてしまうので、練習がてらGitHubにあげているものをバージョン2に対応させてみました。

一応バージョン1とのDIFFはこの辺りにあります。
バージョン2でcoreとリソースに分離したのですが、いまいちリソースの使い方というか使い勝手が分からなかったので、coreのみで作成しています。

バージョン1と2での大きな違いは、バージョン1では大抵戻り値としてインスタンスのオブジェクトが返っていたのですが、バージョン2では単なる構造体が返って来ます。
あと、バージョン1ではステータスの変化を検知するためにウエイトをかけたりループをまわしたりしていましたが、バージョン2ではwait_untilという専用メソッドが追加されています。

今まではいろんなリソースタイプやコレクションをそれぞれ組み合わせて叩いていたので結構大変でしたが、バージョン2では引数として文字列か数値がとシンプルになっていますし、Filterオプションが強力になっているので、全体的に短い行数で書けるようです。
ただ、今まで戻り値がオブジェクトだったので、チェーンメソッドが書けたのですが、そういうわけには行かなくなりました。

ただ、バージョン1と2でのメソッドの対比表みたいなものは無いので、バージョン1でのこのメソッドに該当するメソッドはどれか探すのが地味に大変です。
同じメソッド名のものもあれば、ec2.instance.create->ec2.client.run_instancesのようにまったく違うものもあります。

単純に置き換えは難しそうですが、この記事が少しでも役に立てればと思います。


2015年12月26日土曜日

RubyのOptionParserで地味にはまった

今まで動いていたのに、オプションを増やしたら謎の挙動をして、数時間を無駄にしたのでメモ。

Rubyでコマンドライン引数処理をするのに、optparseを使う人が多いと思います。

こんな感じで使います。

require "optparse"
opts = OptionParser.new
# 引数
opts = OptionParser.new
instance_type = nil
opts.on("-t","--instance_type INSTANCE_TYPE") do |type|
  pp type
  instance_type = type
end
# よく忘れるパーズ実行
opts.parse!(ARGV)
これで、たとえば
ruby hoge.rb -t t2.small
見たいにすると、instance_type変数にt2.smallという値が入ります。
opts.onの第一引数にはショートオプションを、第二引数にはロングオプションとオプションの説明を入れます。
--からはじめるとロングオプションとして認識します。
ロングオプションはどのオプションか一意に決まる長さまで指定すれば良いです。

で、ここでオプションを増やします。
private_ip = nil
opts.on("-ip","--private_ip PRIVATE_IP_ADDRESS") do |ip|
  pp ip
  private_ip = ip
end
さて、これは正しく動作しません(笑)
ruby hoge.rb -ip 192.168.0.1
としても、private_ipには何故か"p"という文字が入ります。
ruby hoge.rb --private_ip 192.168.0.1
だと正しく動き、private_ipには"192.168.0.1"という文字が入ります。
大抵デバック時には引数を埋め込むため気づきませんでしたが、
ショートオプションはアルファベット1文字しか有効ではなく、それ以降の文字列は引数と認識されます。

なので、
private_ip = nil
opts.on("-i","--private_ip PRIVATE_IP_ADDRESS") do |ip|
  pp ip
  private_ip = ip
end
と同じ挙動になり、-ipというオプションは-iオプションに引数pを渡していることになります。

え?常識(汗

よく見たらマニュアルにちゃんと書いてありましたね(汗

ショートオプションの引数指定は使いにくいので、このような場合はロング オプションの方が使う方もわかりやすいです。例えば、上記の場合、-ab を 指定すると -a b と解釈されます。-a が引数を持たない最初の例なら -a -b と 解釈されます。






2015年12月20日日曜日

AnsibleでPostgreSQLのユーザを作成するときに気をつけること。

このところ、暇があればAnsibleを触っています。

前回まではLAMP構成を作ってみましたが、今回はPostgreSQL環境を構築しようとして、
ユーザ作成で地味にはまったのでメモ。

AnsibleでPostgreSQLのユーザを作成するとき、以下のようにします。
*AnsibleのDocumentより抜粋
# Create rails user, grant privilege to create other databases and demote rails from super user status- postgresql_user: name=rails password=secret role_attr_flags=CREATEDB,NOSUPERUSER
なるほど、role_attr_flagsに割り当てる権限を指定するのだな。
というわけで、次のようにしてみました。

 - name: ユーザ作成
   postgresql_user:
     db: "{{ pgsql_dbname }}"
     name: "{{ pgsql_dbuser }}"
     password: "{{ pgsql_dbpass }}"
     priv: ALL
     encrypted: yes
     state: present
     login_user: postgres
     role_attr_flags: "NOSUPERUSER,NOCREATEDB,NOCREATEUSER,NOCREATEROLE"
   sudo_user: postgres
   sudo: yes
 しかし、これはエラーになります。
何故か?と小一時間悩んだのですが、どうやら、NO_SUPERUSER権限は既にNOCREATEDBなどの権限を有しているため、重複するロールを指定するとエラーになるようです。参考

なので、通常はNO_SUPERUSERだけで事が足りそうです。
自分は明示的に指定したかったので、以下のようにNOSUPERUSERを外しました。

 - name: ユーザ作成
   postgresql_user:
     db: "{{ pgsql_dbname }}"
     name: "{{ pgsql_dbuser }}"
     password: "{{ pgsql_dbpass }}"
     priv: ALL
     encrypted: yes
     state: present
     login_user: postgres
     role_attr_flags: "NOCREATEDB,NOCREATEUSER,NOCREATEROLE"
   sudo_user: postgres
   sudo: yes


2015年12月16日水曜日

CentOS6+PHP5.6+MySQL5.6でハマった

久々にかなりはまったのでメモ。

CentOS6に最新のPHP5.6をremiで入れて、MySQL5.6をcommunityリポジトリから入れると、
php-mysql-5.4.45-2.el6.remi.x86_64が依存関係でインストールできません。
lib-mysqlがらみですと、MySQLの公式サイトが配布しているMySQL-shared-compatをインストールすればいいのですが、これはあくまでRedHatのリポジトリにあるlib-mysqlの依存性が解消されるだけで、remiで入れたphp-mysqlが依存している mysql-libs-5.5.47-1.el6.remi.x86_64には無力のようです。

ググってみた感じ、結構詰まっている人が多いようですが、いろいろやった結果、解決法としては

php-mysqlではなく、php-mysqlndをつかう。

というものでした。
php-mysqlndはMySQLのネイティブドライバらしく、MySQLのクライアントが不要らしいです。
(つまり、lib-mysqlにも依存しない)
PHP5.3以降にふくまれており、mysqlndドライバを使用することを強くお勧めするらしいです。



2015年12月11日金曜日

AWSのMicrosoft-ADを試してみた。



2015/12/3に発表されたAWSのクラウド上のマネージド型MicrosoftActiveDirectoryを触ってみました。
といっても、触った感じSimple-ADとの違いが分からない(汗


例によってWiKiにまとめています。

ChefのLWRPについて

いい加減まとめないとなぁと思いつつはや幾年・・・
ChefのLWRPについてのメモ

ここより詳しい解説がこの辺りにありますけど・・


LWRPとは、簡単に言うとレシピ内で使用するリソースを自分で定義したものです。
これの何がうれしいかというと、レシピの中でゴリゴリ書いているとどうしても可読性が落ちたり、
汎用性に乏しかったりするのですが、それを隠蔽し、共通処理をくくりだすことにより再利用しやすくなります。
たとえば、ApacheのインストールはApacheのクックブックで出来ますが、その後ほぼ必ずConfの設定が必要だったり、証明書の設置などが必要になります。
それらはほぼ同じ処理なのにドメイン名が違うなど微妙に異なります。
また、DBをインストールするときも同様にConfの設定やユーザの作成、DBの作成やバックアップなどのレシピが必要になります。

それらを隠蔽し、リソースのように定義できれば可読性も上がり、コピペミスによる動作不良などを防ぐことが出来ます。


LWRP自体はエディタでゴリゴリ書いてもいいのですが、ここではChefdkをインストールし、スケルトンを作成します。

まずは以下のコマンドを実行し、クックブックとLWRPのスケルトン(雛形)を作成します。
chef generate cookbook test
cd test
chef generate lwrp testlwrp

このようなディレクトリ、ファイルが作成されます。

C:.
└─test
    ├─providers
    ├─recipes
    ├─resources
    ├─spec
    │  └─unit
    │      └─recipes
    └─test
        └─integration
            ├─default
            │  └─serverspec
            └─helpers
                └─serverspec
LWRPで使用するのは、このうちprovidersとresourcesです。
この2つのディレクトリには同じファイル名「testlwrp.rb」が生成されています。
この2つのファイルはペアで使用するため、必ず同じファイル名にする必要がありかつ、
LWRPで作成するリソース名にする必要があります。

ここでは、簡単な例として、/tmp/hogehogeというファイルに指定した内容を書き込むものを作成します。

まず、resourceディレクトリ内にあるtestlwrp.rbに以下の内容を記載してください。

# デフォルトのアクションを指定
default_action :install
#このLWRPで定義するアクション
actions :install, :uninstall
#アトリビュートを定義する。
attribute :input_data, :kind_of => String, :required => true

次に、providersディレクトリ内にあるtestlwrp.rbに以下の内容を記載してください。

def whyrun_supported?
  true
end
action :install do
  converge_by("install test #{new_resource.input_data}") do
    file "/tmp/hogehoge" do
      mode "0644"
      content "install test #{new_resource.input_data}"
      action :create
    end
  end
end
action :uninstall do
  converge_by("uninstall test #{new_resource.input_data}") do
    file "/tmp/hogehoge" do
      mode "0644"
      content "uninstall test #{new_resource.input_data}"
      action :create
    end
  end
end


では順に説明していきます。
resourceでは以下の内容を記述しました。
# デフォルトのアクションを指定
default_action :install
chefのリソースを使用する際、アクションと呼ぶ処理の塊を呼び出します。
無指定の場合呼び出すアクションを規定します。
#このLWRPで定義するアクション
actions :install, :uninstall
コメントのままなんですが、このLWRPに定義されているアクションを列挙します。
列挙されているものが外部のレシピから使用することが出来ます。

#アトリビュートを定義する。
attribute :input_data, :kind_of => String, :required => true
このLWRPのに渡す引数です。
input_dataが引数を格納する変数名、kind_ofで引数の型を、requiredで必須入力がそうでないかの指定をします。

次に、実際の処理が記述されているproviderを見ていきます。

頭に以下のような記述があります

def whyrun_supported?
  true
end

これはwhy-runをサポートしているよ。という宣言になります。
why-runって何?なのですが、実際には実行しないテストモードになります。

次にinstallアクションを見ていきます。

action :install do
  converge_by("install test #{new_resource.input_data}") do
    file "/tmp/hogehoge" do
      mode "0644"
      content "install test #{new_resource.input_data}"
      action :create
    end
  end
end
action :install ブロックでinstallアクションを定義しています。
converge_byブロックで囲まれた中身が実際の処理になります。
fileリソースを使用して、/tmp/hogehogeファイルを作成しています。
このように、レシピを書く感じでほかのリソースを呼び出したりして作成することが出来ます。

ここで、new_resource.input_dataという変数を参照しています。
前述のアトリビュートで宣言した変数名の前に、new_resourceをつけることで、その中身を参照することが出来ます。

同様にuninstallアクションも定義してあります。

では、作成したLWRPを動かしてみます。
今回は作成した一式をVagrant上のCentOSで動作させます。
Chefサーバを用意してとかは大変なので、chef-soloでお手軽に実行したいと思います。
まずは、vagrantのディレクトリに作成したディレクトリを一式置きますと、Vagrantないでは/vagrant配下で参照できます。
recipeディレクトリのdefault.rbを以下のように記述します。

test_testlwrp "lwrp_test" do
  input_data  "test"
end
LWRPで作成したリソースを呼び出すには、<クックブック名>_<LWRP名>で呼び出すというルールがあります。
今回作成したのはtestクックブックのtestlwrpという名前なので、test_testlwrpという名前で呼び出します。
このブロックに囲まれたinput_dataというのがアトリビュートですね。
では、chef-soloを動かす準備をします。
/vagrant/testという感じで作成したクックブック一式が見えている前提です。

/vagrant/solo.rbというファイルを作成し、中身に以下の記述をします。

cookbook_path [/vagrant]
では、chef-soloを実行してみましょう。まずはwhy-runモードで変更を加えずに実行してみます。
 chef-solo -c ./solo.rb -o test -w
こんな感じに出ればOKです。

Starting Chef Client, version 11.8.0
[2015-12-11T13:32:13+00:00] WARN: Run List override has been provided.
[2015-12-11T13:32:13+00:00] WARN: Original Run List: []
[2015-12-11T13:32:13+00:00] WARN: Overridden Run List: [recipe[test]]
Compiling Cookbooks...
Converging 1 resources
Recipe: test::default
  * test_testlwrp[lwrp_test] action install
    - Would install test test
Chef Client finished, 1 resources would have been updated
作成したテスト用のレシピ(default.rb)にはアクションを明示的に指定していませんでしたが、デフォルトのアクションであるinstallが呼ばれています。
また、ファイルの中身として、install test testになることが示されています。
また、実際に/tmp/hogehogeファイルは作成されていません。シミュレーションしただけですね。

では、アクションを変えてみます。default.rbを次のように変更して再度chef-soloを実行してみます。

test_testlwrp "lwrp_test" do
  input_data  "test"
  action :uninstall
end
Starting Chef Client, version 11.8.0
[2015-12-11T13:37:11+00:00] WARN: Run List override has been provided.
[2015-12-11T13:37:11+00:00] WARN: Original Run List: []
[2015-12-11T13:37:11+00:00] WARN: Overridden Run List: [recipe[test]]
Compiling Cookbooks...
Converging 1 resources
Recipe: test::default
  * test_testlwrp[lwrp_test] action uninstall
    - Would uninstall test test
Chef Client finished, 1 resources would have been updated

installの箇所がuninstallに変わりましたね。
では、実際に適用してみましょう。

chef-solo -c ./solo.rb -o test
Starting Chef Client, version 11.8.0
[2015-12-11T13:45:18+00:00] WARN: Run List override has been provided.
[2015-12-11T13:45:18+00:00] WARN: Original Run List: []
[2015-12-11T13:45:18+00:00] WARN: Overridden Run List: [recipe[test]]
Compiling Cookbooks...
Converging 1 resources
Recipe: test::default
  * test_testlwrp[lwrp_test] action uninstall
    - uninstall test test
Recipe: <Dynamically Defined Resource>
  * file[/tmp/hogehoge] action create
    - create new file /tmp/hogehoge
    - update content in file /tmp/hogehoge from none to 3c37bb
        --- /tmp/hogehoge       2015-12-11 13:45:18.458044278 +0000
        +++ /tmp/.hogehoge20151211-27701-vdbtpv 2015-12-11 13:45:18.460044278 +0000
        @@ -1 +1,2 @@
        +uninstall test test
    - change mode from '' to '0644'
Chef Client finished, 2 resources updated
uninstallアクションが実行され、/tmp/hogehogeファイルが作成、パーミッションが0644、中身がuninstall test testなファイルが作成されました。
一応中身を確認してみましょう。

[root@localhost vagrant]# more /tmp/hogehoge
uninstall test test
[root@localhost vagrant]# ls -lah /tmp/hogehoge
-rw-r--r-- 1 root root 19 Dec 11 13:45 /tmp/hogehoge
意図したとおりになっていますね。

以上簡単ですけれど、基本的な動作は抑えていると思いますので、これを応用すればオレオレリソースを作成するのも可能だと思います。
さらに複雑、高度なリソースを定義しようとすると、Rubyのモジュールやクラスを作成して呼び出す・・・なんてことも出来ます。
ただ、あまりRubyをゴリゴリ書くと、作った人しか分からない負の遺産が出来るので(経験談)ほどほどが良いです。


Ansibleのグループ変数(?)について調べてみた

AnsibleはInventoryファイルやgroup_vars、プレイブックなどに変数を定義することが出来ます。

しかし、デフォルトでは同名の変数は上書きされてしまいます。
これは、たとえばdbというグループとwebというグループを作り、group_varsでwebとdbそれぞれに変数を定義した場合、それぞれのグループで有効。ではなく、すべてはマージされるということです。

では、どういう優先度でマージされるのでしょう?
っと調べてみたのですが、ハッキリした記述は見つけられませんでした。
また、Ansibleではグループを階層構造にすることが出来ます。
階層化したグループ名に対応するgroup_versもまた有効のようですが、同様に同名の変数が有った場合の優先度が不明です。

というわけで、このようなプレイブックを作成し、実際に動かしてみました。


$ ansible-playbook -i hosts.ini site.yml -c paramiko
PLAY [staging2] ***************************************************************
GATHERING FACTS ***************************************************************
ok: [192.168.0.130]
ok: [127.0.0.1]
TASK: [debug var=hoge] ********************************************************
ok: [127.0.0.1] => {
    "var": {
        "hoge": "web"
    }
}
ok: [192.168.0.130] => {
    "var": {
        "hoge": "db"
    }
}
TASK: [debug var=huga] ********************************************************
ok: [127.0.0.1] => {
    "var": {
        "huga": "www"
    }
}
ok: [192.168.0.130] => {
    "var": {
        "huga": "dbdb"
    }
}
PLAY [staging] ****************************************************************
GATHERING FACTS ***************************************************************
ok: [192.168.0.130]
ok: [127.0.0.1]
TASK: [debug var=hoge] ********************************************************
ok: [127.0.0.1] => {
    "var": {
        "hoge": "vars_hoge"
    }
}
ok: [192.168.0.130] => {
    "var": {
        "hoge": "vars_hoge"
    }
}
TASK: [debug var=huga] ********************************************************
ok: [127.0.0.1] => {
    "var": {
        "huga": "www"
    }
}
ok: [192.168.0.130] => {
    "var": {
        "huga": "dbdb"
    }
}
PLAY [web] ********************************************************************
GATHERING FACTS ***************************************************************
ok: [127.0.0.1]
TASK: [debug var=hoge] ********************************************************
ok: [127.0.0.1] => {
    "var": {
        "hoge": "web"
    }
}
TASK: [debug var=huga] ********************************************************
ok: [127.0.0.1] => {
    "var": {
        "huga": "www"
    }
}
PLAY [db] *********************************************************************
GATHERING FACTS ***************************************************************
ok: [192.168.0.130]
TASK: [debug var=hoge] ********************************************************
ok: [192.168.0.130] => {
    "var": {
        "hoge": "db"
    }
}
TASK: [debug var=huga] ********************************************************
ok: [192.168.0.130] => {
    "var": {
        "huga": "dbdb"
    }
}
PLAY [zaiko] ******************************************************************
GATHERING FACTS ***************************************************************
ok: [192.168.0.130]
ok: [127.0.0.1]
TASK: [debug var=hoge] ********************************************************
ok: [127.0.0.1] => {
    "var": {
        "hoge": "web"
    }
}
ok: [192.168.0.130] => {
    "var": {
        "hoge": "db"
    }
}
TASK: [debug var=huga] ********************************************************
ok: [127.0.0.1] => {
    "var": {
        "huga": "www"
    }
}
ok: [192.168.0.130] => {
    "var": {
        "huga": "dbdb"
    }
}
PLAY RECAP ********************************************************************
127.0.0.1                  : ok=12   changed=0    unreachable=0    failed=0
192.168.0.130              : ok=12   changed=0    unreachable=0    failed=0
グループ名のアルファベット順で上書きされるのかなと思ったのですが、
どうやらそのホストが所属している一番末端のグループが優先ですが、プレイブック内のvarsセクションでの宣言が一番最優先のようです。


2015年12月6日日曜日

LT駆動開発 21に参加してきました。

特にスライドも何も用意していなかったのですが、案の定召集が(ぉ

LT枠が例によって余っていたので現地で急遽こしらえました。
といっても例によってポカーン枠なんですがね(笑)



いやぁ、みんな毎週ネタがあってすごいわ。

2015年11月29日日曜日

Ansibleお為し中・・・

気がついたら今年も残すところあと1ヶ月ですね。

職場でたった一人のインフラ担当者だったりすると、サーバ構築ラッシュが発生すると土日連休ボランティア活動する羽目になるのですが(ぉぉぉ
どうにも手が回りそうにないので、Chefに続いてAnsibleに手を出してみました。

といってもPython書いたことないんですが(笑)

AnsibleはChefと違い、
  • サーバに特別なエージェントが不要。サーバ側にはSSHとPythonがインストールされていればいい。
  • 基本はプレイブックと呼ばれるYAMLファイルにやりたいことを記述するので、習得が容易。
  • Ansible Galaxyとよばれるサービスがあり、大抵のやりたい事はここにあったりする。
  • 動かすのにサーバなどが不要。
  • Chefほど多くのサーバを管理するのには不向き。(管理サーバがいないので)数台程度

という特徴があります。
特にエージェントレスというのは、Chefと違い、サーバに特別何か仕込まなくて良いので、お客さんの環境にセットアップするとか、不要なものを極力入れたくない場合に便利そうです。
反面エージェントがないということは、サーバの現状を取得するとかが難しい。という面もありますが、Chefと違い繰り返し実行して冪等性を確保。というより、おかしくなったらサーバごと作り変える。という用途に向いています。

Ansibleは習得が容易、というよりChefの登場人物や構成要素が多すぎるという気がしますが(笑)
いくつか用語を知っておく必要が有ります。
  • Inventoryファイル
    • Ansible実行対象サーバを記したINIファイル(のようなもの)。特徴として複数のサーバをグループとして設定することが出来、複数のサーバに設定を行うことが出来る。
  • モジュール
    • ファイルをコピーとか、DBを作成とか実際にサーバを操作する機能をもったもの。自作も勿論可能。
  • プレイブック
    • Chefでいうレシピに相当するもの。複数のモジュールを組み合わせて一連の操作を記述したYAMLファイル。複数に分割してInclude出来たりする。
    • 感じ的にはシェルのDSLっぽい感じ。
  • ロール
    • 権限。という訳ではなく、Chefでいうクックブックに相当するもの。複数のプレイブックをまとめたもの。

まずはこれくらいを押さえておけば良いと思います。
自分もAnsible勉強し始めて1週間程度ですが・・・

ではまずは環境構築です。
自分はCygwin上に構築しました。

インストールにはapt-cygコマンドを使用しますので、もし古いapt-cygをつかわれている場合は以下の要領で最新にしておきます。

wget https://raw.githubusercontent.com/transcode-open/apt-cyg/master/apt-cyg
chmod 755 apt-cyg
mv apt-cyg /usr/bin/

まずはPythonをインストールします。
apt-cyg install python
python -V (Vは大文字)

python 2.7.10

とかと出ればOKです。
次に、easy_installやpipを使うのに必要なビルドツール一式をまとめて入れます。
apt-cyg install patch gcc4-core gcc4-g++ make autoconf automake m4 bison readline openssl-devel libsqlite3-devel libxml2-devel libxslt-devel zlib-devel libncurses-devel libtool ca-certificates

次にansibleをインストールするのに必要なpipというコマンドをインストールする為のeasy_installをインストールして、pipをインストールします。(な、長い・・・)
apt-cyg install python-setuptools
easy_install-2.7 pip
やっと準備が出来たので、ansibleをインストールします。
pip install ansible
練習がてら、Vagrant上にJenkinsサーバを構築するAnsibleを作りましたので、これを例に説明します。

まずルートディレクトリにあるhostsというファイルがInventoryファイルになります。
中身はサーバのグループ名「jenkins_server」と、そのグループに所属しているサーバのIPやSSHで接続するユーザ名などが書いてあります。

次に、site.ymlですが、これはマスタープレイブックと呼ばれる、すべての起点になるプレイブックです。
ちなみに今回の例ではひとつだけですが、本番とステージング用など、複数作ることも可能です。その場合それぞれを指定して実行します。

これの中身ですが、hosts:の箇所が実行させるサーバグループ名になります。これはInventoryファイルのグループ名になります。Allとすると、Inventoryファイル全部が対象になります。

rols:の箇所は該当hostsのサーバに対し実行するロールになります。
(とりあえず、Zabbix-agentの箇所は置いておきます)

rollsディレクトリの配下にはそれぞれロールが配置されています。
全部解説は大変なので、まずはcommonロールを見ていきます。
このロールにはhaldlersとtasksというディレクトリがあります。
tasksディレクトリ内には複数のプレイブックがありますが、その中のmain.ymlというプレイブックがこのロールのマスタープレイブックになり、基点となります。
この中では、installとcreate_userとsshの3つプレイブックをインクルードしています。

install.ymlを見ていきましょう。
この中にあるyum:とかservice:とかがモジュールになり、yumとかserviceコマンドに相当する機能を持っています。
モジュールは複数の引数をもつことがあり、key=varという形で渡したり、YAML形式で渡したりします。

handlersについては、commonロールでは使っていないのですが、jenkinsロールのhandlersには"restart apache"と"restart jenkins"という二つのハンドラが登録されています。
これは、プレイブック内でConfファイルを変更した場合などサービスを再起動したりとか、アプリをインストールしたらサービスに登録して起動させたい場合があります。そのときにnotifyとしてハンドラ名を渡すと、そのハンドラに規定されたモジュールが動作します。(Jenkinsロールのmain.yml22~37行目参照)

あと、プレイブックはYAMLなのでChefと違いプログラムが書けません。しかし、with_itemsという構文を使うことにより、変数itemに配列の値を入れることが出来ます。{{ item }}のように使います。なお、変数名はitem固定のようです。

後最後においておいたzabbix_agentですが、ここにロールはありません。
では何処にあるかというと、Ansible Galaxyのサービスからロールをインポートして利用しています。
Ansible Galaxyのインポート方法は以下のとおりです。
ansible-galaxy install dj-wasabi.zabbix-agent
role:以下の記述は、zabbix-agentロールが要求する引数たちです。
Apacheのロールで使用しているテンプレートですが、Ansibleではjinja2(そう。神社です)というテンプレートエンジンを使用しています。
色々出来るようですが、拡張子はj2にする。{{ value }}で変数を埋め込める。てのを知っていれば設定ファイルを丸まる置換とか出来るのでとりあえずは使えると思います。

最後に、Apacheのプレイブックでcopyモジュールを使ってSSL証明書をコピーしているのですが、コミットするとき、うっかりダミーファイルを置くのを忘れてしまったので、GitHubにあがっていませんが、templateディレクトリではなく、filesというディレクトリを作成し、そこからのパスを指定します。

以上ざっくりですが、自分が一週間合間見てお試しした感じです。
ついでにAWS上にちょっと本格的なLAMP環境を構築するものや、Python書いたことないのに無謀にもAnsibleモジュールを2時間で作成したものとかを置いておきます。



2015年11月23日月曜日

Cygwinでsudoを使う

地味にハマったのでメモ。

AnsibleをCygWinで使っていた特に、何故かsudoが無いぞ。と怒られました。

そんな馬鹿なとリモートサーバを覗いてみるも、そもそもVagrant使っている段階でsudoないと使えないし。

っと小一時間プレイブックをこねくり回していたのですが、結果から言うとCygWinにsudoがないのが原因でした。
そもそもCygWinにパーミッションの概念がどこまであるのか疑問ですが、ググるとみんな苦労しているようで、解決法も様々あるようです。

自分が試したのは以下のサイトにあるやり方です。

Cygwin で sudo 的コマンドを使うための設定

/bin/sudoというファイルを作成し、以下の内容を張り付け、実行権限を付与します。


#!/bin/sh

function usage_exit() {
    cat << EOF >&2
Usage: $(basename $0) command
       $(basename $0) -e file
       $(basename $0) -v
EOF
    exit 1
}

edit_flg=0
while getopts :veh opt
do
    case $opt in
        v)
            exit 0
            ;;
        e)
            edit_flg=1
            ;;
        h)
            usage_exit
            ;;
        \?)
            usage_exit
            ;;
    esac
done

shift $(($OPTIND - 1))

if [ $edit_flg -eq 1 ]; then
    if [ $# -ne 1 ]; then
        usage_exit
    fi

    sudoedit "$1"
else
    if [ $# -eq 0 ]; then
        usage_exit
    fi

    quote_args=''

    for arg in "$@"
    do
        arg=$(printf '%q' "$arg")
        quote_args="$quote_args $arg"
    done
    quote_args=$(echo "$quote_args" | sed -e "s/\\\\'/'\"&\"'/g" -e 's/\\\\/&&/g')

    quote_pwd=$(printf '%q' "$PWD" | sed "s/\\\\'/'\"&\"'/g")

    cygstart --hide -w -a runas sh -l -c "'exec < /proc/$$/fd/0 > /proc/$$/fd/1 2> /proc/$$/fd/2; cd $quote_pwd; $quote_args'" &

    trap 'trap "" 1 2 3 15; sudo c:/Windows/system32/taskkill /pid $(ps -p $! | awk "NR==2 {print \$4}") /t > /dev/null 2>&1' 1 2 3 15
    wait $!
fi

2015年10月26日月曜日

Dockerで複数のコマンドを引数で渡す

Dockerで複数のコマンドを引数で渡そうとして、たとえば、
docker run -it centos:6 ls -lah;pwd
としても、lsしか実行されません。pwdはDockerサーバ側で実行されます。&&にしても同じです。
まぁよく見ればわかるのですが、これは"docker run -it centos:6 ls -lah"と"pwd"を続けて実行しているだけですね(汗

かといって、
docker run -it centos:6 "/bin/ls -lah"
としてみても、exec: "/bin/ls -lah": stat /bin/ls -lah: no such file or directoryとなぞのエラーを返します。
これ、方法が分からなくて地味に悩んだのですが、さすがTwitter。即回答が帰ってきましたw
というわけで、
docker run -it centos:6 sh -c "cd ~/;ls -lah;cd /tmp;pwd;ls -lah"
のように、sh -c で渡すと実行できます。

gitbucketにPushするときにreturn code 22と出る

GitHubからクローンしたプロジェクトを自宅gitbucketに移したときにはまったのでメモ

まず、githubからクローンしてきます

git clone https://github.com/aipocom/aipo.git

自宅gitbucketに変更します

git rm origin
git remote add origin http://git.localdomain:8080/gitbucket/git/akira/aipo.git
としてpushすると、
error: Cannot access URL http://git.localdomain:8080/gitbucket/git/akira/aipo.git/, return code 22
fatal: git-http-push failed

と蹴られます。
このエラーはリモートオリジンの指定がおかしいときに出るようです。
git remote rm origin
で先ほど設定したリモートオリジンを削除し

git remote add origin http://akira@git.localdomain:8080/gitbucket/git/akira/aipo.git

とホスト名の前にユーザ名@を追加するとうまく動きます。

2015年10月18日日曜日

100均に売られている自称5V1Aなアダプタをバラしてみた。

100均に売られている、自称5V1Aなアダプタをばらしてみました。

お約束ですが、例によって分解などは自己責任でお願いします。書き起こした回路図ですが、合っている保証はありませんし、一部定数は記載していません。参考程度に留めてください。


以前某社製にそっくりなアダプタをバラしたのですが、最近は少し大きくなった新型が出たそうなので、入手してバラしてみました。


嘘か本当か、240V対応らしいです。


最初で最後の動作チェック(笑)
 
一応700mA程度は出るようです。

では早速分解します。

裏側。
今回は片面基板のようです。
前回はトランジスタ式でしたが、今回はIC化されています。しかし、2次側のフィードバックはなし。

では、回路をトレースしていきます。
2次側は単に半端整流しているだけなので省略。


ICの型番はググって見たもののヒットせず不明。


2015年10月17日土曜日

CorageのギガビットルータCG-BARGXを直してみる

PHPカンファレンス2015に行って来たついでに、秋葉のジャンク屋さんで購入したルータ、CG-BARGX、980円もしたのですが、実は有線ルータだったり地雷ルーターだったりで色々残念だったのですが、 なんとファームウエア不良っぽく、PCからは認識されないわ工場出荷時にリセットできないわで早速楽しめそうです(笑)

あ、毎度のお約束ですが、今回は無線LANじゃないので電波法云々はなさそうですが、分解修理は自己責任になります。内容の正確性も含め一切の保障はありません。


まずは分解。後ろにあるゴム足の中にネジ(T8かな?)があるので、それを外すと、特に爪もなくカパッと外れます。
このあたり親切。
カパッと外すとこんな感じ。




シリアルが出せそうな4ピンがあるので、そこにヘッダピンを着けます。
VCCは必要ないので、TX、RX、GND だけ着けました。


ここまで出来れば、あとは適当なRS232C-TTL変換(3V系対応のやつ)でつなぎ、57600bpsで接続して電源を入れると、UBootの画面が出てきます。
どうやら、ブートローダは生きているようです。

では、ファームを流していきます。
必要なものはTFTPサーバと、純正ファームウエアです。TFTPサーバはググれば色々出てきますので、適当なのをインストールしてください。ファームは解凍し、中のbargx_130.fimをTFTPサーバの転送用ディレクトリに配置します。
ルータのLANポートとPCをLANケーブルでつなぎ、PC側のIPを192.168.1.100にします。
また、PCに無線LANやBlueToohなどが有る場合は無効化し、Windowsファイヤーウォールやアンチウイルス系のファイヤーウォールは無効化します。
無効化しないと、TFTPでの転送が出来なかったり、コケたりします。また、Bluetoothや無線LANが生きているとうまく転送されなかったりしますので、ルータとPCを直結させることが重要です。
シリアルコンソールはつないだままです。こちらでモニターしつつ、LAN経由でファームを流していきます。
では、ファームを流していきます。TFTPサーバを起動し、LANケーブルの接続など準備できたら、
いったんルータの電源を切り、電源を入れたら、シリアルコンソール上ですばやく「2」を押します。
こんな画面になればOKです。

2: System Load Linux Kernel then write to Flash via TFTP.
 Warning!! Erase Linux in Flash then burn new one. Are you sure?(Y/N)
と聞かれるので、Yキーを押します。

 Please Input new ones /or Ctrl-C to discard
        Input device IP (192.168.1.1) ==:
ときかれるので、そのままEnterをおします。

        Input server IP (192.168.1.5) ==:
ここで、192.168.1.100と入力します。

        Input Linux Kernel filename (firmware.bin)==:

では、ファームウエアのファイル名bargx_130.fimを入力します。

ファームの転送が開始されます。


 ETH_STATE_ACTIVE!!
Start httpd!!!
In GemtekHttpdStart...
HTTPD from server 192.168.1.100; our IP address is 192.168.1.1

 HTTPD_TIMEOUT_COUNT=10,Load address: 0x80100000
Waiting: T T T T T

とでたら、ブラウザを開き、192.168.1.1にアクセスしますと、ファームをアップロードする画面が出ますので、再度ファームをアップロードします。

再度ファームが書き込まれます。

シリアルコンソール上に

 Copy 2871296 byte from 80100289 to Flash... bf060000 => OK!!!
done

At fw success!!!

とでたら、一旦ルータの電源を入り切りし、再起動させると、通常起動します。
ブラウザで192.168.1.1にアクセスすると、管理ページが開けます。

以上で修理完了です。

なお、この要領でDD-WRTなど純正以外のファームに書き換えることも技術的には可能です。
UBootさえ生きていれば、文鎮化しても純正ファームに戻すことが出来ます。

余談ですが、このルータ、シリアルコンソールで特にPWなしでいきなり中のLinuxにアクセスできます。
FWの構成自体はIPTablesのようですね。
FWのVer1.0のころはTopコマンド使えたのですが、最新の1.3 では削除されたようです。容量の問題かな?
/proc/status_led_ctrlにあるファイルをcatで開くと、Lチカしたりできます。









2015年10月14日水曜日

Jenkins+DockerでPHPUnitを動かすCIサーバを作ってみた。

PHPカンファレンス2015の書籍コーナーにて、「何か買ってけ。」と言われたものの、自分プログラマじゃないしなー
というわけで、以前から気になっていたDocker本を入手。

どうせDockerやるならTDDだよね。というわけで今風なCIサーバを作ってみました。
CircleCIみたいにプッシュしたら自動でテストが走って~なやつです。

当初Jenkinsサーバ内にDockerを入れていたのですが、テスト中は当然Dockerが動くのでメモリは食うわ重くなるわでこりゃ駄目だ。というのでJenkinsスレーブサーバに手を出す羽目に。

Jenkins+DockerなCIサーバはググれば構築事例は割りと有るので構築自体はそんなに悩まなかったのですが、プログラマじゃないのでPHPUnitの動かし方が分からない。という罠があるとは・・

というわけで、自宅検証サーバにて構築した内容は例によってWiKiにまとめています。
ついでにJenkinsのスレーブサーバ構築も。
Jenkinsスレーブサーバ、今まで環境依存なジョブを動かすために苦労していたのですが、環境ごとにスレーブに切り出す、さらにDockerに押し込めてしまえば随分と楽になりそうな予感がします。


2015年9月23日水曜日

Silexについてメモ

本ブログはすごい広島#123の成果物です。

最近(?)PHPのマイクロフレームワークであるSilxeがいいらしい。ということで、ぼちぼち勉強中。

で、サンプルのHelloWorldまではサクッと行くのですが、コントローラを分離させたとき、何故か読み込まれないというか、そもそもどうやって該当ファイルをrequireしているのか?というところが良く分からず、随分ハマッたのでメモ。


composer.jsonに以下追加し、composer updateすれば、autoload.phpに追加されて読み込まれます。
どちらかというとSilexというよりcomposerの問題でした。(なのでSilexでググっても出てこなかった・・)

"autoload": {
    "psr-4": {
        "Testapp\\": "src/Testapp"
    }
}

こうすることにより、Testapp名前空間のファイルはsrc/Testapp配下を読んでくれるようになります。

作成中のテストアプリはこの辺りにあります。

2015年9月13日日曜日

LT駆動開発18で発表してきました。

例によって前日参加しないのか?とお誘いを受けたので、9/5に開催されたLT駆動開発18で発表してきました。

LT駆動は最近勉強したことを発表する場でして、前回同様、最近FPGAで遊んでいるので、それを発表しました。

まぁポカーン枠確定なんですがw

スライドはこちら。

FPGAやり始めてまだ数週間だったり、体力が尽きて十分ネタをまとめられなかったり、
当日移動中の電車内で作成してたりとオチがなかったりしましたが。

自分は昔PL/SQLプログラマーだったので、VHDLに親近感がありまして、

何となく出来そう!

これだけではじめちゃいました(笑)
実はFPGAやりたいなぁと思ったのはずいぶん前なんですが、なにせ本業でもないし、FPGAトレーニングボードは高いし、数千万ゲートなんて組めないし、どうせすぐ飽きそうなものにちょっと数万は出せないなと。
じゃぁボード作るかと部品だけは揃えたんですけどね。配線が面倒で放置してたんですが。
某所で中古のトレーニングボードが安く出てるよ。と教えてもらったので、入手したのですが、
マイコンのプログラムのようだけど全然違って面白い!
自分の作った回路がその場で書き込まれて動く。ボード手に入れれば、開発環境はフリーでカスタムLSIが作れる。ってのは凄い時代になったなと。

ただ、どうもVHDLよりVerilogHDLのほうが人気が有るようで(汗
サンプル見つけても逆にVerilogさっぱり読めない・・・


2015年8月30日日曜日

FPGAで遊んでみた。

以前から遊んでみたいなぁと思っていたFPGAですが、運よくBASYS2というボードを入手できたので、遊んで見ました。

自分はOracleのPL/SQLというバッチ処理言語(というかストアドプロシージャ)が大好きで、ガリガリバッチ処理を書いていた時代があったのですが、FPGAで使うVHDLという言語も、ご先祖様は同じAda系言語でして、文法とか記述方法が凄く親近感があります。

というわけで、ボードを入手し、4GB超あるISEをダウンロードしたのですが、使い方がさっぱり分からず、手元の本は少々古くて、最新のISEと画面が違うなど、結構試行錯誤したので、WiKiにまずは使い方をまとめておきます。

いきなりVHDLはキツいな・・・と思っていたのですが、回路図書いてそれを書き込むって出来るんですね。
以前汎用ロジックICで組んだ回路がFPGAに入るとか凄く楽しそう!


2015年8月14日金曜日

Yamahaルータ勉強中・・・

諸事情があって、YamahaRTX1200を自腹購入(涙)してルータのお勉強中・・・・

勉強したことは忘れないのと理解をまとめる為WiKiにまとめ中。

2015年8月8日土曜日

夏休みの工作??

夏休み?の工作がてら、地味に出動頻度があるので、今までのトランジスタ式からちゃんとしたIC式のものを作成。
…ってジャンク品のレベル変換ケーブルの先を付け替えただけですけど。

ついでに某所で入手したFONを修理。
こいつ、初期型はヒートシンクが斜めについていて熱暴走でチップが死ぬんだよねぇ。





DRAMリフレッシュの謎に迫る

DRAMリフレッシュ回路の謎を求めて過去にさかのぼっていくうちに、
とうとうこの時代まで来てしまったようだ・・・



2015年8月2日日曜日

LT駆動開発17で発表しました。

例によって前日夜にLTしないのか?と圧力お誘いがあったので、
数時間ばかし徹夜して、LT駆動開発17で発表してきました。

LT駆動は最近勉強したことを発表する場でして、自分がずーっと疑問だったDRAMの動きについてこのところいろいろ実験していたので、それを発表しました。

まぁポカーン枠確定なんですがw


スライドはこちら。

今時素のDRAMかよ!

という誰も得しない内容でしたが、発表後予想外にも(?)いくつか質問が飛んできたりと大変勉強になりました。

この後いろいろあって、ビット演算と格闘する羽目になったのですが・・・

2015年7月26日日曜日

DRAMと遊んでみる。


昨日1日、花火大会も行かず部屋に閉じこもり、21世紀にもなるのにDRAMのテストを行う。
SRAMと違ってかなり面倒なのは予想できたが…

DRAMにはアクセスする方法により、
Read,Write,Read-Write and Read-Modify-Write,RAS-Only Rifresh,Page-Mode Read,Page-Mode Write,CaS before RAS Refreshなど様々な方法がある。
それぞれ高速化の為の工夫だったりするのですが、複雑な手順はタイミングもシビアなのでここでは単純なものを実装してみました。
といってもArduinoが遅いのでこれでも厳しいようで全アドレスにアクセスするとデータが化ける。


今回の実験で知りたかったのは、リフレッシュ動作の挙動で、まずは必要なの?というのと実際どのくらいの頻度でやれば良いの?というずっと引っかかっていた点。
結果からすると、アクセス中は当然リフレッシュはできないから不要。
そして以外にも5秒や10秒間隔でもデータが飛ぶことはなく、30秒くらいで怪しくなるので(どれも通電中)、
電源切って30秒待つというのはあながち外れではないのかも。



こんな感じで実験中・・・





作成したプログラムはこちら。
https://github.com/・・・/blob/master/arduino_dram_test.ino
使用したDRAMはこれです。
http://www.datasheetarchive.com/・・・/Datas・・・/DSAP0024050.pdf



DRAMがXXXWord x 1bbitってなんで1bitなんだろ?と思っていたけど、
DRAMって1bitのメモリセルが正方形に並んでいて、縦横アドレスを指定してそのなかにある1bitを取り出すんですね。
てっきりクロックに同期して8bit分シリアルか何かで取り出すのかと。
あと、入力端子と出力端子が別、なんらかのモード切替で切り替えているのではなく、アクセスするタイミングだけでモードを判断している。読み書きだけでも16ものタイミングが決められているなど色々勉強になった。
タイミングは遅ければ待ってくれると思ったけど、最大時間が規定されているので、それを超えると動かないのは地味に嵌った・・・

リフレッシュは全セルを規定時間内に舐めないといけないのでマイコンには重い処理ですね。
あと、どうせ行アドレスと列アドレス連続アクセスするんだから毎回セットは面倒だなぁと思ってたら、それが後のEDOとかにつながるんですね。
仕事にも何にも役に立ちそうに無いですが、色々わかったのでよし(笑)

行アドレス指定してRAS下げて、列アドレス指定してCAS下げて。
でも立下りで読んでいるわけではなく、規定時間待ってから操作しないといけなかったり、データが出てくるまで少し時間がかかったりデジタルなのに挙動が面倒。

入出力が1bitなので、アドレス変えながら8bit分とってきてバイト変換して・・と結構苦労しました。
SIMMとかどうやってたんだろ?と回路図調べてみたら8個並べてたんですね。アドレス線共有して。
10進<->2進変換とかCでの文字列操作とかすっかり忘れてたよw

2015年7月21日火曜日

たまには旅立ちたいこともある・・・

このところ地味に色々しんどかったので、フラっと旅立とう。探さないでください・・・

ではないのですが、江田島にサイクリングに行って来ました。ボッチですが(ぉ

天気良いですね~
障害対応で呼び出されたくないですな。

N年ぶりにフェリーのチケットなんて買った気がします。
なお、サイクリングで。というと、自転車の乗車代が無料になるキャンペーンをやられていました。



フェリーって電車みたいに、前後に運転台があるんですよね。こちらは後ろ側。
港にバックで入るわけではないですからね。
うん?スクリューどうなっているんだろ??


ふむ。フェリーはDC12~32Vなのか(ぉ


さて、上陸したので散策しますか。

鷹?鷲?っぽいのが飛んでいました。

港町ってかんじですね~


お?ポータル発見(コラ

島の内部に入ると、寂れている風景とかあったり・・・


とか適当に山越えしたりしていたら、なにやらレンガ造りの建物が見えてきました。


が、体力が尽きかけていたので、手前の休憩所でしばし休憩・・・
ついでに中の展示を見て回りました。


ここでMAPをゲット。
自分のきたルートは峠とか坂ばっかり。


さて、気になるレンガつくりの建物ですが、旧海軍兵学校になります。
入館は無料ですが、公開時間が決まっていますので、いつでも入れるわけではなさそうです。


帰りは別ルートを辿っていこうと途中まで行ったのですが・・・



ガードレールが無かったり明かりがほとんど無かったりで危険と判断。
すごすご来た道を引き返しました。


途中なにかの演習場?っぽいのを見かけました。
来たときこんなのあったかなぁ・・・


なお、途中でのどが渇いたので自販機でお茶を買うも商品が出てこず、コカコーラにTELしても当然つながるわけも無く、
さらに、後日談として、半そで短パンでいったのが災いし、普段日焼けしないものが炎天下サイクリングなんてするものだから、ひどい日焼けというかほぼ火傷の状態になって、吐き気はするわ痛いわで数週間ほど苦しみました。
途中曇ってきたから・・とか紫外線は関係ないですねハイ。
皆さんも気をつけましょう。