CODE COMPLETEを読みました – アナロジー

コードコンプリート―完全なプログラミングを目指して (Microsoft PRESS) を読んでみました。

かなり昔の本(初版1994年)で辞書くらい分厚いのもあってしばらく本棚に飾ってあったんですが読んでみたら現在でも使える内容満載のとっても良い本でした。おすすめ。

初っ端第一部からガツンときたのはアナロジーの話です。アナロジーとは例えばこんなの

抽象的でイメージしずらい数学や物理化学の現象をイメージしやすい身近なもので置き換えて理解しやすくすることです。

この本では以下の例え話をしています。

ソフトウェア ≒ 建築

仕様 ≒ 施工図

パッケージ ≒ ユニットパネルや備え付けの家具

さしずめ、プログラマはパネルや家具を集めて組み立て、人が立ち寄れる電脳商店を作る電脳大工さんといったところ。

プログラムとかソフトウェアってなんだか掴みどころが難しくイメージしずらい感じがするのがこのアナロジーですんなり頭に入るようになります。

身近なものに置き換えるって大事です。

Cloud9でバブルソート

いろいろ勉強したいことが溜まってきてしまっている今日このごろ、一個ずついろいろ試していきたいと思います。

とりあえず、HerokuGoogle App EngineならHerokuの方が無課金ユーザに優しい気がするのは分かった。

そんなわけで前からやってみたかったCloud9を使用してのC言語のバブルソートを書いてみます。

とりあえずC言語のコンパイル方法とかさっぱり忘れてしまっているのでドットインストールのC言語を見たり私の旧ブログを見たりして思い出します。

ほんでソースコード探検隊のバブルソートをやってみます。

C言語でバブルソート

bubble_sort.c

#include <stdio.h>

#define NUM_ITEMS 7

void bubbleSort(int numbers[], int array_size);
void printArray(int numbers[], int array_size);

int main()
{
  int numbers[NUM_ITEMS] = {6,5,3,1,7,2,4};

  printf("Start:\n");
  printArray(numbers, NUM_ITEMS);
  printf("\n");

  //perform bubble sort on array
  bubbleSort(numbers, NUM_ITEMS);

  printf("Done:\n");
  printArray(numbers, NUM_ITEMS);
  printf("\n");

  return 0;
}


void bubbleSort(int numbers[], int array_size)
{
  int i, j, temp;

  for (i = 0; i < (array_size - 1) ; i++) {
    for (j = (array_size - 1); j > i; j--) {
      printf("compare: %d and %d\n", numbers[j], numbers[j-1]);
      if (numbers[j-1] > numbers[j]) {
        temp = numbers[j-1];
        numbers[j-1] = numbers[j];
        numbers[j] = temp;

        printf("\tswap: ");
        printArray(numbers, array_size);
        printf("\n");
      }
    }
    printArray(numbers, array_size);
    printf("\n");
  }
}

void printArray(int numbers[], int array_size)
{
    int x;
    for (x = 0; x < array_size; x++) {
        printf("%d ", numbers[x]);
    }
}

コンパイルと実行

masasikatano:~/workspace $ gcc -o bubble_sort bubble_sort.c
masasikatano:~/workspace $ ./bubble_sort 
Start:
6 5 3 1 7 2 4 
compare: 4 and 2
compare: 2 and 7
        swap: 6 5 3 1 2 7 4 
compare: 2 and 1
compare: 1 and 3
        swap: 6 5 1 3 2 7 4 
compare: 1 and 5
        swap: 6 1 5 3 2 7 4 
compare: 1 and 6
        swap: 1 6 5 3 2 7 4 
1 6 5 3 2 7 4 
compare: 4 and 7
        swap: 1 6 5 3 2 4 7 
compare: 4 and 2
compare: 2 and 3
        swap: 1 6 5 2 3 4 7 
compare: 2 and 5
        swap: 1 6 2 5 3 4 7 
compare: 2 and 6
        swap: 1 2 6 5 3 4 7 
1 2 6 5 3 4 7 
compare: 7 and 4
compare: 4 and 3
compare: 3 and 5
        swap: 1 2 6 3 5 4 7 
compare: 3 and 6
        swap: 1 2 3 6 5 4 7 
1 2 3 6 5 4 7 
compare: 7 and 4
compare: 4 and 5
        swap: 1 2 3 6 4 5 7 
compare: 4 and 6
        swap: 1 2 3 4 6 5 7 
1 2 3 4 6 5 7 
compare: 7 and 5
compare: 5 and 6
        swap: 1 2 3 4 5 6 7 
1 2 3 4 5 6 7 
compare: 7 and 6
1 2 3 4 5 6 7 
Done:
1 2 3 4 5 6 7 
masasikatano:~/workspace $ 

ここであることに気づきます。

思ったよりC言語がしんどい。

というわけで、なんとなくPythonでも書いてみます。

Pythonでバブルソート

をやる前にCloud9でPythonを選択してワークスペースを作成すると、Python2がデフォルトになるためPython3に変更します。

masasikatano:~/workspace $ sudo mv /usr/bin/python /usr/bin/python2
masasikatano:~/workspace $ sudo ln -s /usr/bin/python3 /usr/bin/python
masasikatano:~/workspace $ python
Python 3.4.3 (default, Nov 17 2016, 01:08:31)
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

OKです。↓のようなファイルを作成します。参考にしたのは、Problem Solving with Algorithms and Data Structures の バブルソート回です。

bubblesort.py

def bubbleSort(alist):                       # defで関数を定義
    for passnum in range(len(alist)-1,0,-1): # range()で8から-1ずつ進み0で終了を指定
        for i in range(passnum):
            if alist[i]>alist[i+1]:          # データ配列の前後を比較して前の数が大きい
                temp = alist[i]              # 一時変数に前のデータを格納
                alist[i] = alist[i+1]        # データ配列の前後を入れ替え
                alist[i+1] = temp

alist = [54,26,93,17,77,31,44,55,20] # ソートするデータの入った配列を定義
bubbleSort(alist)                    # 関数を実行
print(alist)                         # 表示

実行してみます。

masasikatano:~/workspace $ python bubblesort.py 
[17, 20, 26, 31, 44, 54, 55, 77, 93]
masasikatano:~/workspace $ 

うまくいきました。

やっぱPythonの方が楽だ・・

シェルに関しての基礎的な用語のまとめ

最近Linux関連の書籍をもりもり読んでいます。特に勉強になっているのは

HOW LINUX WORKS―Linuxの仕組み スーパーユーザが知っておくべきこと (MYCOM UNIX Books)ブライアン ウォード (著), Brian Ward (原著)

入門者のLinux 素朴な疑問を解消しながら学ぶ (ブルーバックス)奈佐原 顕郎 (著)

Linux 怒濤のQ&Aぱぱんだ (著)

という書籍達です。

そこで「シェル」というものに対してなんだか認識がふんわりしていることに気づいてしまったので折角なのでここにまとめておきます。

シェル / Shell

シェルとは、コンピュータのOS(オペレーティングシステム)を構成するソフトウェアの一つで、利用者からの操作の受け付けや、利用者への情報の提示などを担当するもの。

IT用語辞典 e-Words

 

このシェル(殻)という名前は、カーネル(OS)とアプリケーションの中間に位置し、カーネルを包み込むことに由来する。シェルは、ユーザーからのコマンドを対話的に処理するのみならず、シェルスクリプトと呼ばれるファイルを作成することにより、一連の処理をバッチ(一括して連続的に)実行することもできる。

@IT

bash

bashとは、多くのUNIX系OSで標準的に使われるシェル(ユーザからの操作を受け付け、結果を表示するソフトウェア)の一つ。

IT用語辞典 e-Words

シェルスクリプト

拡張子が.shでよく分からんおまじないからはじまるプログラムファイルのこと。

シェルスクリプトとはシェルが解釈できるコマンドを羅列したファイルのことである。
たとえばhelloworld.shというファイルを作成し以下のような内容を記述する。

#!/bin/bash
echo "Hello World !"
exit 0

snowlongの日記

 

実はなんだかよく分からない内に、「シェル」と「シェルスクリプト」を混同してしまっていたことに気づきました。こういう認識違いって怖いなあ。

 

tty

 

linusakesson.net

 

UNIXの仮想的なキャラクター端末のデバイス名

weblio辞書

ttyってドライバのことなのね。

PHPのベストプラクティス

PHPの(速さに関しての)良いコードに関しての情報を探しているのですが、色々と収穫があったのでここにまとめておきます。

PHPのプログラマ向けの雑誌や書籍を買ったり、Twitterで情報集めたり色々やってみたのですが、US英語 Googleで「PHP7 performance」とか「PHP7 best speed」とかで検索した方が一番良い情報が手に入るのでおすすめです。

ちなみに2017年6月現在、○○語Googleはほぼ、●●なSEO業者からの派遣社員で構成されていると確信できるようなメタメタな検索結果のため、滅多に使わなくなりました。

あ、でも最近では、『ブンドドってなんだ?』と思った時には使ったので●●業者から見向きもされないニッチなキーワードで検索すればそれなりに使えると思います。では本題。

PHP Best Practices

A short, practical guide for common and confusing PHP tasks

PHPコミッターのAlex Cabal氏のタイトル通りPHPのベストなプラクティス集が集められたサイト。私が特に目からウロコが落ちたのは、

・APCuを使おうぜ!-> php7でのインストール方法 -> Laravelでの使い方

・DateTimeクラス使おうぜ!

・NullやBooleanは===で評価しようぜ!

らへんです。

PHP 7 performance improvements

こちらもPHPのコントリビュータのJulien Pauli氏のPHPのパフォーマンスに関しての記事。

・配列のキーには数字を使うと早くなるよ!

なんて初めて知りましたぜ。

10 Things Not To Do In PHP 7

・PHPの終了タグは使用しないで!

・ループ内でDB参照しないで!

分かってるけど気を抜くとやってしまいかねないことです。

 

他にも見つけたら追記の予定。

macOS Sierra ことはじめ

久々にジャンクのWindowsパソコンを購入して、その時、現役で使用していたPCからパーツを取り出して色々試行錯誤していたら、両方動かなくなりました

さて、こうなってしまった以上は仕方がないので、購入してからしばらくタンスの肥やしになっていた Mac mini (Mid 2011 メモリ16Gに換装済み) を引っ張り出してきてマカーになることにします。スタバには行きません

ちなみに、前述の2台の事は無かった事にしてNPOに寄付しました

 Sierra アップデートとクリーンインストール

Mac miniにはしまいこんだ当時のmac OSが入っているため、最新版にアップデートします。

マカーはオシャレなのでYoutubeにいろいろなそれっぽい動画が上がっていてとても助かるので参考にします。

Sierraをインストールできたらクリーンインストールしておきます。

私の場合は「残り6分」が30分くらいありましたが終わるのを祈りながら我慢して進めるとそのうち終わる気がします。

日本語JISキーボードの初期設定

私が使用しているのが日本語JIS配列のキーボードなのですが、なんとOS Sierraが対応していないため、Karabiner-Elementsを導入します。

最新版のDLはこちらからもできるみたいです

どんどん進めていってインストールできたらキー設定をします。

無変換キーと変換キーの割当て

JISキーボードとして認識

 

この二画面を設定しました。

Google日本語入力のインストールと設定

順番前後しましたが私は日本語入力にGoogle日本語入力を使用しているためインストールしておきました。これで違和感なくキーボードが打てるはずです。

高速化への設定等は次回まとめておくかも。

Cloud9へのPHP7とLaravelの導入

Cloud9のワークスペース作成画面でLaravelの入ったGitプロジェクトを入力してワークスペースの作成が終わったところから開始するとして、以下C9上で入力していきます。

PHP7と必要パッケージの導入

PHP5とphpmyadminを削除(使う人は残してください)。

masasikatano:~/workspace (master) $ sudo apt-get purge -y php5-common
masasikatano:~/workspace (master) $ sudo apt-get purge phpmyadmin
masasikatano:~/workspace (master) $ sudo apt-get autoremove

PHP7とLaravelに必要なパッケージをインストールしてcomposer installします

masasikatano:~/workspace (master) $ sudo add-apt-repository ppa:ondrej/php
masasikatano:~/workspace (master) $ sudo add-apt-update
masasikatano:~/workspace (master) $ sudo add-apt-upgrade
masasikatano:~/workspace (master) $ sudo apt-get install php7.0 libapache2-mod-php7.0 php7.0-mbstring  php7.0-zip php7.0-xml php7.0-mysql php7.0-fpm php7.0-curl
masasikatano:~/workspace (master) $ composer install
masasikatano:~/workspace (master) $ composer update

Apache関連の設定変更

まずはDocument Rootをpubclic以下へ変更

masasikatano:~/workspace (master) $ sudo vi /etc/apache2/sites-available/001-cloud9.conf
<VirtualHost *:8080>
    DocumentRoot /home/ubuntu/workspace/public
    ServerName https://${C9_HOSTNAME}:443

    LogLevel info

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    <Directory /home/ubuntu/workspace>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

ディレクトリのパーミッションを変更

masasikatano:~/workspace (master) $chmod 777 -R bootstrap/cache
masasikatano:~/workspace (master) $chmod 777 -R storage

MySQLのrootユーザのパスワード変更

masasikatano:~/workspace (master) $ mysql -u root
mysql> update mysql.user set password=password('password1234') where user = 'root';
mysql> flush privileges;

 

とりあえずこれで動くと思います。

TCPサーバを立ててみる

UNIXネットワークプログラミング入門という本を読んで、恥ずかしながらC言語でかんたんにTCPのサーバが立てられるということを知りました。さっそくCloud9で実装してみたいと思います。

テキストはWEBでも見ることができます雪田教授に感謝です。

Cloud9でC++のWorkspaceを作成して、以下のファイル群を作っていきます。

/home/ubuntu/workspace/one2one.h
/*********************************************/
/* File name: one2one.h */
/* Project name: socket/1-1 */
/* Month/Year: Jan/2003 */
/* Author: Shuichi YUKITA */
/*********************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#define PORT 50000
#define HOSTNAME_LENGTH 20
#define MSG_BUF_LEN 512

extern char * chop_newline(char *, int);

 

/home/ubuntu/workspace/server.c
/*********************************************/
/*       File name:  server.c                */
/*    Project name:  socket/1-1              */
/*      Month/Year:  Jan/2003                */
/*          Author:  Shuichi YUKITA          */
/*********************************************/

#include "one2one.h"

main()
{
  struct  sockaddr_in   me;
  int  s,snew;
  char  send_buf[MSG_BUF_LEN];
  char  recv_buf[MSG_BUF_LEN];
  int count;

  memset((char *)&me, 0, sizeof(me));
  me.sin_family = AF_INET;
  me.sin_addr.s_addr = htonl(INADDR_ANY);
  me.sin_port = htons(PORT);

  if ((s = socket(AF_INET,SOCK_STREAM,0)) < 0 )	{
    perror("socket");
    exit(1);
  }

  if (bind(s,(struct sockaddr *)&me,sizeof(me)) == -1){
    perror("bind");
    exit(1);
  }

  listen(s,1);
  fprintf(stderr,"successfully bound, now waiting.\n");
  snew = accept(s,NULL,NULL);
  close(s);

  do	{
    printf("input: ");
    fgets(send_buf,MSG_BUF_LEN,stdin);
    /*    chop_newline(send_buf,MSG_BUF_LEN);*/
    write(snew,send_buf,strlen(send_buf));
    count = read(snew,recv_buf,MSG_BUF_LEN);
    recv_buf[count] = '\0';
    printf("client: %s",recv_buf);
  }
  while (strncmp(recv_buf,"quit",4) != 0);

  close(snew);
}

 

/home/ubuntu/workspace/client.c
/*********************************************/
/*       File name:  client.c                */
/*    Project name:  socket/1-1              */
/*      Month/Year:  Jan/2003                */
/*          Author:  Shuichi YUKITA          */
/*********************************************/

#include "one2one.h"

main()
{
  struct  hostent  *server_ent;
  struct  sockaddr_in  server;
  int s;  /* descriptor for socket */
  char  send_buf[MSG_BUF_LEN];
  char  recv_buf[MSG_BUF_LEN];
  char  hostname[HOSTNAME_LENGTH];
  int   count;

  printf("input  server's  hostname: ");
  fgets(hostname, HOSTNAME_LENGTH, stdin);
  chop_newline(hostname, HOSTNAME_LENGTH);

  if((server_ent = gethostbyname(hostname)) == NULL){
    perror("gethostbyname");
    exit(1);
  }

  memset((char *)&server,0,sizeof(server));
  server.sin_family = AF_INET;
  server.sin_port = htons(PORT);
  memcpy((char *)&server.sin_addr, server_ent->h_addr, 
   server_ent->h_length);

  if ((s = socket(AF_INET,SOCK_STREAM,0)) < 0){
    perror("socket");
    exit(1);
  }

  if (connect(s,(struct sockaddr *)&server,sizeof(server)) == -1){
    perror("connect");
    exit(1);
  }
  fprintf(stderr,"connected.\n");

  do   {
    count = read(s,recv_buf,MSG_BUF_LEN);
    recv_buf[count] = '\0';
    printf("server: %s",recv_buf);
    printf("input: ");
    fgets(send_buf,MSG_BUF_LEN,stdin);
    /*    chop_newline(send_buf,MSG_BUF_LEN);*/
    write(s,send_buf,strlen(send_buf));
  }
  while( strncmp(send_buf,"quit",4) != 0 );

  close(s);
}

 

/home/ubuntu/workspace/chop_newline.c
/*********************************************/
/*       File name:  chop_newline.c          */
/*    Project name:  socket/1-1              */
/*      Month/Year:  Jan/2003                */
/*          Author:  Shuichi YUKITA          */
/*********************************************/

#include "one2one.h"

char * chop_newline(char *str, int len){
  int n = strlen(str);

  if(n < len && str[n-1] == '\n'){
    str[n-1] = '\0';
  }
  return str;
}

 

/home/ubuntu/workspace/Makefile
#*********************************************/
#*       File name:  Makefile                */
#*    Project name:  socket/1-1              */
#*      Month/Year:  Jan/2003                */
#*          Author:  Shuichi YUKITA          */
#*********************************************/
#
#  "root.o" target is implicitly built by
#  $(COMPILE.c) -o root.o root.c

RM=rm -f

all:	s c

s:	server.o chop_newline.o
  $(LINK.c)  -o s  server.o chop_newline.o

c:	client.o chop_newline.o
  $(LINK.c)  -o c  client.o chop_newline.o

server.o:	server.c one2one.h

client.o:	client.c one2one.h

clean:
  $(RM) s c *.o *~

 
ここまでヘッダファイル1つ、サーバ用ファイル1つ、クライアント用ファイル1つ、計5つのファイルを作成したらmakeをします。

masasikatano:~/workspace $ make
cc    -c -o chop_newline.o chop_newline.c
cc      -o s  server.o chop_newline.o
cc    -c -o client.o client.c
cc      -o c  client.o chop_newline.o

コンパイルが完了したら、サーバとクライアントを起動することができます。まずはサーバを起動します。

masasikatano:~/workspace $ ./s
successfully bound, now waiting.

同じCloud9上で別のターミナルを立ち上げてクライアントを立ち上げてみます。

masasikatano:~/workspace $ ./c
input  server's  hostname: localhost
connected.

こうするとサーバ側でinputの表示がされ、文字入力を受付ける状態になり、文字を入力するとクライアント側で表示されます。すげえ。

Raspberry Pi のサーバ最適化とセキュリティ設定まとめ

いままでRaspberryPiにいろいろなセキュリティを行ってきたのですが新ブログに移転したのもあるので内容をまとめておきます。セキュリティには4つの重要な要素があります。

制限する

一番安全で強力なセキュリティの方法はネットワークに接続しないことです。(後に紹介する)冗長化や監視に必要なアプリケーションは残しておきますが、可能な限りのアプリケーションは停止します。

参考: Raspberry Pi 起動高速化手順メモ

ラズパイへの施行例

root@rpi1 /var/www #chkconfig --list
alsa-utils                0:off  1:off  2:off  3:off  4:off  5:off  6:off
apache2                   0:off  1:off  2:on   3:on   4:on   5:on   6:off
atd                       0:off  1:off  2:on   3:on   4:on   5:on   6:off
avahi-daemon              0:off  1:off  2:off  3:off  4:off  5:off  6:off
bluetooth                 0:off  1:off  2:off  3:off  4:off  5:off  6:off
bootlogs                  0:off  1:on   2:on   3:on   4:on   5:on   6:off
bootmisc.sh               0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
checkfs.sh                0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
checkroot-bootclean.sh    0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
checkroot.sh              0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
console-setup             0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
cron                      0:off  1:off  2:on   3:on   4:on   5:on   6:off
dbus                      0:off  1:off  2:off  3:off  4:off  5:off  6:off
dhcpcd                    0:off  1:off  2:on   3:on   4:on   5:on   6:off
dphys-swapfile            0:off  1:off  2:off  3:off  4:off  5:off  6:off
dropbear                  0:off  1:off  2:on   3:on   4:on   5:on   6:off
fake-hwclock              0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
hostname.sh               0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
hwclock.sh                0:off  1:off  2:off  3:off  4:off  5:off  6:off
kbd                       0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
keyboard-setup            0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
killprocs                 0:off  1:on   2:off  3:off  4:off  5:off  6:off
kmod                      0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
motd                      0:off  1:off  2:off  3:off  4:off  5:off  6:off
mountall-bootclean.sh     0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
mountall.sh               0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
mountdevsubfs.sh          0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
mountkernfs.sh            0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
mountnfs-bootclean.sh     0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
mountnfs.sh               0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
mysql                     0:off  1:off  2:off  3:off  4:off  5:off  6:off
networking                0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
nfs-common                0:off  1:off  2:off  3:off  4:off  5:off  6:off
ntp                       0:off  1:off  2:on   3:on   4:on   5:on   6:off
php7.0-fpm                0:off  1:off  2:on   3:on   4:on   5:on   6:off
plymouth                  0:off  1:off  2:off  3:off  4:off  5:off  6:off
plymouth-log              0:off  1:off  2:off  3:off  4:off  5:off  6:off
procps                    0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
raspi-config              0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
rc.local                  0:off  1:off  2:on   3:on   4:on   5:on   6:off
rcS                       0:off  1:off  2:off  3:off  4:off  5:off  6:off
rmnologin                 0:off  1:off  2:on   3:on   4:on   5:on   6:off
rpcbind                   0:off  1:off  2:off  3:off  4:off  5:off  6:off
rsync                     0:off  1:off  2:on   3:on   4:on   5:on   6:off
rsyslog                   0:off  1:off  2:on   3:on   4:on   5:on   6:off
sendsigs                  0:off  1:off  2:off  3:off  4:off  5:off  6:off
sudo                      0:off  1:off  2:off  3:off  4:off  5:off  6:off
triggerhappy              0:off  1:off  2:off  3:off  4:off  5:off  6:off
udev                      0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
udev-finish               0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
umountfs                  0:off  1:off  2:off  3:off  4:off  5:off  6:off
umountnfs.sh              0:off  1:off  2:off  3:off  4:off  5:off  6:off
umountroot                0:off  1:off  2:off  3:off  4:off  5:off  6:off
urandom                   0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on

また、PHPの便利すぎてクラッキングにも使えるfunctionを制限しておきます。

参考: Dangerous PHP Functions Must be Disabled

ラズパイへの施行例 (php.iniファイルを編集して、Apache再起動すると反映されます。)

root@rpi1 /etc/php/7.0/apache2 #less php.ini
; 中略
; This directive allows you to disable certain functions for security reasons.
; It receives a comma-delimited list of function names.
; http://php.net/disable-functions
disable_functions = phpinfo,system,popen,show_source,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,

冗長化する

セキュリティには可用性も重要です。二番目は可用性を確保するために可能な限りスペアのアプリケーションを用意しておき、どこかに異常が現れた際にすぐに代用が可能な状態にすることです。

参考 : Raspberry Pi チューニング – DBサーバの独立と移行

監視する

問題を事前に発見するために監視を怠らないようにするのもセキュリティにはとても重要です。
サーバのメトリクス(評価尺度)を可視化するのは、Mackerelがかんたんに導入できておすすめです。ロードアベレージが一定数を超えたらメールが飛んでくるように設定することもできます。

参考 : Raspberry Pi を Mackerel で監視する

空にする

最後に意図して情報資産を保持しないようにするのも効果的な方法です。お金を自宅に置かずに銀行に預けるように、お金に関わる情報や個人情報等の情報資産は外部サイトにあずけてしまうのも手です。