作業中のメモ

よく「計算機」を使って作業をする.知らなかったことを中心にまとめるつもり.

Raspberry Pi 3 Model B でファイルサーバーとプリンタサーバーを構築する(その 3) Samba のインストールと設定

どうも,筆者です.

前回の続きである. workspacememory.hatenablog.com

今回は,Samba のインストールとその設定を行う.

Samba のインストール

Samba のインストールは,コマンド 1 行で行える.

sudo apt-get install -y samba

外付け HDD のフォーマットとマウント

外付け HDD が正しく接続されているかを確認する.その後,パーティションの設定を行い,フォーマットする.パーティションの設定等は,Raspberry Piでファイルサーバ、Part2 外付けハードディスクの導入編 を参考にした.

# 接続確認
sudo fdisk -l
# パーティションの設定
sudo fdisk /dev/sda
# フォーマット
sudo mkfs.ext4 /dev/sda1

自動マウントのために UUID の取得とマウント先を作成し,設定を記述する.

# マウント先の生成
sudo mkdir /media/hdd1
# UUID の取得
sudo blkid /dev/sda1
# 設定を記述
sudo vim /etc/fstab

### === /etc/fstab の中身 === ###
proc            /proc           proc    defaults          0       0
/dev/mmcblk0p1  /boot           vfat    defaults          0       2
/dev/mmcblk0p2  /               ext4    defaults,noatime  0       1
UUID=abcdefgh-1234-5678-xyzw-123abc456xyz  /media/hdd1         ext4    defaults  0       0  # ここに追加
# a swapfile is not a swap partition, no line here
#   use  dphys-swapfile swap[on|off]  for that

# 再起動しておく
reboot

Samba の設定

その後,共有するディレクトリを作成する.そして,Samba の設定を行う.

pushd /media/hdd1/
# ディレクトリの生成
sudo mkdir share
sudo chown -R nobody:nogroup share
sudo chmod 777 share
popd

# Samba の設定
sudo vim /etc/samba/smb.conf
#
# Sample configuration file for the Samba suite for Debian GNU/Linux.
#
#
# This is the main Samba configuration file. You should read the
# smb.conf(5) manual page in order to understand the options listed
# here. Samba has a huge number of configurable options most of which
# are not shown in this example
#
# Some options that are often worth tuning have been included as
# commented-out examples in this file.
#  - When such options are commented with ";", the proposed setting
#    differs from the default Samba behaviour
#  - When commented with "#", the proposed setting is the default
#    behaviour of Samba but the option is considered important
#    enough to be mentioned here
#
# NOTE: Whenever you modify this file you should run the command
# "testparm" to check that you have not made any basic syntactic
# errors.

#======================= Global Settings =======================

[global]

## Browsing/Identification ###
   dos charset = CP932
   unix charset = UTF8

# Change this to the workgroup/NT-domain name your Samba server will part of
   workgroup = WORKGROUP

# Windows Internet Name Serving Support Section:
# WINS Support - Tells the NMBD component of Samba to enable its WINS Server
#   wins support = no

# WINS Server - Tells the NMBD components of Samba to be a WINS Client
# Note: Samba can be either a WINS Server, or a WINS Client, but NOT both
;   wins server = w.x.y.z

# This will prevent nmbd to search for NetBIOS names through DNS.
   dns proxy = no

#### Networking ####
   hosts deny = all
   hosts allow = 192.168.33.

# The specific set of interfaces / networks to bind to
# This can be either the interface name or an IP address/netmask;
# interface names are normally preferred
;   interfaces = 127.0.0.0/8 eth0

# Only bind to the named interfaces and/or networks; you must use the
# 'interfaces' option above to use this.
# It is recommended that you enable this feature if your Samba machine is
# not protected by a firewall or is a firewall itself.  However, this
# option cannot handle dynamic or non-broadcast interfaces correctly.
;   bind interfaces only = yes
   printing = cups
   printcap name = cups


#### Debugging/Accounting ####

# This tells Samba to use a separate log file for each machine
# that connects
   log file = /var/log/samba/log.%m

# Cap the size of the individual log files (in KiB).
   max log size = 1000                                                                                                                                                
# If you want Samba to only log through syslog then set the following
# parameter to 'yes'.
#   syslog only = no

# We want Samba to log a minimum amount of information to syslog. Everything
# should go to /var/log/samba/log.{smbd,nmbd} instead. If you want to log
# through syslog you should set the following parameter to something higher.
   syslog = 0

# Do something sensible when Samba crashes: mail the admin a backtrace
   panic action = /usr/share/samba/panic-action %d

####### Authentication #######

# Server role. Defines in which mode Samba will operate. Possible
# values are "standalone server", "member server", "classic primary
# domain controller", "classic backup domain controller", "active
# directory domain controller".
#
# Most people will want "standalone sever" or "member server".
# Running as "active directory domain controller" will require first
# running "samba-tool domain provision" to wipe databases and create a
# new domain.
   server role = standalone server

# If you are using encrypted passwords, Samba will need to know what
# password database type you are using.
   passdb backend = tdbsam

   obey pam restrictions = yes

# This boolean parameter controls whether Samba attempts to sync the Unix
# password with the SMB password when the encrypted SMB password in the
# passdb is changed.
   unix password sync = yes

# For Unix password sync to work on a Debian GNU/Linux system, the following
# parameters must be set (thanks to Ian Kahan <<kahan@informatik.tu-muenchen.de> for
# sending the correct chat script for the passwd program in Debian Sarge).
   passwd program = /usr/bin/passwd %u
   passwd chat = *Enter\snew\s*\spassword:* %n\n *Retype\snew\s*\spassword:* %n\n *password\supdated\ssuccessfully* .

# This boolean controls whether PAM will be used for password changes
# when requested by an SMB client instead of the program listed in
# 'passwd program'. The default is 'no'.
   pam password change = yes

# This option controls how unsuccessful authentication attempts are mapped
# to anonymous connections
   map to guest = bad user
   usershare allow guests = yes



[share]
   comment = share directory
   browseable = yes
   path = /media/hdd1/share
   read only = no
   available = yes
   guest ok = yes
   create mask = 0666
   directory mask = 0666

[printers]
   comment = All Printers
   browseable = no
   path = /var/spool/samba
   printable = yes
   guest ok = yes         ### この設定を間違えたせいで PDF が印刷できなかった
   read only = yes
   create mask = 0700

# Windows clients look for this share name as a source of downloadable
# printer drivers
[print$]
   comment = Printer Drivers
   path = /var/lib/samba/printers
   browseable = yes
   read only = yes
   guest ok = no
# Uncomment to allow remote administration of Windows print drivers.
# You may need to replace 'lpadmin' with the name of the group your
# admin users are members of.
# Please note that you also need to set appropriate Unix permissions
# to the drivers directory for these users to have write rights in it
   write list = root, @lpadmin
   admin users = @lpadmin

後は,サービスを再起動するか,システムを再起動すれば設定が反映される.

接続方法

Windows の場合は,「ネットワーク」にアクセスすることで,しばらくすると表示されるはずである.もし,表示されなければ,「コンピュータ」から「ネットワークドライブの割り当て」を選択し,「フォルダー」に「\\[Raspberry Pi の IP アドレス]\share」と入力する.ここでは,「\\192.168.33.12\share」とすれば良い.この時,「share」は,Samba の「comment = share directory」の 1 行上にある「share」を指す.名前を変えた場合は,注意すること.

Linux の場合は,場所バーに「smb://[Raspberry Pi の IP アドレス]/share」と入力すれば接続されるはずである.

次回

次回は,上にも記述してある「この設定を間違えたせいで PDF が印刷できなかった」という部分について説明しようと思う.

Raspberry Pi 3 Model B でファイルサーバーとプリンタサーバーを構築する(その 2) CUPS とプリンタドライバのインストール

どうも,筆者です.

前回の続きである. workspacememory.hatenablog.com

使用しているプリンタは,「EPSON PX-501A」である.これは,USB 接続であるので,Raspberry Pi に接続し設定をする事で,スマホやノート PC などから印刷を出来るようにするのが目的である.history を参考にしつつ,思い出しながら書いていくので,この通りにやって上手くいくかが怪しい.

CUPS のインストール

まず,CUPS をインストールする.CUPS だけでは足りないらしいので,必要そうなものも一緒にインストールする.

sudo apt-get install -y cups cups-devel cups-pdf python-cups avahi-discover

後から,CUPS の設定の際に,ユーザーが必要になるらしいので,以下のようにして,対応するグループに追加しておく.そして,サービスを開始する.

# ユーザーの追加
sudo usermod -aG lpadmin pi
# サービスの開始
sudo /etc/init.d/cups start
sudo /etc/init.d/avahi-daemon start

次に,CUPS の設定ファイル「/etc/cups/cupsd.conf」を以下のように変更する.

#
#
# Sample configuration file for the CUPS scheduler.  See "man cupsd.conf" for a
# complete description of this file.
#

# Log general information in error_log - change "warn" to "debug"
# for troubleshooting...
###LogLevel warn
LogLevel debug

# Deactivate CUPS' internal logrotating, as we provide a better one, especially
# LogLevel debug2 gets usable now
MaxLogSize 0

# Only listen for connections from the local machine.
#Listen localhost:631 ### コメントアウト
Port 631              ### 追加する
Listen /var/run/cups/cups.sock

# Show shared printers on the local network.
Browsing On
BrowseLocalProtocols dnssd

# Default authentication type, when authentication is required...
DefaultAuthType Basic

# Web interface setting...
WebInterface Yes 

# Restrict access to the server...
<Location />
  Order allow,deny
  Allow @local        ### 追加する
</Location>
 Restrict access to the admin pages...                                                                                                                                
<Location /admin>
  Order allow,deny
  Allow @local        ### 追加する
</Location>

# Restrict access to configuration files...
<Location /admin/conf>
  AuthType Default
  Require user @SYSTEM
  Order allow,deny
  Allow @local        ### 追加する
</Location>

書き換えが終わったら,サービスを再起動する.

sudo /etc/init.d/cups restart

ここまでは,Raspberry Pi をプリントサーバ化 を参考にした.

これで,CUPS の設定は半分終わった.次に,プリンタを CUPS に追加すればよいのだが,CUPS に「EPSON PX-501A」のドライバが無かったので,この段階でインストールしておく.このドライバのインストールでかなり苦労した.

プリンタドライバのインストール

まず,Raspberry Pi 用のドライバが見つからない.自分で書くわけにはいかないので,EPSON Download Center から頑張ってソースコードを探す.PX-501A の場合は,モジュール名が,「ESC/P-R Driver (generic driver)」であるものをダウンロードする.設定を行っている段階では,「epson-inkjet-printer-escpr-1.6.11-1lsb3.2.tar.gz」であった.今は,1.6.12 が出ているらしい.

次に,make で止まるので,あらかじめ以下をインストールしておく.これは,EpsonのプリンタドライバをRasPi用にビルドしたよー を参考にした.

# configure 用
sudo apt-get install libtool autoconf
# cups/cups.h が見つからないときの対策
sudo apt-get install libcups2-dev
# cups/raster.h が見つからないときの対策
sudo apt-get install libcupsimage2-dev

後は,解凍して,インストールの準備を行う.この時,PPD ファイルを該当するディレクトリにコピーしておく.

tar zxvf epson-inkjet-printer-escpr-1.6.11-1lsb3.2.tar.gz
pushd epson-inkjet-printer-escpr-1.6.11/

# PPD ファイルのコピー
sudo cp -f ppd/Epson-PX-501A-epson-escpr-en.ppd /usr/share/ppd/cupsfilters/

# configure を行う
./configure --prefix=/usr

# make を行う(しばらく時間がかかる)
make

# install を行う
sudo make install
popd

これで,ドライバがインストールされたことになる.後は,Web ブラウザから,プリンタの設定を行えばよい.

CUPS からプリンタを追加

ウェブブラウザ(WindowsLinux など Raspberry Pi 以外でもよい)で「http://[Raspberry Pi の IP アドレス]:631」にアクセスする.ここでは,Raspberry Pi の IP アドレスを「192.168.33.12」にしたので,

http://192.168.33.12:631

とすれば良い.プリンタの電源を入れて,「管理」メニューから「プリンタの追加」からプリンタを追加する.USB で接続されたプリンタ(EPSON PX-501A)が表示されるはずなので,選択し,続ける.

次のページでは,「このプリンターを共有する」にチェックを入れて続ける.

次のページで,ドライバを追加したので,「または PPD ファイルを提供」から,「/usr/share/ppd/cupsfilters/」にある PPD ファイルを選択する.

最後に自動設定を選択し,設定が完了する.試しに,テストページを印刷しておこう.

次回

次回は,Samba の設定を行い,Windows 側で共有が行えるようにする.また,SD にアクセスし続けると寿命が縮むので,外付け HDD にアクセスするよう設定する. このとき,一箇所だけ設定を間違え,Windows で PDF が印刷できない問題が生じたので,そのことについても別の記事で説明する予定である.

Raspberry Pi 3 Model B でファイルサーバーとプリンタサーバーを構築する(その 1) OS のインストールと初期設定

どうも,筆者です.

2017 年 1 月頃に,「Raspberry Pi 3 Model B」を購入した.今回は,CUPS と Samba を導入し,ファイルサーバーとプリンタサーバーを構築しようと思う.

購入した Raspberry Pi

購入したラズパイは,以下のものだ.ついでに,SD と電源アダプターも購入した.

Raspberry Pi3 Model B

SD カード

電源アダプター

これらを一式揃えて,1 万円以内に収まった.後は,キーボード,マウス,HDMI ケーブル,LAN ケーブルと,必要なものを家の中からかき集めて,他の方のサイトを参考にしながら,セットアップを行った.

OS のインストール

使用する OS は,「RASPBIAN JESSIE」を選び,「DD for Windows」で OS のインストールを行った.この辺は,別の方のサイトを参考にしたので,詳しくはそちらを見て欲しい. Raspberry Pi 3 Model B をインストールしてSSH接続できるようにしてみる

初期設定

上のサイトは,CUI がメインだったので,GUI がメインの以下のサイトの「Raspi-configセットアップ」を参考にしながら,設定を行った. Raspberry Pi 3でRaspbian Jessieをセットアップする方法

まず,パスワードの設定と解像度の設定を行った.

sudo passwd pi

解像度は,テレビ出力をしていたので,設定を行う必要があった.PC のモニタなら,設定する必要はないかも. 32 インチのテレビでは,以下のように設定すると綺麗に出力された.

sudo vi /boot/config.txt

# uncomment to force a specific HDMI mode (this will force VGA)
hdmi_group=1
hdmi_mode=5

設定後,システムのアップデートと firmware のアップデートを行うために,以下のコマンドを実行した. また,良く使うエディタ,vim と emacs24 をインストールした.この段階では,まだ有線 LAN を使用している.

sudo apt-get update
sudo apt-get upgrade
sudo rpi-update
sudo apt-get install -y vim
sudo apt-get install -y emacs24
sudo reboot

アップデートは終わったが,個人的に,テレビで操作をし続けるのは大変なため,ssh で遠隔ログインをして操作が行えるように,設定を行う.また,無線 LAN を利用したいので,有線 LAN から無線 LAN に切り替える.

まず,ssh でログインする際の IP アドレスを固定する.設定ファイルは,「/etc/dhcpcd.conf」,「/etc/network/interfaces」,「/etc/wpa_supplicant/wpa_supplicant.conf」を弄ればよいらしいので,順番に編集していく.

ここでは,IP アドレスとして,192.168.33.12 を使用し,ルーターDNS は,192.168.33.1 を設定するものとする.「/etc/dhcpcd.conf」をエディタで開き,最後に以下を追加する.

interface wlan0
static ip_address=192.168.33.12
static routers=192.168.33.1
static domain_name_servers=192.168.33.1

次に,「/etc/network/interfaces」の設定を行う.最終的に,中身は以下のようになった.

# interfaces(5) file used by ifup(8) and ifdown(8)                                                                       
# Please note that this file is written to be used with dhcpcd
# For static IP, consult /etc/dhcpcd.conf and 'man dhcpcd.conf'

# Include files from /etc/network/interfaces.d:
source-directory /etc/network/interfaces.d

auto lo
iface lo inet loopback

iface eth0 inet manual

allow-hotplug wlan0
iface wlan0 inet manual
    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

最後に,「/etc/wpa_supplicant/wpa_supplicant.conf」の設定を行う.これは,ルーター側の設定となるので,個人ごとで異なる.

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=JP

network={
    ssid="接続先のSSID"
    psk="設定しているパスワード"
    key_mgmt=暗号化方法
}

一通り設定が終わったら,再起動をして正しく動作するか確認する.

次回

これで,一通り初期設定は終わったので,次は,CUPS と Samba のインストールと設定を行う.ドライバーのインストールにかなり苦労した.

ガウスの消去法(Fortran 自由形式)

Fortran90 の自由形式に関して

どうも,筆者です.何度同じ記事書くんだ?って感じだが,どうも自分が扱っていた Fortran の記述方法は古いらしい. 無料のコンパイラがあることを含めると,Fortran 90/95 の自由形式(free format)が主流らしい.Fortran 2003/2008 とかもあるらしい.

という事で,Fortran 90/95 の自由形式で記述する練習を兼ねてプログラムを書き直した.また,配列の使い方も何となく理解してきた.もっとも,同じプログラムを違う形式で書き換えているだけなので,動作は同じである.

プログラム

まず,ガウスの消去法を行う subroutine を示す.モジュールなるものを使ってみたりした.

! ====================
! Gaussian elimination
! ====================
!23456789|123456789|123456789|123456789|123456789|123456789|123456789|123456789|123456789|123456789
!        1         2         3         4         5         6         7         8         9
module mdlGaussElim
  implicit none
  private
  public :: GaussianElimination
  real(8), parameter :: eps_default = real(1e-10, 8)

  contains

  ! =================================
  ! ガウスの消去法
  !
  ! A: n × n の係数行列,A(row, col)
  ! b: n 次元右辺ベクトル,b(row)
  ! =================================
  subroutine GaussianElimination(A, b, mineps)
    ! 引数
    real(8), intent(inout) :: A(:, :), b(:)
    real(8), intent(in), optional :: mineps

    ! 局所変数
    integer(4) :: n, i, id, pivot
    real(8) :: val, diag, weight, use_eps
    n = size(A, 1)

    ! 許容誤差の確認
    use_eps = eps_default
    if (present(mineps)) then
      use_eps = mineps
    end if

    if (n /= size(A, 2)) then
      write(*, '("A is not square matrix")')
      return
    end if

    ! ================
    ! 部分ピボット選択
    ! ================
    do i = 1, n - 1
      id = maxloc(abs(A(i:n, i)), 1)

      ! 対角要素が最大でない場合
      if (id /= 1) then
        pivot = id + i - 1

        ! 入れ替えを行う
        do id = 1, n
          val = A(i, id)
          A(i, id) = A(pivot, id)
          A(pivot, id) = val
        end do
        val = b(i)
        b(i) = b(pivot)
        b(pivot) = val
      end if

      ! ========
      ! 前進消去
      ! ========
      diag = A(i, i)

      if (abs(diag) < use_eps) then
        write(*, '("Error: diagonal component is less than", G15.7)') use_eps
        return
      end if

      do id = i + 1, n
        weight = A(id, i) / diag
        A(id, i:n) = A(id, i:n) - weight * A(i, i:n)
        b(id) = b(id) - weight * b(i)
      end do
    end do

    ! ========
    ! 後退代入
    ! ========
    b(n) = b(n) / A(n, n)
    do i = n - 1, 1, -1
      id = i + 1
      val = b(i) - sum(A(i, id:n) * b(id:n))
      b(i) = val / A(i, i)
    end do

    return
  end subroutine GaussianElimination
end module mdlGaussElim

次に,main routine を示す.

! ============
! main routine
! ============
!23456789|123456789|123456789|123456789|123456789|123456789|123456789|123456789|123456789|123456789
!        1         2         3         4         5         6         7         8         9

program main
  use mdlGaussElim
  implicit none

  character(32) :: fmtstr, fname
  integer(4) :: n, i, ioerr
  real(8), allocatable :: A(:, :), b(:)

  ! ======================
  ! === 引数のチェック ===
  ! ======================
  if (iargc() /= 1) then
    call getarg(0, fname)
    write(*, '("Usage: ", a, "[data file name]")') fname
    stop
  else
    ! ======================
    ! === 引数の読み込み ===
    ! ======================
    call getarg(1, fname)
  end if

  ! ========================
  ! === ファイルオープン ===
  ! ========================
  open(10, file = fname, status = 'old', iostat = ioerr)

  if (ioerr /= 0) then
    write(*, '("Error: ", a, " cannot open")') fname
    stop
  end if

  ! ====================================
  ! === ファイルからデータを読み込む ===
  ! ====================================
  read(10, *) n

  allocate(A(1:n, 1:n), b(1:n))
  write(fmtstr, '("(", i0, "(E20.13), 3X, E20.13)")') n

  do i = 1, n
    read(10, *, iostat = ioerr) A(i, 1:n), b(i)

    if (ioerr /= 0) exit
  end do
  close(unit = 10)

  ! ============================
  ! === ガウスの消去法を行う ===
  ! ============================
  call GaussianElimination(A, b)

  ! ============
  ! === 出力 ===
  ! ============
  write(*, '(E20.13)') (b(i), i = 1, n)

  deallocate(A, b)

  stop
end program main

そして,最後に Makefile である.

FC := gfortran
FFLAG := -O2
PROG := gaussSolver
SRCS := gaussianElimination.f90 mainRoutine.f90

all: $(PROG)

$(PROG): $(SRCS)
  $(FC) -o $@ $(FFLAG) $^

.PHONY: clean
clean:
  rm -f $(PROG) *.mod

ファイル読み込みは,以前と同様で,最初に次元数,次に係数行列,右辺ベクトルという並びのものを用意する.

ガウスの消去法(MATLAB バージョン)

どうも,筆者です.部分ピボット選択付きのガウスの消去法を C 言語と Fortran で書いてきたが,MATLABスクリプトを探している人もいた.

目的

なので,今回は,MATLAB 用にガウスの消去法を書き直すことにした.これも久しぶりに使うので,もっと効率化できる部分があるかもしれない.まぁ,MATLAB 用にわざわざ 1 から書く人はいない(組み込みの関数を使うべきである)と思うので,勉強用として考えれば,速度と精度はそこまで必要にならないだろう.

C 言語と Fortran は,以下でコードを公開している.

workspacememory.hatenablog.com workspacememory.hatenablog.com

MATLAB 用のコード

MATLAB 用に書いていて気付いたが,Fortran も同様なコードに落とせるのではないか(確か,ベクトル演算できたよなぁ).

%===================================%
%                                   %
% gaussSolver                       %
%                                   %
% A: coefficient matrix, A(row,col) %
% b: right side vector,  b(row)     %
%                                   %
% return: solution vector x         %
%===================================%
function [x] = gaussSolver(A,b)
    [n, ~] = size(A);

    for i = 1:(n - 1)
        % i 列目のうち,最大のものを探す
        [~, id] = max(abs(A(i:n, i)));

        if id ~= 1
            pivot = id + i - 1;
            % 行の入れ替え
            tmpVec = A(i, :);
            A(i, :) = A(pivot, :);
            A(pivot, :) = tmpVec;

            % 右辺ベクトルの入れ替え
            tmpScalar = b(i);
            b(i) = b(pivot);
            b(pivot) = tmpScalar;
        end
        diagVal = A(i, i);

        % 対角成分が eps よりも小さい場合は,エラー処理
        if (abs(diagVal) < eps)
            error('Error: diagonal component is less than eps=%.15e\n', eps);
        end

        % ========
        % 前進消去
        % ========
        for row = (i + 1):n
            idList = i:n;
            weight = A(row, i) / diagVal;
            A(row, idList) = A(row, idList) - weight * A(i, idList);
            b(row) = b(row) - weight * b(i);
        end
    end

    % ========
    % 後退代入
    % ========
    b(n) = b(n) / A(n, n);
    for row = (n - 1):(-1):1
        idList = (row + 1):n;
        b(row) = (b(row) - A(row, idList) * b(idList)) / A(row, row);
    end
    x = b;
end

動作確認

筆者は,MATLAB を持っていないので,Octave を利用して,検証を行った.その際,テストスクリプトとして,以下のようなものを作成した.

n = 10;
A = rand(n);
xexact = (1:n)';
b = A * xexact;

xhat = gaussSolver(A, b)

これを,Octave で実行したところ,真の解の近似解が得られたので,正しく動作していると考えられる.