下級エンジニアの綴

新しく発見したことを綴っていこうと思っています。夢はでっかく上級エンジニアになることです。

ssh先のサーバでrailsサーバを立ち上げるシェルを書いたのはいいけど、sshをkillするとrailsのプロセスが残ったままになったのでメモ

今回ハマった点ですが、タイトルの名の通りssh先のサーバでrailsサーバを立てるシェルを書いたのでが、ctrl + c で抜けるとsshはkillされてrailsのプロセスがssh先のサーバで残ったままだったので、解決方法を模索したメモになります。

ssh hostname 'rails s -b 0.0.0.0 -p 3005'

とコマンドを実行した時、ssh先のサーバでrailsサーバを立ち上げてテストを行おうと思っており、実際に問題なく立ち上げることには成功しました。しかし、ctrl + cで処理を終了させるとsshのプロセスだけ死んでrails sのプロセスだけずっと残ったままでした。

プロセスを確認すると↓のようになっており、

$ ps aux | grep ruby
508      17276  1.0  5.2 406732 155300 ?       Sl   12:24   0:05 bin/rails s -b 0.0.0.0 -p 3105
508      17587  0.0  0.0  81796   836 pts/0    S+   12:32   0:00 grep ruby

調べてみると、ttyとかptsの問題のようでした。 下記の記事でわかりやすく説明してくださってました。

qiita.com

簡潔に説明すると

ターミナルからアクセスしていると pts/ というものが表示され、 と表示されている場合はdemonで立ち上がっているよという目印みたいでした。

上記を解決する方法ですが、

ssh -t hostname 'rails s -b 0.0.0.0 -p 3005'

-t オプションを付ければ良いみたいでした。

LINE DEVELOPER DAY 2017に行って来ました

Line Developer Day に行って来ました f:id:yanterakun:20170929003922j:plainf:id:yanterakun:20170929003757j:plain 昨年も参加したのですが、ブログに書くのは今年が初めてになります。

受付

受付を完了するとお昼代としてヒカリエお食事券をいただきました。(2000円分) 写真を撮り忘れていたので、写真はありませんorz 受付を済ませオープニングセッションのホールへ向かう途中に f:id:yanterakun:20170929003820j:plain ホームスピーカーが展示されていました。(めっちゃ欲しかったです

午前のセッション

午前のセッションは2つだけでLineのオープニングとLineが最近力を入れているAI、clovaの2本立てでした

Opening Session

openingはLINEがどのようにしていきたいという話と、もっとossに力を入れていくので、エンジニアのみなさんも力を貸してくださいという内容でした。私自身は勿論OKでした。エンジニアに優しいLINEのお願いとあっては断れるはずありません。

www.slideshare.net

The Technologies in Clova

clovaのセッションではlineがclovaをどのように定義し、これから展開していくかというお話でした。

一番びっくりしたのが、clovaを搭載したwavaは1年前にプロジェクトが始まったらしいです。地固めをしっかりしているLINEさんだからこその開発スピードなのかなと思いました。

(Line Developer Dayのアンケートに回答するとwaveが50名に当たるそうなので、めっちゃ欲しいです。ブログ書くので当たらないかなーって思ってました。)

www.slideshare.net

LUNCH TIME

ランチはお寿司を頂いて来ました。とっても美味しかったです。 f:id:yanterakun:20170929010954j:plain ランチが終わると11階のカフェで休んでいました。f:id:yanterakun:20170929011251j:plain (これだけものが無料で提供されていたので、Lineの懐の深さに驚愕です。

午後のセッション

Gateboxのこれまでとこれから

Gateboxってなにかというとホームスピーカー1つですが、AmazonGoogle、Lineと違うところは端末にキャラクターが存在しており、感情豊かなキャラクターがいるということでした。

いわゆる俺の嫁みたいな感じらしく、コンセプトムービーを見ましたが、これは是非欲しいなと思いました。

clovaとgateboxの提携が決定しているらしく、どちらかに吸収されるという事ではなく、互いに良いところを取り入れて来たいねという形での提携されるそうです。

www.youtube.com

www.slideshare.net

Paying back technical debt - LINE Androidクライアントの事

リファクタリングをしやすい文化と技術を取り入れましょうという内容でした。 ボーイスカウトルールはチームの文化に是非取り入れていきたいなと思いました。(めっちゃ耳が痛いですが

www.slideshare.net

休憩

ここから1時間ほど元会社の上司の方とお話していました。

LINEにおけるBluetoothを活用した取り組みの紹介

主にline beaconの話でした。 本屋と連携しており、LINE漫画を読むことにより、限定特典などもらえるみたいでした。

Tappinessは自販機にline beaconを仕込んでおり、 lineを立ち上げて自販機に端末を近づけるとline payまたは現金で決済が出来、15ポイントでクーポンがもらえるみたいです。

なるほど、line beaconをlineの入った端末のネットを使ってサーバと連携するのか・・・(web buletoothを参考にしているらしいです。

line simple beaconはbuletoothの端末をline beaconに出来るソフトウェアらしく、ラズパイとか使って一回試して見たいなと思いました。

www.slideshare.net

Parallel Selenium Test With Docker

翻訳機を使っていたのですが、英語がかなり聞きやすかったので、英語聴きながら日本語を聞くと訳が分からなくなるので、途中から使うのをやめました。

内容はスライドを見ていただくと8割くらい理解できると思います。

docker+jenkins+seleniumでのテスト行う環境、良いなぁ。

www.slideshare.net

休憩

疲れたので次のセッションは参加せずに休憩してました。 フラフラしていると、上記セッションでお話をされていたTappinessの自販機を発見したので、利用させていただきました。

使い方はLineを起動すると自販機のline beaconが反応するので、Line Payまたは現金で決済を行うと買えました。

suicaと違ってドリンクポイントが貯まり、何回か利用するとお得になると思うと、あったら使うなと思いました。 f:id:yanterakun:20170929012919j:plain f:id:yanterakun:20170929012902j:plain

BOT and the new Comfortableness

最後の技術セッションは message api とline loginの連携が出来るようになったみたいです。

グループを作成した時にユーザーのIDを取得できるようになったので、 個別のユーザーに対してのリアクションが可能に。

rich menuのレイアウトが自由に構築できるようになるみたいです。 自由なデザインが可能になるので、これは遊ぶ楽しさが増えますね。

ただし、rich menuのapiの更新はcommig soonらしいです。 line bot studioも近いうちにリリースされるみたいです。 ( 非エンジニアの人がカルーセルとかで出てくるものを選択してline botが作れるみたいです。コード書けなくてもできるというのが凄いなと思いました。

clovaのAPIも近い内に公開されるみたいです。

結論、rich menuのapiの更新・line bot studio ・clova apiはまだなので、とりあえずmessage apiとline loginで遊んでみてくださいとのことでした。

line api expertが公開されるみたいで、要は一緒にline api作ってくれる人募集との事でした。

www.slideshare.net

Closing Session

クロージングでは本日のセッションの振り返りとLineのこれからどのように展開していくのかというお話でした。京都にも開発拠点は学生との交流がメインであったりと、次を見据えているLineは改めてすごいなと感じさせられました。

www.slideshare.net

最後に

本日のアンケートに回答するとノベルティがもらえました。 その時にclova waveの抽選もあったのですが、筆者は見事当選しました!!

(左上 : ステッカー、右上 : マグカップ、下 : クローバー栽培キット f:id:yanterakun:20170929021621j:plain (clova wave f:id:yanterakun:20170929021656j:plain これで当分頑張れそうな気がします。

本当Line Developer Day最高でした。

開催して下さった関係者のみなさんありがとうございました!

来年も開催されたら是非参加させて頂きたいなと思っています。

linux(centos)の公開鍵を置いているサーバーにsshが出来なくて嵌まったのでメモ。

今回は公開鍵を置いているサーバーにsshが出来なくて嵌まって調べたメモになります。

状況

  • .sshフォルダの権限は700で所有者はログインユーザー
  • authorized_keysの権限は600で所有者はログインユーザー
  • 公開鍵と秘密鍵は対になっている
  • タイポもしていない

この状況でsshが出来ませんでした。

理由

view /var/log/secure

ここに

User your_username not allowed because account is locked

と書かれていました。

↑のログはssh_configの設定でパスワードの設定をしてないユーザーがsshしようとする時に出るみたいです(アクセスを弾いちゃいます)。

view /etc/shadow

↑を見るとUSERNAME:の次に「!!」と書いて有る場合は lockされているみたいです。(パスワードが設定されていると「!!」ではなくランダムの文字列になっているみたいです。

解決

passwd user_name

↑のようにloginユーザーのpasswordを設定してあげるとsshが出来るようになりました。

参考URL

tkuchiki.hatenablog.com

Rspecでインスタンスメソッドのテストに苦労したのでメモ

今回はRspecでメソッドのテストをしたかったのですが、メソッド内で定義しているメソッド先の処理のテストは記述したくなかったので、それを解決したメモになります。

rubyのコード

# 今回テストしたかったのはTest1のexecuteメソッドになります
Class Test1
  def self.execute(test_params)
    Test2.execute(test_params)
    Test3.new(test_params).execute(test_params) # ←こいつが一番の曲者でした
  end
end

Class Test2
  def self.execute(test_params)
    p test_params + 'test2'
  end
end

Class Test3
  def initialize(test_params)
    @test = test_params + 'test3'
  end

  def execute(test_params)
    p @test + test_params + 'test3'
  end
end

テストコード

require 'rails_helper'

RSpec.describe Test1 do
  describe 'テスト1'
    it 'interfaceのテスト'
      test = double('Test3:00000000')
      allow(Test2).to receive(:execute).and_return(true)
      allow(Test3).to receive(:new).and_return(test)
      allow(Test3.new("")).to receive(:execute).and_return(true)
      Test1.execute(anything)
    end
  end
end

Test3のテストコードですが、。最初は下記のように記述していました。

allow(Test3).to receive(:new)
allow(Test3.new("")).to receive(:execute)

↑だとexecuteを呼ぶ時にno method errorがでます。

Test3で定義しているexecuteはクラスメソッドではなくインスタンスメソッドなので、インスタンスにメソッドを定義しないとエラーが出てしましました。

なので、

test = double('Test3:00000000')

↑でインスタンスを定義して

allow(Test3).to receive(:new).and_return(test)

↑でnewした時の戻り値にインスタンスを返えすようにします。

allow(Test3.new("")).to receive(:execute)

↑でインスタンスにexecuteメソッドを定義することによって

Class Test1
  def self.execute(test_params)
    Test2.execute(test_params)
    Test3.new(test_params).execute(test_params) # ←こいつのテストが通るようになる
  end
end

Test3のテストが通るようになります。(解決するまでにめっちゃ時間がかかりました。

参考URL

qiita.com

docker-composeでRAILS_ENVを切り替えて実行する方法を調べたのでメモ

今回はrspecを実行したいけど、わざわざdockerのコンテナの中に入って実行するのはイケてないと思い、調べたそのメモになります。

docker-compose exec test bash
RAILS_ENV=test_docker rake db:migrate:reset
RAILS_ENV=test_docker rspec

↑のコマンドを叩きたくないので

docker-compose exec test RAILS_ENV=test_docker rake db:migrate:reset
docker-compose exec test RAILS_ENV=test_docker rspec
## rpc error: code = 2 desc = oci runtime error: exec failed: container_linux.go:262: starting container process caused "exec: \"RAILS_ENV=test_docker\": executable file not found in $PATH"

と叩くと↑のようなエラーが出て上手く動きませんでした。

なので、

docker-compose run -e RAILS_ENV=test_docker test rake db:migrate:reset
docker-compose run -e RAILS_ENV=test_docker test rspec

↑のようにrunする時に-eをつけると、envの指定が出来たので、上手く動きました。

ログインするというより、使い捨てのインスタンスを立てるって感じですね。

参考URL

blog.codeship.com

railsのhash#tryでちょっと躓いたのでメモ

railsでhashにtryをかけているとエラーが出たので、その時に調べた内容をメモ。(一度先輩に教えてもらった気がするのですが完全に忘れてましたorz

本題

この書き方だとhashにkeyが存在する時は問題無いのですが、

{ name: 'yantera' }.try(:fetch, :name)
# => "yantera"

hashにkeyが存在しない時はerrorになります

{}.try(:fetch, :name)
# KeyError: key not found: :name
# from /usr/local/bundle/gems/activesupport-4.1.8/lib/active_support/core_ext/object/try.rb:45:in `fetch'

解決するには以下の2パターンがありました。

  • 自分でdefault値を設定する
    • 同時に好きな値を定義できる
  • []メソッドを設定する
    • メリットはシンプルに書ける
{}.try(:fetch, :name, nil)
{}.try(:fetch, :name, 1)
{}.try(:fetch, :name, 'yantera')
# => nil
# => 1
# => "yantera"

{}.try(:[], :name)
# => nil

参考リンク

qiita.com

小ネタ

  • tryの中身はこのようになってます
    • aにはtryを呼ぶときの引数が配列で入って、bにはブロック文が入ります。
def try(*a, &b)
  if a.empty? && block_given?
    yield self
  else
    public_send(*a, &b) if respond_to?(a.first)
  end
end

要は下のように呼ぶと

{}.try(:fetch, :test, 1) do
  p 'test'
end
# a
# => [:fetch, :test, 1]
# b
# => #<Proc:0x007f5b9bf15f88@(pry):2>

が入ります。

  • if文を見るとaがemptyでかつブロック文が投げられている時、自分で作成したブロックぶんが呼ばれるという内容ですね。
{}.try() do
  p 'test'
end
# => 'test'

というように使えます。(用途はわからないですが)

続いてelseの方ですが

def try(*a, &b)
  if a.empty? && block_given?
    yield self
  else
    public_send(*a, &b) if respond_to?(a.first)
  end
end

self(Hash)にa.firstのメソッドがあれば実行されるので

{}.try(:fetch, :test, 1) do
  p 'test'
end
# a
# => [:fetch, :test, 1]

この場合fetchが呼ばれます。fetchメソッドははhashのkeyをとって実行するので、

{}.fetch(:test, 1)
# => 1
{}.fetch(:test)
# KeyError: key not found: :test

の形になり、hashの中にkeyが存在していると、そのkeyの値が返りますが、デフォルト値を定義していないとKeyErrorになります。

[]はhashからkeyを取るメソッドなので

{}.[] :test
# => nil

という風にかけます。

また、

hoge = {}
hoge.[] :test
# => nil

hoge.default = 1
hoge.[] :test
# => 1

hashにdefault値を設定できるみたいで、指定しなければnilが返りますが、指定すると好きな値に出来るみたいでした。

rubyの特異メソッドのprivateについて気になったから調べたのでメモ

特異メソッドでprivateなメソッドを呼ぶ方法

  • sendを使う
    • privateの特異メソッド、privateのインスタンスメソッドを関係なく呼べる
    • 最終手段な感じがするので、あまり推奨できないと思った
class A
  def self.hoge
    A.new.send(:fuga)
  end

  def self.aaa
    A.send(:bbb)
  end

  def self.bbb
    p 'bbb'
  end

  private

  def fuga
    p 'fuga'
  end

  private_class_method :bbb
end

A.hoge      # "fuga"
A.aaa       # "bbb"
A.new.fuga  # private method `fuga' called for #<A:0x007f3ac14fb2f0> (NoMethodError)
A.bbb       # private method `bbb' called for A:Class (NoMethodError)
  • private_class_methodを使う
    • 特異メソッドが少ない時はこちらを使用する
    • privateにしたいメソッドを定義した後にprivate_class_methodで定義する
class A
  def self.hogo
    fugo
  end

  def self.fugo
    p 'fugo'
  end

  private_class_method :fugo
end

A.hogo  # "fugo"
A.fugo  # private method `fugo' called for A:Class (NoMethodError)
  • class << selfを使う
    • 特異メソッドが多い時に使用する
    • 階層が1段多くなるがメソッドにclass << self~endまでに定義したメソッドが特異メソッドになる。
    • private以下に定義したメソッドは特異クラスのprivateメソッドになる
class A
  class << self
    def hoo
      foo
    end

    private

    def foo
      p 'foo'
    end
  end
end

A.hoo  # "foo"
A.foo  # private method `foo' called for A:Class (NoMethodError)