Raspberry Pi 3にNode.jsをインストール

どうも.
もうそろそろ,ラズパイになれてきたところで
Node.jsをインストールしてみたいと思います.

通常のCentOSでは,

# yum install epel-release
# yum install nodejs

でインストールすることができるのですが
なにせRaspberry Pi 3ではepelが対応していないので
このやり方をやることはできません!
なので,yumを使わずにNode.jsをインストールしてみたいと思います.

# wget https://nodejs.org/dist/v4.0.0/node-v4.0.0-linux-armv7l.tar.xz
# tar -xvf node-v4.0.0-linux-armv7l.tar.xz 
# cd node-v4.0.0-linux-armv7l
# sudo cp -R * /usr/local/

参考:Blog | Wia

これで,インストールができたと思います.
インストールされたかを確認するには,

# node -v
v4.0.0

と入力して,表示されれば大丈夫です.

npmとは

今回のやり方では,同時にnpmというコマンドもインストールされます.
まず,npmとは何かについて説明したいと思います.

Node Packaged Modules(npm)とはNode.jsのライブラリやパッケージを管理することができるツールです。
ライブラリやパッケージの管理ツールを主にパッケージマネージャと呼びます。

引用:STEP2-4.パッケージマネージャのnpmとは / チームラボ オンラインスキルアップ課題

つまり,Pythonでいうpip,Rubyでいうgemと同じってことですね.
今後は,お世話になると思います.

Node.jsのバージョンの違い

最初に説明したyumのやり方では,バージョンv0.10.xがインストールされる一方,
今回のやり方では,バージョンv4.0.0がインストールされています.
最初,見た時「これ,大丈夫なの!?」って思ったぐらいバージョンが違いますよね(笑)
よくよく調べてみると,v.4.0.0の方が性能が向上しているようなので良さ気です.
詳しくは,以下のサイトを参考にしてみてください.

html5experts.jp

Raspberry Pi 3でyumが使えなくなる問題

どうも。
Raspberry Pi 3にCentOSを入れたもののyumが使えなくなり、3回も初期化した者です。
いやぁー、ラズパイにものすごく悪戦苦闘していますが、
ネットワーク関係に関する知識が非常に身につきます。

今回発生した問題として、yumでいろいろとやっていたら、

# yum list
Loaded plugins:fastestmirror
http://mirror.centos.org/altarch/7-2.1511.el7.centos.0.4/os/armhfp/repodata/repomd.xml:
[Errno14] curl#6 - "Could not resolve host: mirrorlist.centos.org; Name or service not known"
Trying other mirror.

One of the configured repositories failed (CentOS-7-2.1511.el7.centos.0.4 - Base),
and yum doesn't have enough cached data to continue. At this point the only
safe thing yum can do is fail. There are a few ways to work "fix" this:

    1. Contact the upstream for the repository and get them to fix the problem.

    2. Reconfigure the baseurl/etc. for the repository, to point to a working
       upstream. This is most often useful if you are using a newer
       distribution release than is supported by the repository (and the
       packages for the previous distribution release still work).

    3. Disable the repository, so yum won't use it by default. Yum will then
       just ignore the repository until you permanently enable it again or use
       --enablerepo for temporary usage:

           yum-config-manager --disable <repoid>

    4. Configure the failing repository to be skipped, if it is unavailable.
       Note that yum will try to contact the repo. when it runs most commands,
       so will have to try and fail each time (and thus. yum will be be much
       slower). If it is a very temporary problem though, this is often a nice
       compromise:

           yum-config-manager --save --setopt=<repoid>.skip_if_unavailable=true

failure: repodata/repomd.xml from base: [Errno 256] No more mirrors to try.
[Errno14] curl#6 - "Could not resolve host: mirrorlist.centos.org; Name or service not known"

というエラーが出るようになってしまいました。


そこで今回、最も苦しんだyumに関することを今後も忘れない、
かつyumの仕組みを理解するために記事にしたいと思います。

環境

Raspberry Pi 3
CentOS 7.2

そもそもyumとは…

RedHatディストリビューションのパッケージ管理システムの事です。
リポジトリと呼ばれるパッケージ置き場からのパッケージをダウンロードし、インストール、アンインストール、更新をする事ができます。
その際、各パッケージの依存関係を自動的に解決し、関連するパッケージがどれなのか教えてくれたり、
必要な場合は、関連パッケージをダウンロードしてそのまま更新してくれたりしてくれます。

引用:パッケージの管理|yumとは

yumは、パッケージを管理するコマンドとなっています。
Ubuntuで言う、apt-getと同じです。
で、yumで覚えてほしいのはrpmコマンドと異なり、ネットワーク経由でパッケージをダウンロードし、インストールします。
なので、基本的にyumでパッケージをインストールし、問題が発生したらrpmでインストールするというのが一般的だと思います。

リポジトリの設定

パッケージのダウンロードに用いるリポジトリの設定ファイルは、「/etc/yum.repos.d/」にあります。
まず、リポジトリには、2種類あります。
1つ目が、CentOSのデフォルトのリポジトリです。
それに関する設定は、基本的に「CentOS-Base.repo 」に記述されています。
2つ目が、サードパーティが公開しているリポジトリです。
一般的に、remiやepelが有名だと思います。
これらを用いることで、デフォルトのリポジトリで対応していないパッケージなどをダウンロードすることができます。

設定ファイルの説明

それでは、実際にリポジトリの設定ファイルの中身を見てみましょう!

# vim CentOS-Base.repo

〜〜 省略 〜〜

[base]
name=CentOS-$releasever - Base
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os&infra=$infra
baseurl=http://mirror.centos.org/altarch/$releasever/os/$basearch/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
       file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-SIG-AltArch-Arm32

#released updates 
[updates]
name=CentOS-$releasever - Updates
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=updates&infra=$infra
baseurl=http://mirror.centos.org/altarch/$releasever/updates/$basearch/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
       file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-SIG-AltArch-Arm32

〜〜 省略 〜〜


mirrorlistやbaseurlがリポジトリ参照先のURLとなっています。
あと、覚えとくのは、「enabled=1」だとリポジトリを有効にするって意味です。
無効にしたい場合は、「enabled=0」にすれば大丈夫です。
ちなみに、無効にしたけど、一時的にそのリポジトリを使いたい場合は以下の通りにすれば使えます。

# yum --enablerepo=remi install php

他にも、ここで重要なのが$releaseverなどのYum変数と呼ばれる変数です。
個人的に覚えた方がいいと思うのは、2つだけだと思います。

$releasever CentOSのバージョンの値
$basearch システムのベースアーキテクチャーの値(x86_64など)

問題の原因

http://mirror.centos.org/altarch/ にアクセスしてみたら分かりますが、
「7-2.1511.el7.centos.0.4」というディレクトリはありません。
同様に、Raspberry Pi 3は64bitなので、「$basearch=x86_64」だと思ってしまうんですが、異なるアーキテクチャの値が代入されています。
そう、問題の原因はラズパイのアーキテクチャリポジトリの参照URLがうまく対応してないので、ダウンロードできないからです。

解決策

なので、問題が発生したら

# baseurl=http://mirror.centos.org/altarch/$releasever/updates/$basearch/
                    ↓
                    ↓
                    ↓
# baseurl=http://mirror.centos.org/altarch/$releasever/updates/x86_64/

にすれば大丈夫だと思います。

あと、他にも
サードパーティリポジトリは、ラズパイに対応していません!
サードパーティリポジトリの設定ファイルで「enabled=1」となっていることが原因で
Not Foundなどのエラーが発生することがあります。

CentOS 7にApacheを導入しようとして挫折する物語

これは、CentOS 7.2をインストールしたRaspberry Pi 3にApacheを導入する物語である。
筆者は、CentOSを3年もいじっているので、Apacheを入れるなんて朝飯前。
サーバを何回も初期化して、幾度とApacheを入れ直してるんで
Apacheを入れるのなんかカップラーメンにお湯を注ぐぐらい簡単だよって思ってます。

やることを頭に描き

## Apacheのインストール
# yum install httpd

## Apacheの起動および自動起動の設定
# service httpd start
# chkconfig httpd on

## 80番ポートの開放
# vim /etc/sysconfig/iptables
-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT // 追加
# service httpd restart

サラッと、これを実行して、http://__IP_Address__ にアクセスして下の画面を確認しよう!

f:id:usmysa:20160529172640p:plain

第一章 Apacheを起動させよ

一瞬でApacheをインストールし、いざApacheを起動させようとした時、
普段なら下みたいに表示されるのに、表示されない…
まぁ、いっか。
きっと起動してるはず!

# いつも表示される結果
# service httpd start
httpd を起動中: httpd: Could not reliably determine the server's fully qualified domain name, using localhost.localdomain for ServerName
                                                           [  OK  ]
# 今回、表示された結果
# service httpd start
Redirecting to /bin/systemctl start httpd.service

第二章 挫折への前触れ

じゃあ、次にポートの開放をやってみよう。
えっ…「/etc/sysconfig/」に「iptables」がない…!
うん、きっと80番ポートはデフォルトで空いてるはず…

第三章 大いなる挫折

さぁ、http://__IP_Address__にアクセスして、いつもの画面を確認しよう!

「ページを開けません。このページのあるサーバが応答しません。」

な、な、なぜだ…!!
いつもの段取りでやってるのに、なんで出来ない…
いつもiptablesあるのに、なんでない…
ラズパイ用のCentOSだとないのかな…

第四章 解決へのアプローチ

実は、解決へのヒントが表示されていました。
そうです、「Redirecting to /bin/systemctl start httpd.service」です。
実は、CentOS 7になってから自分が大好きだったserviceコマンドがなくなっていました。
ついでに、iptablesもなくなってました。
新しいやり方では、「systemctl」というコマンドを使います!

## Apacheの起動および自動起動の設定
# systemctl start httpd.service
# systemctl enable httpd.service

## 80番ポートの開放
# firewall-cmd --add-service=http --zone=public
# firewall-cmd --add-service=http --zone=public --permanent

参考:Apache httpd 2.4 を CentOS 7 に yum でインストールする手順 | WEB ARCH LABO

で、http://__IP_Address__にアクセスしてみると、Apacheの画面を確認することができるようになりました。
f:id:usmysa:20160529181908p:plain

あとがき

今回、初めて当たり前だと思っていたことに挫折を覚えました。
ググる時も、CentOSのバージョンを意識しないで、
普通に「CentOS Apache」というクエリーで調べていたので
違うバージョンのやり方が出て、解決するのに時間がかかってしまいました。
バージョンが上がったら、変更される部分があるということを実感したので、
今後は注意したいと思います!笑

CentOSでキーボードのレイアウトを変更

Raspberry Pi 3にCentOS 7.2を入れており、
設定をする時にSSHからじゃなくてキーボードを使ったんですが、
どうやっても「:(コロン)」が打てないんですよねぇ…
昔、Virtual BoxにCentOSを入れた時も同じ問題が発生して解決したので
次、同じ問題が発生しても忘れないようにメモしときたいと思います。

環境

CentOS 7.2

解決策

# localectl list-keymaps | grep jp106
jp106

とコマンドを入力して、「jp106」があることを確認してください。
ちなみに、localectlコマンドはCentOSロケールを確認および変更するために使うコマンドのようです。

ロケールとは、ソフトウェアに内蔵される、言語や国・地域ごとに異なる単位、記号、日付、通貨などの表記規則の集合。または単に、利用する言語や国・地域の指定。多くのソフトウェアやプログラミング言語は、使用する言語とともにロケールを設定し、ロケールで定められた方式に基づいてデータの表記や処理を行う。

引用:ロケールとは|locale|ロカール - 意味/定義 : IT用語辞典

なるほど、また賢くなってしまいました…笑
(初めて見た時、「ローカルじゃないの?」って思っちゃいました…)

$ localectl set-keymap jp106

これで完了です。
無事にコロンが打てるようになりました!


参考:centos7でキーボードレイアウト変更 - Qiita

wgetとcurlの違い

サーバ関係の作業をしていると、よくwgetを使っているサイトを見るんですが、
稀にcurlを使っているサイト見かけます。
どちらも、ダウンロードをするのに使うコマンドなんですが、
その違いを調べてみました。

wget

読み方は「ダブルゲット」です!
自分は、ずっと「ダブリューゲット」って読んでました…笑
みなさん、ご存知の通り、ファイルをダウンロードする時に使うコマンドです。
wgetには、2つの特徴があります。

  • 再帰的にファイルをダウンロードすることができる
  • 左手だけで入力することができる

curlと違って、再帰的にファイルをダウンロードすることができるのが最大の特徴です。
wgetで対応しているプロトコルは、HTTP・HTTPSFTPのみです。
実は、アップロードもできたんですね…

今まで、wgetコマンドにオプションを使ったことがなかったんですが、便利なオプションがあるんですね!
ここで、wgetコマンドの便利なオプションを紹介したいと思います。

# index.htmlファイルをダウンロード
wget http://xxxxx/yyyyy/zzzzz/index.html

# オプション「-r」
# ディレクトリにあるファイルを全部ダウンロード
wget -r http://xxxxx/yyyyy/zzzzz/

# オプション「-I」 
# 再帰的にダウンロードする場合に、階層の数を指定する
wget -r -I 3 http://xxxxx/yyyyy/zzzzz/

# オプション「-A」 
# 指定した文字列のあるファイルをダウンロードする
wget -r -A png http://xxxxx/yyyyy/zzzzz/

# オプション「-R」 
# 指定した文字列のあるファイルはダウンロードしない
wget -r -A jpg http://xxxxx/yyyyy/zzzzz/

curl

読み方は「カール」です。
curlの最大の特徴は、

  • サポートが充実している

です。
例えば、wgetと異なり、curlで対応しているプロトコルには、
FTP、FTPS、Gopher、HTTP、HTTPS、SCP、SFTP、TFTP、TELNET、DICT、LDAP、LDAPS、FILE、POP3IMAP、SMB/CIFS、SMTPRTMP、RTSP
があります。
他にも、wgetでは対応していないものが、curlでは対応されているという場合があります。

# オプション「-o(小文字)」
# ダウンロードしたファイルを指定したファイルに出力する
curl -o index2.html http://xxxxx/yyyyy/zzzzz/index.html

# オプション「-O(大文字)」
# index.htmlファイルをダウンロード
curl -O http://xxxxx/yyyyy/zzzzz/index.html

# 連番ファイルをダウンロードする
curl -O ftp://ftp.example.com/data[001-100].txt

curlコマンドは、SFTPプロトコルに対応しているので、
curlコマンドを使って、SFTPでアップロードできないのかな…?
どうやるのか、分からないので
教えていただけると嬉しいです!

参考:Linuxコマンド集 - 【 wget 】 ファイルをダウンロードする:ITpro
   Linuxコマンド集 - 【curl】ファイルのダウンロードやアップロードを行う:ITpro

Raspberry Pi 3の起動時に自動無線LAN接続(2)

前回の続きです!
前回:Raspberry Pi 3の起動時に自動無線LAN接続(1) - usmysaの開発メモ

前回、コマンドから無線LANに繋ぐ方法を紹介しました。
今回は、シェルスクリプトを使って、それを自動化するスクリプトを作成したいと思います。

シェルスクリプトとは

シェルスクリプトとは、複数の処理をまとめて行う(バッチ処理)ときに使われる、OSのシェルが直接解釈・処理できるスクリプト

引用:シェルスクリプトとは|shell script - 意味/定義 : IT用語辞典


そもそもスクリプトとは…

コンピュータプログラムの種類の一つで、機械語への変換や実行可能ファイルの作成などの過程を省略または自動化し、ソースコードを記述したら即座に実行できるようなプログラムのことをスクリプトという。

引用:スクリプトとは|script|scr - 意味/定義 : IT用語辞典

なるほど。
スクリプトとは、コンパイルが必要ない言語のことを言うんですね。
スクリプト言語の例としては、PythonRubyなどがあります。
つまり、シェルスクリプトとは、シェルのスクリプト(=コンパイルが必要ないプログラム)ってことですね!

起動時に自動で接続するための手順


f:id:usmysa:20160520171816p:plain


サーバ起動時に実行するコマンドとして、「chkconfig」があります。
これに作成したスクリプトを登録して、ラズパイが起動したときに実行させます。

いざ、スクリプトを書いてみる

スクリプト名は、「wifi-connect-script」となっています。
コードは以下のとおりです。

# !/bin/sh
# chkconfig: 2345 99 20
# description: wifi-connect-script

LoopConnectWiFi(){
  ssid=$1
  password=$2
  nmcli d wifi connect ${ssid} password ${password}
  result_connect='nmcli d wifi connect $ssid password $password'
  success_str="Device 'wlan0' successfully activated with"
  if [ ! 'echo ${result_connect} | grep ${success_str}' ]; then
    sleep 3
    LoopConnectionWiFi $ssid $password
  fi
}

readonly ssid_array=($(nmcli d wifi))
readonly wifi="SSID"
readonly wifi_pass="SSIDのパスワード"

case "$1" in
  start)
    for ssid in "${ssid_array[@]}"; do
      if [ $ssid = $wifi ]; then
        LoopConnectWiFi $wifi $wifi_pass
      fi
    done
    ;;
  stop)
    ;;
  *)
    ;;
esac

解説

# !/bin/sh

まず、これを書くことで、「このテキストはシェルスクリプトである」ということを宣言します。
なので、シェルスクリプトを書く場合は絶対必要な部分となります。

# chkconfig: 2345 99 20
# description: wifi-connect-script

これは、chkconfigの設定を記述しています。

2345 起動させるランレベル ランレベルを数字で入力。複数ある場合は、連続して2345のように各。- と書くと全てのランレベルでOFFとする。
99 起動時の優先度 数値(1~99までで記入するのが一般的)で記入。数字が大きくなるほど後で起動される。
20 停止時の優先度 数値(1~99までで記入するのが一般的)で記入。数字が大きくなるほど後で停止される。

ランレベルとは、Linux OSの動作モードを表します。

0:システムの停止
1:シングルユーザーモード、ネットワーク無し
2:マルチユーザーモードNFSマウントなし)
3:マルチユーザーモード(コンソール)、ネットワーク有り
4:未使用
5:マルチユーザーモードX Windows)、ネットワーク有り
6:システム再起動

引用:ランレベルとは(chkconfig) - Linux入門 - Webkaru

「description」はサービスの説明です。
適当に書いといて大丈夫です。

readonly ssid_array=($(nmcli d wifi))
readonly wifi="SSID"
readonly wifi_pass="SSIDのパスワード"

「nmcli d wifi」はWiFiの一覧を表示するコマンドで、その結果を「ssid_array」という配列に代入しています。
また、ここら辺の変数は書き換えることはないと思うので、一応「readonly」にして読み込み専用にしています。

case "$1" in
  start)
    for ssid in "${ssid_array[@]}"; do
      if [ $ssid = $wifi ]; then
        LoopConnectWiFi $wifi $wifi_pass
      fi
    done
    ;;
  stop)
    ;;
  *)
    ;;
esac

この部分は、switch文になってます。
「$1」っていうのは、シェルスクリプトでは第1引数を表します。
ここは覚えとく必要があります。
で、for文を使ってWiFi一覧の中から接続したいWiFiがあったら、LoopConnectWiFiメソッドを呼び出すという仕組みになっています。
この時、switch文で「start」の場合しか使ってないので、if文で書いた方が正しいのかなと思います。

nmcli d wifi connect ${ssid} password ${password}

前回で紹介しましたが、これでWiFiに接続しています。

result_connect='nmcli d wifi connect $ssid password $password'
success_str="Device 'wlan0' successfully activated with"
if [ ! 'echo ${result_connect} | grep ${success_str}' ]; then
  sleep 3
  LoopConnectionWiFi $ssid $password
fi

「result_connect」には、WiFiに接続した後に表示される文章を代入しています。
そして、result_connectが失敗していた場合、3秒ごとに再接続するような仕組みになっています。

chkconfigに登録する

$ sudo mv wifi-connect-script /etc/init.d/
$ sudo chkconfig --add wifi-connect-script
$ sudo chkconfig wifi-connect-script on


これで、Raspberry Pi 3が起動した時に自動で無線LANに接続します!
個人的に、ソースコードにパスワードを書くのは非常に嫌いなんですが、良い方法を知っている方がいれば教えて下さい!

参考:bash: コマンドの実行結果を配列や変数に代入する | deadwood
   (CentOS6まで)自作のサービスをchkconfigで登録する
   シェルスクリプトで関数を利用する - Qiita
   文字列Aに文字列Bが含まれるか - わからん
   CentOSの起動スクリプトを書き方(+注意点) | 本日も乙

Raspberry Pi 3の起動時に自動無線LAN接続(1)

Raspberry Pi 3には、2とは違い
無線LANのモジュールがデフォルトで付いているらしいです。
で、Raspberry Pi 3に無線経由でSSHをするには、以下のような手順が必要です!

1. ラズパイに有線ケーブルをつないで、SSHで入ったあと、無線LANに接続する
2. ラズパイに有線ケーブル・キーボード・ディスプレイをつないで、無線LANに接続する

無線経由でSSHしたくても、どっちにしろ有線で一度繋がなきゃいけないんです…
それって面倒くさくないですか!?
ってことで、今回はラズパイが起動した時点で、自動的に無線LANに接続するようなスクリプトを作成したいと思います。

環境

Raspberry Pi 3
CentOS 7

そもそも、どうやって無線LANに繋げるのか

ラズパイを無線LANに接続するには、「nmcli」というコマンドを使います。
「nmcli d」というコマンドを打って、ネットワーク機器の一覧を表示します。

# nmcli d
DEVICE  TYPE      STATE         CONNECTION 
eth0    ethernet  connected     eth0       
lo      loopback  unmanaged     -- 

しかし、無線LANであるwlan0が認識できておらず、見当たらりません。
そこで、wlan0を認識するには、Firmwareというソフトウェアを準備しなくちゃいけないっぽいです。

# yum -y install git
# git clone https://github.com/RPi-Distro/firmware-nonfree.git
# mv /lib/firmware/brcm{,.org}
# cp -R firmware-nonfree/brcm80211/brcm /lib/firmware/brcm
# curl -L --output /usr/bin/rpi-update https://raw.githubusercontent.com/Hexxeh/rpi-update/master/rpi-update
# chmod +x /usr/bin/rpi-update
# rpi-update
# reboot

で、リブートした後、もう一度ネットワーク機器の一覧を確認してみると

DEVICE  TYPE      STATE         CONNECTION 
eth0    ethernet  connected     eth0       
wlan0   wifi      disconnected  --         
lo      loopback  unmanaged     -- 

と、wlan0が認識されるようになります。
で、無線LANに接続するには、以下のような手順で接続することができます。

# nmcli d wifi connect ___ssid___ password ___password____
# nmcli d
DEVICE  TYPE      STATE      CONNECTION 
eth0    ethernet  connected  eth0       
wlan0   wifi      connected  ___ssid___    
lo      loopback  unmanaged  --  

ちなみに、無線LANの一覧を確認したい場合は、以下のようなコマンドを打てば確認できます

# nmcli d wifi

参考:Raspberry Pi 3 へCentOS7導入からWifi無線LAN接続まで設定メモ - YOMON8.NET

以上で、やっと無線LANに接続なるようになりました。
次回では、自動的に起動するようなスクリプトを書きたいと思います。