Yuki猫のおうち

気ままに自由に日々を生きる

2018年の抱負

2017年はこのブログ放置しすぎたので、2018年は何かやります。

 

一年半ほど職業プログラマとしてphpをガリガリ書いてきて、設計思想とかメモリ効率のいい実装とか、色々知識はついていると自負しているんだけれども、それを全くアウトプットしてないなぁと。

 

業務に関わる話なのでそのまま書けるわけでもないというのもあるけれど、自宅で全くプログラミングしなくなったのも要因の一つかなぁと。

 

流石にエンジニアとして死んでるよなぁ、まずいよなぁ、と思ってはいるものの2017年は結局行動しないで終わってしまった……

 

ので、直近の行動しますよ宣言をここに書いておきます。

 

1.データベーススペシャリスト試験受けます

2.競プロ始めます

 

デスペは春試験の合格を目指して頑張ります。

競プロは、1日1問とかのスローペースな感じで毎日PCを開いてコードを書く習慣をつけられたらいいなぁ、と思っています。

[php]phpの文字列比較時に自動型変換されているのを知らなくてハマった話

違う文字列なのに一致する...?

phpは型の制約が緩い分、意図しないところで勝手に型変換されていたりして困っちゃうことが時々あります。

例えば、文字列の比較を==で行うと、以下のような驚きの結果に。

$ echo "5seq" == 5; // true
$ echo "3.0" == "3"; // true

これは、==で整数値と文字列を比較する際、文字列を内部処理でint型にキャストしてしまっていることが原因です。

どうすればいいのか?

文字列の比較の際には===を使うことで、明示的にstringでの比較を行うことができます。

$ echo "5seq" === 5; // false
$ echo "3.0" === 3; // false


また、数字での比較を明確に行いたいならば、is_numeric()メソッドで文字列が数字であることを保証するという方法が取れます。
formから受け取ったユーザ入力を扱う場合などは、面倒ですが比較の前にこの処理をはさんでおくと確実です。

$str = "5sec";
if(is_numeric($str)) { // ここでfalseになる
  if($str == 数字) {
    ...
  }
}

あるいは、扱う文字列が明確に数字である場合などは、あらかじめ明示的にキャストしてしまうという手もあります。

  $str = (int)"3min";
  if($str == 3) { // true
    ...
  }


型が緩いと便利ではありますが、コードを書く際はしっかりと意識しないといけませんね。

お名前vps(kvm)上のCentOS7にシリアルコンソールでssh接続する方法

接続できない...

vpsサーバのネットワークが不調になった時とか、ssh接続できなくなった状況だといつも管理画面でブラウザ上からコンソールにアクセスしていた。
ただこのブラウザ上のコンソール、コピペができなかったりしてすごく使い勝手が悪い。
できればブラウザからじゃなくて、ターミナルから操作したい。
そこで、シリアルコンソール接続でターミナルからssh接続する方法があるらしいのでやってみた。

guide.onamae-server.com

なんだ意外と簡単に設定できるじゃん、と思ったら、

$ssh hogehoge
 Last login: Sat Jul 16 22:48:18 2016 from 106.161.167.199
 [Enter `^Ec?' for help]

ここで操作不能になった。ログインに遷移しない...
しかもC-cが効かなくてプロセスも落とせない...

設定が簡単とか、そんなうまい話はなかったのだ。

いざ、解決の旅へ

説明通りやっているのに、なぜログインできないのか。
調べてみると、どうもサーバ側でシリアルコンソール接続の設定をしないとダメらしい。

いろいろやってみた結果、このサイトの方法で解決できた。

www.nightmare-yk.com


まず、以下のコマンドで設定ファイルを編集して、新規作成する仮想端末ttyS1とserialの対応を行う。
編集したのは以下の4行。

$ vi /etc/default/grub
 ~
 GRUB_TERMINAL_OUTPUT="serial console"
 GRUB_CMDLINE_LINUX="console=tty0 console=ttyS0,9600 console=ttyS1,9600"
 ~
 GRUB_TERMINAL="console serial"
 GRUB_SERIAL_COMMAND="serial --speed=9600 --unit=0 --word=8 --parity=no --stop=1"

そして反映。

$ /usr/sbin/grub2-mkconfig -o /boot/grub2/grub.cfg

次にgettyの設定を行う。
この辺りの処理は調べていくとsystemdがどうとかと書いてあったのだが、よくわからなかったので後で勉強することにして、まずは無心にコマンドを叩く。

雛形をコピって、ログインシェル振り分けるところにシンボリックリンク貼って、デーモンにサービス追加して、最後に自動起動設定してる。多分。

$cp /lib/systemd/system/serial-getty@.service  /etc/systemd/system/serial-getty@ttyS1.service 
$ ln -s /etc/systemd/system/serial-getty@ttyS1.service /etc/systemd/system/getty.target.wants/
$ systemctl daemon-reload
$ systemctl start  serial-getty@ttyS1.service
$ systemctl enable serial-getty@ttyS1.service

ここまで出来たら、最後に以下のファイルを編集して、ttyS1の存在を教えてあげる。
このsecurettyはrootでログインできる端末のリストらしい。

$ vi /etc/securetty
~
ttyS1
~

これで設定は完了。

$ shutdown -r now

サーバを一度再起動して、ログインを試みる。

$ ssh hogehoge
 Last login: Sun Jul 17 00:52:35 2016 from 106.161.167.199
 [Enter `^Ec?' for help]

 CentOS Linux 7 (Core)
 Kernel 3.10.0-327.22.2.el7.x86_64 on an x86_64

 yukineko login:

できた!!

こんな面倒な設定するだなんて、公式のどこにも書いてなかったよ...

新たなる問題

今度はシリアルコンソール接続を終了できなくなってしまった...誰か助けて...

gitで追跡ファイルの大文字小文字を区別する

大文字小文字区別

gitはデフォルトだと大文字小文字の区別をしない設定になっているらしい。

$ git config --list
   ~~
$ core.ignorecase=true
   ~~

ignorecaseをfalseに設定すると区別してくれるようになる。

# 大文字小文字を区別する場合
$ git config core.ignorecase false

これで変更できた。

$ git confiig --list
   ~~
core.ignorecase=false
   ~~

そもそも、大文字小文字でファイルを分けることなんて滅多にないんだけれども。

久しぶりにサーバにログインしようとしたらsshできなかった時の話

経緯

お名前.comに借りたサーバを4か月ほど放置してたんだが、久々になんかやろうと思ってsshしてみたら接続できなくなっていた。
かまってあげないから拗ねちゃったのか?

試行錯誤

とりあえずpingしてみる。
$ ping yukineko.work
 PING yukineko.work (133.130.66.130): 56 data bytes
 Request timeout for icmp_seq 0
 Request timeout for icmp_seq 1
 Request timeout for icmp_seq 2

 --- yukineko.work ping statistics ---
 4 packets transmitted, 0 packets received, 100.0% packet loss


Request Timeoutが発生した。ネットワークに問題があるらしい。

サーバの中で調査

仕方ないので管理画面のコンソールからサーバに入って、サーバ内部でもpingしてみる。

$ ping google.com
 connect: Network is unreachable

今度はnetwork is unreachableとエラーが出た。
え、サーバの外に出れない...

まさかnetworkが息をしてないのか?

$ nmcli device
 DEVICE  TYPE      STATE        CONNECTION
 eth0    ethernet  disconnected    eth0
 lo      loopback  unmanaged    --

案の定eth0デバイスが死んでいた。

お前いつの間に死んだんだ。

解決

$nmcli connect up eth0

上記コマンドでeth0デバイスを起こしてあげたら、無事ssh接続することができるようになった。

めでたしめでたし。

eth0はなぜ死んだ?

ところで、ネットワーク設定が勝手に切れるはずはないので、何が起こったのかちょっと調べてみたので忘備録。
まずはサーバの起動日時を調べてみる。

$ uptime
 23:13:57 up 25 days, 19:39,  2 users,  load average: 0.07, 0.03, 0.05

あれ、なんか25日前にサーバが起動してる...
もしかして、メンテナンスか何かで一度サーバが再起動されたのか?

案の定、eth0の設定ファイルを開いてみたらONBOOTがnoになっていた。

$ cat /etc/sysconfig/network-scripts/ifcfg-eth0
 TYPE=Ethernet
 NAME=eth0
 ~~
 ONBOOT=no
 ~~

これが原因か......

ONBOOTの値をyesに変更しておけば、次は大丈夫なはず!

インデックスと複合インデックスのうまい使い方

dbの検索高速化

大量のデータがあるデータベースには、select文の実行速度を上げるためにインデックスを作成することが多い。
最近データベースを勉強していて、複合インデックスなるものの存在を初めて知ったので詳しく調べてみることにした。

以下のサイトがとてもわかりやすくまとめてあったと思う。

qiita.com

use-the-index-luke.com

このサイトはもう一歩くらい踏み込んでいて、読んでいて面白かった。

nippondanji.blogspot.jp

学んだこと

  • 複合indexは左側に定義したものから順番にしか使えない
    • 一つでも多くのクエリがindexを利用できるように指定するカラムの順番を熟慮する
  • mysqlのindexはデフォルトではB-Treeで作成される
  • mysqlでは、一つのクエリで使えるindexは一つだけ
  • データの更新がある度にB-Treeが更新される
    • indexが大量にあると、更新するB-Treeが大量になるため一部のクエリが遅くなる
    • データが大量にある場合、B-Treeも巨大になるため一部のクエリが遅くなる

結論

何でもかんでもとりあえずindexを貼っておけばいいというものではないのだなぁ。

あと、mysqlの公式ドキュメントが結構読みやすかったので、ぼちぼち読んでいこうと思う。

sshで公開鍵認証を行ったときに「Permission denied」が発生したときの対処法

よくあるエラーな「Permission denied」

一般的なPermission deniedの解決法はネットを漁ればたくさんヒットするので割愛するが、稀にそれでも解決できないときがある。

$ ssh -i ~/.ssh/id_rsa_hoge foo@hugahuga
 Permission denied (publickey).
 fatal: Could not read from remote repository.

解決法

そんなときに試してみたい方法がこれ。
sshクライアントが秘密鍵の存在を知らないという可能性を疑ってみる。

$ eval `ssh-agent` // sshエージェントを起動
$ ssh-add ~/.ssh/id_rsa_hoge // sshエージェントに秘密鍵を登録
 Enter passphrase for ~/.ssh/id_rsa_hoge:

これで秘密鍵をエージェントに教えてあげれば、先ほどのsshコマンドが通るようになっているはず。

$ ssh -i ~/.ssh/id_rsa_hoge foo@hugahuga

http://webos-goodies.jp/archives/50672669.html
上の記事を見る限り、別にssh-agentが秘密鍵の存在を知らなくてもssh接続自体はできそうな感じがする。

もしかして、id_rsaの鍵を作成済みの状態で別の鍵ペア(id_rsa_newとか)を生成すると、ssh-agentが自動でid_rsaの方を参照しちゃって「鍵違うよ」となっているとか、そういうことなんだろうか...

わからん...