読者です 読者をやめる 読者になる 読者になる

ハイパーニートプログラマーへの道

頑張ったり頑張らなかったり

【Ubuntu 16.04】MySQLを自動起動できるようにする

sysv-rc-confのインストール

$ sudo apt-cache search sysv-rc-conf
sysv-rc-conf - SysV init runlevel configuration tool for the terminal
$ sudo apt-get install sysv-rc-conf

mysql自動起動設定

$ sudo sysv-rc-conf --list
(中略)
mysql # なんにもない
$ sudo sysv-rc-conf mysql on
$ sudo sysv-rc-conf --list | grep mysql
mysql        2:on  3:on   4:on   5:on

vagrant上にUbuntuを入れているので、一旦 exit -> vagrant halt する。
そしてvagrantにログインしなおすと

$ sudo service mysql status
● mysql.service - LSB: Start and stop the mysql database server daemon
   Loaded: loaded (/etc/init.d/mysql; bad; vendor preset: enabled)
   Active: active (exited) since Sat 2017-03-04 02:10:14 UTC; 8min ago
...

active になっている。

参考記事:

Ubuntu 14.04 LTSでApache2やMySQLを自動起動する設定 - PHPやるお

当たって砕け散れ [mysql]ubuntuへmysqlの自動起動の登録

【RSpec】 Capybara + poltergeist にて rspec failed to detect theversion of the executable at '/usr/bin/phantomjs'

Ubuntu16.04上に構築しているRailsにてfeature spec (capybara + poltergeist) を走らせたときに

rspec failed to detect theversion of the executable at '/usr/bin/phantomjs' とかなんとかエラーでこける。

ちょっと古いですがこちらを見ると

stackoverflow.com

apt-getでインストールしたphantomjsは削除して、npmで入れてるみたい?

さらに調べると、apt-getで入れるphantomjsだと問題があるみたい。

obel.hatenablog.jp

この方もnpmで入れていますね。

というわけでまずUbuntuにnpmをインストールしました。

しかしapt-get だと入るバージョンが古かったり、node でなくて nodejs コマンドだったりします。

よって n package を使用します。

github.com


Specs

rails about で確認(バージョン古め・・・)


n packageの導入 〜 node のインストールまで

まずは普通にapt-getnodejs & npm のインストール

$ sudo apt-get install -y nodejs npm

次に n packageの導入

$ sudo n stable
$ echo $PATH # /usr/local/bin が含まれているかどうか確認 詳しくは後述
$ exec $SHELL # shellの再読み込み

参考にしたのはこちらの記事ですが

http://qiita.com/seibe/items/36cef7df85fe2cefa3ea

sudo n stable の後にsymlink を張っていますが、コメントにて

/usr/local/binが$PATHに含まれている環境においてはこのsymlinkは不要で、exec $SHELLでシェルを読み込み直すだけで使うことができました。

とありましたので、それを採用することにしました。


node, npm のバージョン確認

$ node -v
v7.6.0
$ npm -v
4.1.2

古いほうのバージョンは忘れてしまった・・・。

はじめに入れた(古いほうの)nodejs, npm の削除

$ sudo apt-get purge -y nodejs npm

phantomjs のインストール

$ sudo npm install -g phantomjs

nodejs-legacy は入れていません。

参考記事:

obel.hatenablog.jp

これでfeature testsが走るようになったぞい。ふぅ・・・。

CrystalでOSを作ってみた

この記事は Crystal Advent Calendar 2016 の25日目の記事です。

OSと言っても、ブートして文字を表示してるだけですが・・・こんなんです。

f:id:noriyo_tcp:20161225004431p:plain

リポジトリはこちら

github.com

軽く自己紹介

  • 普段はフリーランスRailsエンジニア(無職ともいう)
  • OS作りたい、という願望は以前からあった(話すとちょっと長くなるので割愛)
  • アセンブリC言語、Crystal に関しては初心者同然

参考にしたもの

Writing an OS in Rust

そしてRustの部分をCrystalで置き換えればいいやろ、と思っていましたがそんな甘い話があるわけもなく・・・。

ざっくり言うと、blog_osでは、Rust側で rust_main() という関数を用意します。

src/lib.rs

.
.
extern crate rlibc;

#[no_mangle]
pub extern "C" fn rust_main() {
    // ATTENTION: we have a very small stack and no guard page

    let hello = b"Hello World!";
    let color_byte = 0x1f; // white foreground, blue background

    let mut hello_colored = [color_byte; 24];
    for (i, char_byte) in hello.into_iter().enumerate() {
        hello_colored[i*2] = *char_byte;
    }

    // write `Hello World!` to the center of the VGA text buffer
    let buffer_ptr = (0xb8000 + 1988) as *mut _;
    unsafe { *buffer_ptr = hello_colored };

    loop {}
}
.
.

#[no_mangle]付けて pub extern "C" fn rust_main() していると。

それをアセンブリ側からこのように呼び出しています。

arch/x86_64/long_mode_init.asm

global long_mode_start
extern rust_main

section .text
bits 64
long_mode_start:
    ; call rust main
    call rust_main
.
.

全く同じことをCrystalでやろうとしましたが、上手く出来なかった・・・。pub extern "C" みたいなのはどうやるの・・・。name mangling を防ぐのどうするの・・・。

そこで次に参考にしたのはこれです。

crystal_library

Write C static (or shared) libraries in Crystal. This is just a Proof of Concept that exemplifies how to expose a Crystal library to the outside world, eg: C or any language with bindings to C.

ふむ、Crystalで静的(or 共有)ライブラリ作って、それをC言語に食わせればいいんだろうか。

ということはこんな感じ? assembly <- C lang <- Crystal

で、やってみましたが、リンク時に -no-stdlib オプションをつけているので当然、あれもないこれもないでコケまくります。
blog_osでも結局は、rlibc というcrateを導入することで、この問題を回避しています(しかしその後も色々問題は発生するようですが)

http://os.phil-opp.com/set-up-rust.html#rlibc

つ、詰んだ・・・。と思っていたところへ

os-crystal

そのものズバリなプロジェクトを発見します。

ここでは src/x86/loader.cr にて

@[Naked]
fun __entry()
  asm("mov $0, %esp" : : "Z"(0x00100000 + 0x1000));
  asm("push 0");
  asm("push 0");
  asm("call main")
  asm("hlt")
end

インラインアセンブリからシンプルに call main しています。で、呼び出される側は

src/main.cr

require "./x86/loader"
require "./x86/OutputConsole"

puts "Kernel booting with Crystal!"
puts
puts "<3"

こうなっているのですが、不思議なのはmainという関数ではなく、main.cr というファイルが呼び出されている?ということです。
いや、ほんとわかんない。でも確かに呼び出されている。
これで助かった・・・。

TODOs

というわけでまだまだこれからですが、最後は自分を叱って終わりにしたいと思います。

  • アセンブリ部分はほぼblog_osからのパクリじゃないですか。ちゃんと理解しているんですか? 低レベル言語をしっかりと勉強しなさい
  • Crystalの部分はほぼos-crystalからのパクリじゃないですか。なんとかしなさい
  • OSと言っても、ブートして文字出してるだけじゃないですか。カッコつけてオーガニゼーションアカウント取得して、よくわからないままリリースもしてしまっているんだから、行けるところまで行きなさい
  • そもそももっと早くから取り組んでいればこんなことには・・・。 見積もりの甘さと腰の重さをいい加減直しなさい
  • pineさんからgithubでフォローしてもらっているのに、すっかり忘れて放置しているじゃないですか。今すぐフォロバしなさい
  • コミニュティにも参加しなさい。「他人の輪の中に入っていく」という発想がごっそり抜け落ちてしまっているのは致命的です。もういい歳なんだからしっかりしなさい
  • 仕事が全然進んでいない。このままではクライアントに顔向けできないし、何より安心して年を越せないので仕事しなさい

こちらからは以上です・・・。

【Crystal】ランダムな数の中から最も差が小さい2つの数を取得する

Crystal 0.20.0
crystal play上で実行

def closest_two_numbers
  xx, yy, dd = 0, 0, 0
  dd = Float64::INFINITY
  seq = (1..100).map { Random.rand(10**10) }.sort.uniq
  seq.each_cons(2) do |cons|
    x, y = cons[0], cons[1]
    d = (x - y).abs
    if d < dd
      xx, yy, dd = x, y, d
    end
  end
  return [xx, yy, dd]
end

results = closest_two_numbers
puts "
the closest two numbers
-----------------------
1st number: #{results[0]}
2nd number: #{results[1]}
difference: #{results[2]}
"

なぜdd = Float64::INFINITYで正の無限大を用意しているかというと、1番最初のd < dd の比較に使用するため。
以降は、2つの数の差(d) をddに格納しておき、それをまた新たな2つの数の差と比較していくと。

実行結果は

the closest two numbers
-----------------------
1st number: 414497986
2nd number: 414546754
difference: 48768

こちらがPython3バージョン

from random import randrange
seq = sorted([randrange(10**10) for i in range(100)])
dd = float("inf")
for i in range(len(seq)-1):
  x, y = seq[i], seq[i+1]
  if x == y:
    continue
  d = abs(x-y)
  if d < dd:
    xx, yy, dd = x, y, d

result = """
the closest two numbers
-----------------------
1st number: %d
2nd number: %d
difference: %d
""" % (xx, yy, dd)

print(result)
the closest two numbers
-----------------------
1st number: 6437661962
2nd number: 6438850998
difference: 1189036

元ネタはこちらの Chapter 4 - INDUCTION AND RECURSION ... AND REDUCTION より

Python Algorithms: Mastering Basic Algorithms in the Python Language

Python Algorithms: Mastering Basic Algorithms in the Python Language